ios - UIGraphicsGetImageFromCurrentImageContext 导致导航 Controller 返回动画断断续续

标签 ios swift uinavigationcontroller uiimageview

我有一个 UINavigationController,其中包含 View Controller A。我将其推送到 View Controller B。 View Controller B 包含一个 ImageView ,该 View 通过以下代码异步加载其图像:

let ss = MKMapSnapshotter(options: options)

ss!.start { (snapshot, error) in

    guard let snappy = snapshot else {
        return
    }

    let snap = snappy.image

    ...
    // create a pinView which gets combined with the snapshot image
    ...

    UIGraphicsBeginImageContextWithOptions(snap.size, false, snap.scale)

    snap.draw(at: CGPoint(x: 0, y: 0))

    let rect = CGRect(origin: CGPoint(x: self.frame.width/2 - pinView.frame.width/2, y: self.frame.height/2 - pinView.frame.height/2), size: CGSize(width: pinView.frame.width, height: pinView.frame.height))

    pinView.drawHierarchy(in: rect, afterScreenUpdates: true)

    let finalSnap = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    self.snapshotView.image = finalSnap
}

每当我从 VC B 按下后退按钮返回 VC A 时,如果图像尚未完成渲染,则弹出动画会非常不稳定/缓慢/断断续续。我对行进行了注释,以查看哪一行导致了缓慢,并且它发生在 UIGraphicsGetImageFromCurrentImageContext 上(如果我在调用该行之前按<返回,则会发生此问题)

我尝试通过 ss.cancel() 取消 MKMapSnapshotter,我尝试将 UIGraphics 上下文部分包装在 DispatchQueue.main.async{} 中,并且我还尝试设置在 viewWillDisappear 期间设置一个标志,并检查 isMovingFromParentViewController 是否告诉它不要运行该行,但由于图像创建是异步的并立即触发,因此无法保证它已经加载。他们都没有为我工作过。

有谁知道如何正确地告诉我的 VC B 停止所有进程,或者我如何解决这个问题?如果我让快照图像完全加载,则不会发生此问题,但我不能指望会发生这种情况。

最佳答案

根据 @rmaddy 的建议,我将图像创建移至后台线程。然而,我确实遇到了一个问题,即无法在后台线程上调用 drawHierarchy(in: rect, afterScreenUpdates: true) ,因此我更改了创建 pinView 的方式,以便我可以只需通过在矩形中绘制将 UIImage 添加到我当前的图形上下文即可。

最终的代码是这样的:

DispatchQueue.global(qos: .background).async {
    UIGraphicsBeginImageContextWithOptions(snap.size, false, snap.scale)

    snap.draw(at: CGPoint(x: 0, y: 0))

    let rect = CGRect(origin: CGPoint(x: self.frame.width/2 - pinView.frame.width/2, y: self.frame.height/2 - pinView.frame.height/2), size: CGSize(width: pinView.frame.width, height: pinView.frame.height))

    pinView.image?.draw(in: rect) // changed this to allow background thread execution

    let finalSnap = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    // main thread image view assignment    
    DispatchQueue.main.async {
        self.snapshotView.image = finalSnap
    }          
}

关于ios - UIGraphicsGetImageFromCurrentImageContext 导致导航 Controller 返回动画断断续续,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47045023/

相关文章:

ios - 在 Swift 中将日期从 GMT+1 转换为 UTC 时出现混淆

ios - 无法在模拟器上运行的功能(iOS 开发)

ios - 线程 1 :EXC_BAD_ACCESS (code=1, 地址=0x14)

ios - 为了 "reload"应用程序,注销功能应该是什么样的?

ios - 如何在 View Controller 时间轴中跳回两步?

ios - 当我从另一个 Mainstoryboard 添加 containerViews 时,导航不起作用?

ios - 使用 SwiftUI 呈现多个模式表

swift - CryptoSWIFT-表达式类型在没有更多上下文的情况下不明确

swift - swift .contains(element :_) method work? 如何

ios - UIStatusBar 风格与 UINavigationBar 一致