iOS 11中HTTPCookie.cookies返回空数组问题求助
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:
1. Verify the Server’s Set-Cookie Header Format
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/pathattributes (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 zzzlikeWed, 21 Oct 2015 07:28:00 GMT) - Unescaped special characters in the cookie value or name
2. Set Cookie Accept Policy Before Making Requests
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)") } }
4. Check for Multiple Set-Cookie Headers
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




