简体   繁体   中英

Swift Error Domain=NSURLErrorDomain Code=-999 “cancelled”

I've been trying to figure out this one for a bit now, so while trying to load an image remotely and I am running into the domain error. So here is what I get from the console:

Task <95AAB48F-8670-4E1D-AA29-21D47E0EE069>.<5> finished with error [-999] Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLStringKey=http://gba.ergoware.io/cache/content/topstory/ergo_news_01.png, NSLocalizedDescription=cancelled, NSErrorFailingURLKey=http://gba.ergoware.io/cache/content/topstory/ergo_news_01.png}

Here is the class calling the image from the site:

// MARK: Remote Image Loading
class ImageLoader: ObservableObject {

    @Published var image: UIImage?
    private let url: URL
    private var cancellable: AnyCancellable?
    private var cache: ImageCache?

    init(url: URL, cache: ImageCache? = nil) {
        self.url = url
        self.cache = cache
    }

    func load() {
        if let image = cache?[url] {
            self.image = image
            return
        }

        cancellable = URLSession.shared.dataTaskPublisher(for: url)
        .map { UIImage(data: $0.data) }
        .replaceError(with: nil)
        .handleEvents(receiveOutput: { [weak self] in self?.cache($0) })
        .receive(on: DispatchQueue.main)
        .assign(to: \.image, on: self)
    }

    private func cache(_ image: UIImage?) {
        image.map { cache?[url] = $0 }
    }

    func cancel() {
        cancellable?.cancel()
    }
}

struct AsyncImage<Placeholder: View>: View {
    @ObservedObject private var loader: ImageLoader
    private let placeholder: Placeholder?

    init(url: URL, placeholder: Placeholder? = nil, cache: ImageCache? = nil) {
        loader = ImageLoader(url: url, cache: cache)
        self.placeholder = placeholder
    }

    var body: some View {
        image
            .onAppear(perform: loader.load)
            .onDisappear(perform: loader.cancel)
    }

    private var image: some View {
        Group {
            if loader.image != nil {
                Image(uiImage: loader.image!)
                    .resizable()
            } else {
                placeholder
            }
        }
    }
}

protocol ImageCache {
    subscript(_ url: URL) -> UIImage? { get set }
}

struct TemporaryImageCache: ImageCache {
    private let cache = NSCache<NSURL, UIImage>()

    subscript(_ key: URL) -> UIImage? {
        get { cache.object(forKey: key as NSURL) }
        set { newValue == nil ? cache.removeObject(forKey: key as NSURL) : cache.setObject(newValue!, forKey: key as NSURL) }
    }
}

// MARK: Image Cache

struct ImageCacheKey: EnvironmentKey {
    static let defaultValue: ImageCache = TemporaryImageCache()
}

extension EnvironmentValues {
    var imageCache: ImageCache {
        get { self[ImageCacheKey.self] }
        set { self[ImageCacheKey.self] = newValue }
    }
}

So how this is set up is, my interface calls the images, and for certain images like the user's profile image or achievement badges, the image will be cached during the session to prevent multiple request for the same image and cutting down on load time and server traffic in the long run.

Any help would be appreciated! Thanks!

This error happens due to attached .onDisappear to placeholder, so when real image has loaded and assigned to published property the view is refreshed, so placeholder is removed, so cancel is called on completed but not yet finished data task, so the log.

Here is simplest fix. Tested with Xcode 11.4 / iOS 13.4.

var body: some View {
    image
        .onAppear(perform: loader.load)
        .onDisappear {
            if self.loader.image == nil { // cancel only if not loaded yet
                self.loader.cancel()
            }
        }
}

Hello, Try to Allow Arbitrary loads in info.plist file Learn More by checking out this answer: https://stackoverflow.com/a/40299837/7443052

Regards, David

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM