Load a remote image using MTKTextureLoader

我只是一个虾纸丫 提交于 2019-12-11 08:42:31

问题


I'm trying to load a remote image into a MTLTexture with this code,

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

If the URL comes from a Bundle resource, then it works, e.g.

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

However, it fails if I pass something like this,

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

With this error,

Could not find resource bla_bla.jpg at specified location.

If I copy-paste the url into the browser, the image is displayed without problems (plus I've implemented the same thing in Android using OpenGL and the image renders OK).

I've added my domain to the Info.plist, and I can load things like Json from that location. It's just the texture loader being funny... Info.plist looks like this,

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

The MTKTextureLoader documentation does not mention anything about external URLs, but could it be that it only handles internal resources?


回答1:


Here's an example of how to extend MTKTextureLoader to load remote URLs, which are not supported by the default implementation.

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()
    }
}

Ideally, you would implement your own caching mechanism to avoid repeatedly downloading the same image, but this should get you started.



来源:https://stackoverflow.com/questions/42459312/load-a-remote-image-using-mtktextureloader

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!