如何异步drawInRect

smn*_*mnk 0 asynchronous grand-central-dispatch ios swift

我正在尝试加载一个巨大的图像(谈论131.072x131.072像素)很好地平铺成一堆URL的256x256像素的512x512块.

一旦我的函数返回Image我想在一个正确位置的Rect中绘制它.

由于这个过程需要一段时间,我想以异步方式运行整个过程.以下是我到目前为止所尝试的内容:

override func drawRect(rect: CGRect) {
    let firstColumn = Int(CGRectGetMinX(rect) / sideLength)
    let lastColumn = Int(CGRectGetMaxX(rect) / sideLength)
    let firstRow = Int(CGRectGetMinY(rect) / sideLength)
    let lastRow = Int(CGRectGetMaxY(rect) / sideLength)

    let qos = Int(QOS_CLASS_USER_INITIATED.rawValue)
    dispatch_async(dispatch_get_global_queue(qos, 0)) { () -> Void in

        for row in firstRow...lastRow {
            for column in firstColumn...lastColumn {

                let url = NSURL(string: "https://someURL/\(row)/\(column).jpg")
                let tile = UIImage(data: NSData(contentsOfURL: url!)!)!

                let x = self.sideLength * CGFloat(column)
                let y = self.sideLength * CGFloat(row)
                let point = CGPoint(x: x, y: y)
                let size = CGSize(width: self.sideLength, height: self.sideLength)
                var tileRect = CGRect(origin: point, size: size)

                tileRect = CGRectIntersection(self.bounds, tileRect)

                dispatch_async(dispatch_get_main_queue()) {
                    tile.drawInRect(tileRect)
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到这个错误:

<Error>: CGContextRestoreGState: invalid context 0x0. Backtrace:
      <-[UIImage drawInRect:]+66>
       <_TFFFC6H1Z1DB15MyClass8drawRectFS0_FVSC6CGRectT_U_FT_T_U_FT_T_+122>
        <_TTRXFo__dT__XFdCb__dT__+39>
         <_dispatch_call_block_and_release+12>
          <_dispatch_client_callout+8>
           <_dispatch_main_queue_callback_4CF+1738>
            <__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__+9>
             <__CFRunLoopRun+2073>
              <CFRunLoopRunSpecific+488>
               <GSEventRunModal+161>
                <UIApplicationMain+171>
                 <main+109>
Run Code Online (Sandbox Code Playgroud)

任何人都可以给我一个关于如何异步检索和绘制图像的提示吗?

jca*_*ron 5

不要用drawRect.drawRect在这种情况下没有理由使用.只需使用视图,图层或SpriteKit或OpenGL ES(可能有更多选择).在前两种情况下,您可能必须根据屏幕上可见的视图部分添加/删除位和碎片,但使用标准视图/图层将获得更好的性能.Apple强烈建议不要使用drawRect.

如果你使用drawRect,当然不要在那里加载数据.Apple明确表示你应该画画,而不是在那里做任何其他事情.你肯定不想在那里开始异步任务,这只会导致灾难.事先加载数据,将其存储在某处,并在进入时进行绘图drawRect.如果您在用户移动时加载数据,请在用户移动时进行加载,而不是在绘制时进行加载.当图像实际被加载时,您可能需要使rects无效,drawRect然后调用.但同样,不要使用drawRect.只需添加/删除视图/图层即可.

我也建议不要使用NSData(contentsOfURL:).使用NSURLSession dataTask*适当的完成处理程序.这样,您的所有负载将同时发生(达到设定的限制),而不是一个接一个地发生.