未调用iOS URLSession委托方法(session、dataTask、willCacheResponse、proposedResponse)

kupeojn6  于 2023-04-22  发布在  iOS
关注(0)|答案(1)|浏览(121)

我需要API响应缓存更长的时间。因此,我试图修改API响应的“max-age”头。
但是

urlSession(_ session: URLSession, 
          dataTask: URLSessionDataTask, 
          willCacheResponse proposedResponse: CachedURLResponse, 
          completionHandler: @escaping (CachedURLResponse?
) -> Void)

方法不会被调用来执行此操作。
API客户端类代码:

public class APIClient: NSObject, URLSessionDelegate {
    var endPoint: String!
    var urlSession: URLSession!
    
    public init(urlSession: URLSession = .shared) {
        super.init()
        self.endPoint = endPoint
        
        let sessionConfiguration: URLSessionConfiguration = URLSessionConfiguration.default
            sessionConfiguration.requestCachePolicy = .returnCacheDataElseLoad
            sessionConfiguration.urlCache = .shared
    
            self.urlSession = URLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: nil)
    
    }
    
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Void) {
    
        if dataTask.currentRequest?.cachePolicy == .useProtocolCachePolicy {
            let newResponse = proposedResponse.response(withExpirationDuration: 60)
            completionHandler(newResponse)
        }else {
            completionHandler(proposedResponse)
        }
    }
    
    private func dispatch<ReturnType: Decodable>(request: URLRequest) -> AnyPublisher<ReturnType, NetworkError> {
        let url = request.url // For troubleshooting only
        return urlSession
            .dataTaskPublisher(for: request)
        
        // Map on Request response
            .tryMap({ data, response in
                return data
            })
            .decode(type: ReturnType.self, decoder: JSONDecoder())
            .mapError { error in
            }
            .eraseToAnyPublisher()
    }
}

API调用:

func makeAPICall() -> AnyPublisher<ContentConfigResponseModel, NetworkError> {
    var request = // create request data
    let apiClient = APIClient(endPoint: request.path)
    return apiClient.dispatch(request)
}

我已经尝试了多个cachePolicy。根据一些建议,我已经尝试实现

func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse) async -> URLSession.ResponseDisposition {
    return URLSession.ResponseDisposition.allow
}
bxjv4tth

bxjv4tth1#

不调用委托方法通常有三个原因:

  • delegatenil:已dealloc或未设置(根本未设置,或未在正确示例上设置)
  • 委托方法未正确编写:签名不一样,方法也不一样
  • 委托对象未设置为与协议兼容

你的问题是最后一个。
urlSession(_:dataTask:willCacheResponse:completionHandler:)是一个URLSessionDataDelegate方法。
它是URLSessionDelegate的“子协议”。
APIClient只符合URLSessionDelegate,而不是URLSessionDataDelegate,即使它实现了具有相同签名的方法。
所以public class APIClient: NSObject, URLSessionDelegate应该是public class APIClient: NSObject, URLSessionDelegate, URLSessionDataDelegate
我们也可以查看URLSession源代码,指出它:

if let delegate = task.session.delegate as? URLSessionDataDelegate {
    delegate.urlSession(task.session as! URLSession, dataTask: task, willCacheResponse: cacheable) { (actualCacheable) in
        if let actualCacheable = actualCacheable {
            cache.storeCachedResponse(actualCacheable, for: task)
        }
    }
} else {
    cache.storeCachedResponse(cacheable, for: task)
}

你没有通过测试if let delegate = task.session.delegate as? URLSessionDataDelegate

相关问题