# iOS samples (Keychain, API key, offline queue) Use with [docs/ios/README.md](../ios/README.md). These snippets are **reference only** (not a full Xcode project). ## Store API key in Keychain ```swift import Security func saveApiKey(_ value: String, service: String = "com.smoa.api") throws { let data = Data(value.utf8) let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: "apiKey", kSecValueData as String: data ] SecItemDelete(query as CFDictionary) let status = SecItemAdd(query as CFDictionary, nil) guard status == errSecSuccess else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(status)) } } func loadApiKey(service: String = "com.smoa.api") -> String? { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: "apiKey", kSecReturnData as String: true ] var out: AnyObject? guard SecItemCopyMatching(query as CFDictionary, &out) == errSecSuccess, let data = out as? Data else { return nil } return String(data: data, encoding: .utf8) } ``` ## Simple offline sync queue (UserDefaults + retry) Persist operation JSON strings; on `NWPathMonitor` satisfied, POST to `/api/v1/...` with `URLSession` and remove on success. ## Face ID / Touch ID Wrap Keychain access with `LAContext().evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, …)` before reading sensitive items. ## Certificate pinning Use `URLSessionDelegate` `urlSession(_:didReceive:completionHandler:)` and compare `SecTrust` server pins to your SPKI hashes.