You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS 11中HTTPCookie.cookies返回空数组问题求助

iOS 11 HTTPCookie.cookies() Returns 0 Elements: Troubleshooting Tips

Hey there, sorry to hear you’ve spent over two hours stuck on this cookie storage issue—iOS 11 introduced some stricter cookie handling rules that often trip up code that worked perfectly on older versions. Let’s walk through actionable fixes to get this sorted:

iOS 11 enforces stricter compliance with RFC cookie standards compared to earlier iOS versions. First, print out the raw Set-Cookie header returned by your server to check for invalid formatting:

if let responseheaderFields = response.response?.allHeaderFields as? [String : String] {
    print("Raw Set-Cookie Header: \(responseheaderFields["Set-Cookie"] ?? "No Set-Cookie header found")")
}

Look for common issues that iOS 11 rejects:

  • Missing or incorrectly formatted domain/path attributes (iOS 11 won’t parse cookies without these if the URL doesn’t explicitly match)
  • Malformed expiration dates (must use the format EEE, dd MMM yyyy HH:mm:ss zzz like Wed, 21 Oct 2015 07:28:00 GMT)
  • Unescaped special characters in the cookie value or name

iOS 11 may ignore the cookieAcceptPolicy if you set it only after receiving the response. Move this setting to your app’s launch phase to ensure it’s active when the request is sent:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    HTTPCookieStorage.shared.cookieAcceptPolicy = .always
    // Rest of your initialization code
    return true
}

3. Manually Parse and Create Cookies (Fallback for Strict iOS 11 Rules)

If automatic parsing fails, manually extract cookie properties from the Set-Cookie header and create the cookie yourself. This bypasses iOS 11’s strict automatic parsing logic:

if let response = response.response, let url = response.request?.url, let allHeaders = response.allHeaderFields as? [String: String] {
    let cookieStorage = HTTPCookieStorage.shared
    guard let setCookieHeader = allHeaders["Set-Cookie"] else { return }
    
    // Split the header into individual cookie components
    let cookieParts = setCookieHeader.split(separator: ";").map { $0.trimmingCharacters(in: .whitespaces) }
    var cookieProps = [HTTPCookiePropertyKey: Any]()
    
    for part in cookieParts {
        let keyValuePair = part.split(separator: "=", maxSplits: 1).map(String.init)
        guard keyValuePair.count == 2 else { continue }
        let key = keyValuePair[0].lowercased()
        let value = keyValuePair[1]
        
        switch key {
        case "name": cookieProps[.name] = value
        case "value": cookieProps[.value] = value
        case "domain": cookieProps[.domain] = value
        case "path": cookieProps[.path] = value
        case "expires":
            // Handle strict date formatting required by iOS 11
            let dateFormatter = DateFormatter()
            dateFormatter.locale = Locale(identifier: "en_US_POSIX")
            dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss zzz"
            if let expiresDate = dateFormatter.date(from: value) {
                cookieProps[.expires] = expiresDate
            }
        case "max-age":
            if let maxAge = Int(value) {
                cookieProps[.maximumAge] = maxAge
            }
        case "secure": cookieProps[.secure] = true
        case "httponly": cookieProps[.HTTPOnly] = true
        default: break
        }
    }
    
    // Fill in missing domain/path with values from the request URL
    if cookieProps[.domain] == nil {
        cookieProps[.domain] = url.host
    }
    if cookieProps[.path] == nil {
        cookieProps[.path] = "/"
    }
    
    // Create and store the cookie
    if let customCookie = HTTPCookie(properties: cookieProps) {
        cookieStorage.setCookie(customCookie)
        Application.sessionCookie = customCookie
        print("Manually created cookie: \(customCookie)")
    }
}

iOS 11 handles multiple Set-Cookie headers differently than older versions. If your server sends multiple cookies, the allHeaderFields might store them as an array instead of a comma-separated string. Adjust your parsing to handle this case:

if let allHeaders = response.response?.allHeaderFields {
    var setCookieStrings = [String]()
    for (key, value) in allHeaders {
        guard let keyStr = key as? String, keyStr.lowercased() == "set-cookie" else { continue }
        if let valueStr = value as? String {
            setCookieStrings.append(valueStr)
        } else if let valueArray = value as? [String] {
            setCookieStrings.append(contentsOf: valueArray)
        }
    }
    // Process each Set-Cookie string individually here
}

5. Validate the Request URL

Ensure the response.request?.url is valid (includes a scheme like http/https, correct host, etc.). iOS 11 won’t parse cookies for URLs with missing or invalid components. Print the URL to confirm:

print("Request URL: \(response.request?.url ?? URL(string: "invalid")!)")

Start with checking the raw Set-Cookie header—most of the time, the issue is a minor formatting detail that iOS 11 now rejects. If that doesn’t work, the manual parsing method should reliably create the cookie you need.

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

火山引擎 最新活动