首页 > 解决方案 > Kingfisher 在 SessionDelegate.remove() 上崩溃

问题描述

我们正在使用 Kingfisher 为我们的 iOS 应用程序下载图像,在尝试取消下载任务时我遇到了很多崩溃

EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000020

Crashed: com.apple.main-thread
0  CFNetwork                      0x18436b058 HTTPParser::HTTPParser(__CFAllocator const*, HTTPParserClient*, HTTPParser*) + 44
1  CFNetwork                      0x18424b27c HTTPMessage::commonInitialization(unsigned char, HTTPMessage const*) + 212
2  CFNetwork                      0x18424b27c HTTPMessage::commonInitialization(unsigned char, HTTPMessage const*) + 212
3  CFNetwork                      0x18424b41c HTTPMessage::HTTPMessage(HTTPMessage const*) + 112
4  CFNetwork                      0x18436c1dc HTTPRequestMessage::HTTPRequestMessage(HTTPRequestMessage const*) + 36
5  CFNetwork                      0x18422a74c HTTPRequest::HTTPRequest(HTTPRequest const*) + 24
6  CFNetwork                      0x18422ce8c URLRequest::initialize(URLRequest const*, unsigned char) + 656
7  CFNetwork                      0x1841e2bd8 _createRequestCopy(__CFAllocator const*, _CFURLRequest const*, unsigned char) + 152
8  CFNetwork                      0x184355de0 -[NSURLRequest mutableCopyWithZone:] + 44
9  libswiftFoundation.dylib       0x105a95a0c URLRequest.init(_bridged:) + 77948
10 libswiftFoundation.dylib       0x105a99344 static URLRequest._unconditionallyBridgeFromObjectiveC(_:) + 92596
11 Kingfisher                     0x102fb5788 SessionDelegate.remove(_:) + 93 (SessionDelegate.swift:93)
12 Kingfisher                     0x102fb566c closure #1 in SessionDelegate.add(_:url:callback:) + 1000 (<compiler-generated>:1000)
13 Kingfisher                     0x102fb9eb0 partial apply for thunk for @escaping @callee_guaranteed (@guaranteed SessionDelegate, @unowned Int, @in_guaranteed SessionDataTask.TaskCallback) -> () + 84 (<compiler-generated>:84)
14 Kingfisher                     0x102f46734 specialized closure #1 in Delegate.delegate<A>(on:block:) + 96 (<compiler-generated>:96)
15 Kingfisher                     0x102fb9f34 partial apply for specialized closure #1 in Delegate.delegate<A>(on:block:) + 28 (<compiler-generated>:28)
16 Kingfisher                     0x102fb14d0 SessionDataTask.cancel(token:) + 356 (<compiler-generated>:356)
17 Kingfisher                     0x102f6de18 DownloadTask.cancel() + 74 (ImageDownloader.swift:74)
18 MyApp                          0x1011e55f4 UIImageView.cancel() + 4310799860 (<compiler-generated>:4310799860)
...
...

例如,我们在重用表格视图中的单元格时调用此方法,在此我们取消对不再可见的单元格的请求。我们在 UIImageView 上创建了一个扩展来定义方便的方法,例如cancel()

在某些情况下,我似乎在服务器取消 HTTP 请求时应用程序崩溃,但这并不是唯一一次发生。

这是我们所做的示例代码:

func fetchImage(fromURL url: URL, completion: @escaping (UIImage?, NSError?) -> Void) -> MyAppDownloadTask {    
    
    let resource = ImageResource(downloadURL: url)
    let options: KingfisherOptionsInfo = [.targetCache(cache), .downloader(downloader)]

    let task = KingfisherManager.shared.retrieveImage(with: resource, options: options, progressBlock: nil) { result in

    switch result {
        case .success(let value):
            completion(value.image, nil)
        case .failure(let error):
            completion(nil, error.toNSError())
    }
    }

    return MyAppDownloadTask(task: task)
}

private class MyAppDownloadTask {

    let task: DownloadTask? // KingFisher task

    init(task: DownloadTask?) {
        self.task = task
    }

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

在我们的集合视图中重用单元格时,我们调用 cancel 方法:

override func prepareForReuse() {
    super.prepareForReuse()
    downloadTask.cancel()
}

标签: iosswiftkingfisher

解决方案


推荐阅读