ios - 如何异步绘制InRect

标签 ios swift asynchronous grand-central-dispatch

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

一旦我的函数返回图像,我想将其绘制在正确位置的 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)
                }
            }
        }
    }
}

我收到这个错误:

<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>

谁能给我一些关于如何异步检索和绘制图像的提示?

最佳答案

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

如果你确实使用了drawRect,当然不要在其中加载数据。 Apple 明确指出您应该绘图,而不是在那里做任何其他事情。而且您当然不想在那里启动异步任务,这只会导致灾难。预先加载数据,将其存储在某处,然后在 drawRect 中进行绘图。如果您在用户四处移动时加载数据,请在用户移动时加载数据,而不是在您绘制时加载。您可能需要在实际加载图像时使 rects 无效,以便随后调用 drawRect。但同样,不要使用 drawRect。只需添加/删除 View /层。

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

关于ios - 如何异步绘制InRect,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34817632/

相关文章:

ios - Crashlytics 中的 EXC_BREAKPOINT 0x00000000e7ffdefe

ios - 如何检查 Firebase 中是否存在用户名

javascript - 将 bcrypt 哈希/验证函数转换为异步函数

javascript - 如何解决 node.js 中可变数量的 promise

ios - 我无法在 Swift 3 中枚举 NSAttributed Text

ios - 更新到 Xcode 10.2 后 : Invalid Toolchain error when trying to submit app to App Store

android - 在 Angular 的 UI 中显示图像后将图像发送到服务器

swift - 开发 macOS 的辅助应用程序,apiDisabled

ios - 具有相同参数类型的 Swift 初始化器

c# - 确保取消某些任务