yumi-flutter/ios/Runner/AppDelegate.swift
2026-05-07 10:06:02 +08:00

111 lines
3.3 KiB
Swift

import Flutter
import Security
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
registerDurableAuthStorageChannel()
registerMobileContextChannel()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func registerMobileContextChannel() {
guard let controller = window?.rootViewController as? FlutterViewController else {
return
}
let channel = FlutterMethodChannel(
name: "com.org.yumiparty/mobile_context",
binaryMessenger: controller.binaryMessenger
)
channel.setMethodCallHandler { call, result in
switch call.method {
case "getTimeZoneIdentifier":
result(TimeZone.current.identifier)
default:
result(FlutterMethodNotImplemented)
}
}
}
private func registerDurableAuthStorageChannel() {
guard let controller = window?.rootViewController as? FlutterViewController else {
return
}
let channel = FlutterMethodChannel(
name: "com.org.yumiparty/durable_auth_storage",
binaryMessenger: controller.binaryMessenger
)
channel.setMethodCallHandler { [weak self] call, result in
guard
let self,
let args = call.arguments as? [String: Any],
let key = args["key"] as? String
else {
result(FlutterError(code: "bad_args", message: "Missing key", details: nil))
return
}
switch call.method {
case "write":
guard let value = args["value"] as? String else {
result(FlutterError(code: "bad_args", message: "Missing value", details: nil))
return
}
self.writeKeychainValue(value, key: key)
result(nil)
case "read":
result(self.readKeychainValue(key: key))
case "delete":
self.deleteKeychainValue(key: key)
result(nil)
default:
result(FlutterMethodNotImplemented)
}
}
}
private func keychainQuery(key: String) -> [String: Any] {
[
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: "com.org.yumiparty.durable_auth_storage",
kSecAttrAccount as String: key
]
}
private func writeKeychainValue(_ value: String, key: String) {
deleteKeychainValue(key: key)
guard let data = value.data(using: .utf8) else {
return
}
var query = keychainQuery(key: key)
query[kSecValueData as String] = data
query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
SecItemAdd(query as CFDictionary, nil)
}
private func readKeychainValue(key: String) -> String? {
var query = keychainQuery(key: key)
query[kSecReturnData as String] = true
query[kSecMatchLimit as String] = kSecMatchLimitOne
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
guard
status == errSecSuccess,
let data = result as? Data
else {
return nil
}
return String(data: data, encoding: .utf8)
}
private func deleteKeychainValue(key: String) {
SecItemDelete(keychainQuery(key: key) as CFDictionary)
}
}