将数据从AppDelegate传递到UIViewController

时间:2020-06-11 16:45:39

标签: ios swift uiviewcontroller appdelegate

如何将数据从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之前初始化。

我需要做什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

您可能希望将设置代码放入AppDelegate方法中,而不是作为惰性变量。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool

您能够发布PasscodePasscodeConfig类的样子吗?