UIGraphicsGetImageFromCurrentImageContext导致不稳定的导航控制器返回动画

时间:2017-10-31 21:48:10

标签: ios swift uinavigationcontroller uiimageview

我有一个带有View Controller A的UINavigationController。我将它推到View Controller B. View Controller B包含一个Image 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上(如果我按下< Back在该行被调用之前,则会出现此问题)

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

有没有人能够深入了解如何正确告诉我的VC B停止所有进程,或者我如何解决这个问题?如果我让快照图像完全加载,那么这个问题就不会发生,但我不能指望这种情况发生。

1 个答案:

答案 0 :(得分:0)

根据@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
    }          
}