如何将数据从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()
}
...
}
不幸的是,变量 config 返回-无 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
}
}
此外,变量 config 必须在加载View之前初始化。
我需要做什么?
谢谢!
答案 0 :(得分:0)
您可能希望将设置代码放入AppDelegate方法中,而不是作为惰性变量。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
您能够发布Passcode
和PasscodeConfig
类的样子吗?