ios - 将数据从 AppDelegate 传递到 UIViewController
问题描述
如何将数据从 AppDelegate 类传递到自定义 ViewController?
import UIKit
import LocalAuthentication
class ViewController: UIViewController {
public var config: PasscodeConfig!
func GetAppDelegate(){
print("\(self.config)") /// nil %(
}
override public func viewDidLoad() {
super.viewDidLoad()
self.GetAppDelegate()
}
...
}
不幸的是,变量配置返回 - nil AppDelegate:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var appCoordinator: AppCoordinator!
var code = ""
lazy var passcode: Passcode = {
let config = PasscodeConfig(passcodeGetter: {
return self.code
// Return code as string
}, passcodeSetter: { code in
self.code = code
// Save new code
}, biometricsGetter: {
return true
// return Should use biometrics (Touch ID or Face ID) as Bool
})
let passcode = Passcode(window: self.window, config: config)
return passcode
}()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
appCoordinator = AppCoordinator(window: window!)
appCoordinator.start()
self.passcode.authenticateWindow()
return true
}
...
}
密码类
导入 UIKit 导入 LocalAuthentication
协议 PassDelegate:类 { func jumpToHomePage() func jumpToOnboardingPage() }
公共类密码{
public var config: PasscodeConfig! public var isPresented = false private var appDelegateWindow: UIWindow? private var authenticationViewController: PasscodeViewController? private lazy var passcodeWindow: UIWindow = { let window = UIWindow(frame: UIScreen.main.bounds) window.windowLevel = UIWindow.Level(rawValue: 0) window.makeKeyAndVisible() return window }() public init(window: UIWindow?, config: PasscodeConfig) { self.appDelegateWindow = window self.config = config NotificationCenter.default.addObserver(self, selector: #selector(self.willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.didEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil) let context = LAContext() var error: NSError? if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) { switch context.biometryType { case .faceID: self.config.biometricsString = "Face ID" self.config.reason = localized("biometricsReasonFaceID") case .touchID: self.config.biometricsString = "Touch ID" self.config.reason = localized("biometricsReasonTouchID") default: break } } else { self.config.biometricsString = nil } } @objc func willEnterForeground() { self.config.foreground = true DispatchQueue.main.async { self.authenticationViewController?.biometrics() } } @objc func didEnterBackground() { self.config.foreground = false } // MARK: - Public public func authenticateWindow(completion: ((Bool) -> Void)? = nil) { guard !isPresented, let viewController = self.load(type: .authenticate, completion: completion) else { return } viewController.dismissCompletion = { [weak self] in self?.dismiss() } passcodeWindow.windowLevel = .init(2) passcodeWindow.rootViewController = viewController self.isPresented = true } public func authenticate(completion: ((Bool) -> Void)? = nil) -> UIViewController? { return self.load(type: .authenticate, completion: completion) } public func authenticate(on viewController: UIViewController, animated: Bool, completion: ((Bool) -> Void)? = nil) { guard let target = self.authenticate(completion: completion) else { return } viewController.present(target, animated: animated) } public func askCode(completion: ((Bool) -> Void)? = nil) -> UIViewController? { return self.load(type: .askCode, completion: completion) } public func askCode(on viewController: UIViewController, animated: Bool, completion: ((Bool) -> Void)? = nil) { guard let target = self.askCode(completion: completion) else { return } viewController.present(target, animated: animated) } public func changeCode(completion: ((Bool) -> Void)? = nil) -> UIViewController? { return self.load(type: .changeCode, completion: completion) } public func changeCode(on viewController: UIViewController, animated: Bool, completion: ((Bool) -> Void)? = nil) { guard let target = self.changeCode(completion: completion) else { return } viewController.present(target, animated: animated) /// Отображение viewController } // MARK: - Private private func load(type: PasscodeType, completion: ((Bool) -> Void)?) -> PasscodeViewController? { let bundle = Bundle(for: PasscodeViewController.self) let storyboard = UIStoryboard(name: "Login", bundle: bundle) guard let viewController = storyboard.instantiateViewController(withIdentifier: "PasscodeViewController") as? PasscodeViewController else { return nil } viewController.authenticatedCompletion = completion viewController.type = type viewController.config = config self.authenticationViewController = viewController return viewController } private func dismiss(animated: Bool = true) { DispatchQueue.main.async { self.isPresented = false self.appDelegateWindow?.windowLevel = UIWindow.Level(rawValue: 1) self.appDelegateWindow?.makeKeyAndVisible() UIView.animate( withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: [.curveEaseInOut], animations: { [weak self] in self?.passcodeWindow.alpha = 0 }, completion: { [weak self] _ in self?.passcodeWindow.windowLevel = UIWindow.Level(rawValue: 0) self?.passcodeWindow.rootViewController = nil self?.passcodeWindow.alpha = 1 } ) } }
}
PasscodeConfig 类
public class PasscodeConfig {
var foreground = true
var biometricsString: String?
public var biometrics: String? { return biometricsString }
public var autoBiometrics = false /// Флаг Включения Аутентификации по Биометрии
public var reason: String?
public var colors = PasscodeColors(dark: false, mainTint: UIColor(red: 0.0, green: 0.48, blue: 1.0, alpha: 1.0), buttonTint: .black, biometrics: (.white, UIColor(red: 0.0, green: 0.48, blue: 1.0, alpha: 1.0)), text: .black)
public var passcodeGetter: (() -> String)
public var passcodeSetter: ((String) -> Void)
public var biometricsGetter: (() -> Bool)
public init(passcodeGetter: @escaping (() -> String), passcodeSetter: @escaping ((String) -> Void), biometricsGetter: (() -> Bool)? = nil) {
self.passcodeGetter = passcodeGetter
self.passcodeSetter = passcodeSetter
self.biometricsGetter = biometricsGetter ?? { true }
}
}
public struct PasscodeColors {
public var mainTint: UIColor
public var buttonTint: UIColor
public var biometrics: (UIColor, UIColor)
public var text: UIColor
public var dark: Bool
public init(dark: Bool, mainTint: UIColor, buttonTint: UIColor? = nil, biometrics: (UIColor, UIColor)? = nil, text: UIColor) {
self.mainTint = mainTint
self.buttonTint = buttonTint ?? mainTint
self.biometrics = biometrics ?? (text, mainTint)
self.text = text
self.dark = dark
}
public init() {
self.mainTint = UIColor(red: 0.0, green: 0.48, blue: 1.0, alpha: 1.0) ///
if #available(iOS 13.0, *) {
self.buttonTint = .label
self.biometrics = (.label, mainTint)
self.text = .label
} else {
self.buttonTint = .black
self.biometrics = (.black, mainTint)
self.text = .black
}
self.dark = false
}
}
此外,必须在加载 View 之前初始化变量config 。
我需要做什么?
提前致谢!
解决方案
您可能希望将设置代码放在 AppDelegate 方法中,而不是作为惰性 var。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
你能张贴什么Passcode
和PasscodeConfig
类的样子吗?
推荐阅读
- android - 在 Android ARCore 中检测二维码
- javascript - 移动设备上的 onClick 事件后功能没有反应
- javascript - 在节点 js 中使用 java 脚本函数
- ios - 从 UIWebview 迁移到 WKWebview
- angularjs - 我可以将 ng-switch 与 ng-repeat 一起使用吗?
- java - 在 JFreechart 中将 unix 时间转换为日期?
- excel - AutoFilter Array 不适用于更多元素 VBA
- javascript - 单击“订阅”按钮后关闭弹出表单
- c# - ASP.NET Core CRUD 工具:未找到但实际安装的命令
- javascript - 我可以在 chartjs 选项上使用三元,尤其是在图例上?