使用MTKTextureLoader加载远程图像

时间:2017-02-25 17:33:40

标签: ios metal

我尝试使用此代码将远程图像加载到MTLTexture中,

    let textureLoader = MTKTextureLoader(device: device)
    textureLoader.newTexture(withContentsOf: url, options: options) { [weak self] (texture, error) in
        if let t = texture {
            completion(t)
        } else {
            if let desc = error?.localizedDescription {
                NSLog(desc)
            }
            completion(nil)
        }
    }

如果URL来自Bundle资源,那么它可以工作,例如

let url = Bundle.main.url(forResource: name, withExtension: ext)

但是,如果我传递这样的内容,它就会失败,

let url = URL(string: "http://example.com/images/bla_bla.jpg")

出现此错误,

Could not find resource bla_bla.jpg at specified location.

如果我将网址复制粘贴到浏览器中,图片会毫无问题地展示(另外我在Android中使用OpenGL实现了相同的功能,图像呈现正常)。

我已将我的域名添加到Info.plist中,我可以从该位置加载Json之类的内容。只是纹理加载器很有趣...... Info.plist看起来像这样,

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>example.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.1</string>
        </dict>
    </dict>
</dict>

MTKTextureLoader documentation没有提及任何有关外部网址的内容,但它是否只能处理内部资源?

1 个答案:

答案 0 :(得分:3)

以下是如何扩展MTKTextureLoader以加载远程URL的示例,默认实现不支持这些URL。

extension MTKTextureLoader {
    enum RemoteTextureLoaderError: Error {
        case noCachesDirectory
        case downloadFailed(URLResponse?)
    }

    func newTexture(withContentsOfRemote url: URL, options: [String : NSObject]? = nil, completionHandler: @escaping MTKTextureLoaderCallback) {
        let downloadTask = URLSession.shared.downloadTask(with: URLRequest(url: url)) { (maybeFileURL, maybeResponse, maybeError) in
            var anError: Error? = maybeError
            if let tempURL = maybeFileURL, let response = maybeResponse {
                if let cachePath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first {
                    let cachesURL = URL(fileURLWithPath: cachePath, isDirectory: true)
                    let cachedFileURL = cachesURL.appendingPathComponent(response.suggestedFilename ?? NSUUID().uuidString)
                    try? FileManager.default.moveItem(at: tempURL, to: cachedFileURL)
                    return self.newTexture(withContentsOf: cachedFileURL, options: options, completionHandler: completionHandler)
                } else {
                    anError = RemoteTextureLoaderError.noCachesDirectory
                }
            } else {
                anError = RemoteTextureLoaderError.downloadFailed(maybeResponse)
            }
            completionHandler(nil, anError)
        }
        downloadTask.resume()
    }
}

理想情况下,您应该实现自己的缓存机制,以避免重复下载相同的图像,但这应该可以帮助您入门。