You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS URLSession代理方法willCacheResponse未触发,需修改缓存max-age

问题:无法触发willCacheResponse代理方法修改缓存时长

想延长API响应的缓存时间,尝试修改max-age头,但urlSession(_:dataTask:willCacheResponse:completionHandler:)代理方法始终不被调用,无法完成修改。已经试过多种cachePolicy,还实现了异步版本的didReceive response方法,问题依旧。

现有代码

APIClient类

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 = // 创建请求数据
    let apiClient = APIClient(endPoint: request.path)
    return apiClient.dispatch(request)
}

已尝试的额外代码

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

问题原因及解决方案

1. 代理协议未正确遵守

willCacheResponse方法属于URLSessionDataDelegate协议,当前APIClient只遵守了URLSessionDelegate,系统不会回调不属于当前协议的方法。修改类的协议声明:

public class APIClient: NSObject, URLSessionDataDelegate { // 替换为URLSessionDataDelegate
    // ... 其他代码不变
}

2. 初始化方法参数错误

init方法参数定义与调用逻辑不匹配:调用时传入endPoint,但init未接收该参数,导致self.endPoint被赋值为nil,同时传入的urlSession参数未被使用。修正初始化方法:

public init(endPoint: String) { // 改为接收endPoint参数
    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)
}

3. 检查响应是否可缓存

只有当服务器返回的响应符合缓存条件时,willCacheResponse才会被触发:

  • 响应需包含有效的Cache-Control头(如public/private,且max-age大于0)
  • 响应状态码为可缓存类型(如200、203、300、301等)
  • 请求方法为GET(POST等方法默认不缓存)

4. 验证Combine Publisher的代理触发

dataTaskPublisher内部会创建URLSessionDataTask,只要session的delegate设置正确、协议遵守无误,代理方法应正常触发。若仍无效果,可尝试直接使用dataTask(with:completionHandler:)验证代理是否生效,排除Combine的影响。


内容的提问来源于stack exchange,提问作者7vikram7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:02:46