UIAppDelegate解耦

1.OC版的UIAppDelegate 解耦

oc版本的解耦demo有很多,大家可以google出来很多的方法。这里我推荐使用豆瓣的FRDModuleManager。推荐阅读这篇文章http://www.cocoachina.com/articles/17938。简单的说一下使用方法。

1.1 加载所有模块,文件从 plist中获取,将不同的模块填写到 plist 文件中。

1567072713370.jpg

1.2 在 UIApplicationDelegate 各方法中留下钩子

  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"ModulesRegister" ofType:@"plist"];
    FRDModuleManager *manager = [FRDModuleManager sharedInstance];
    [manager loadModulesWithPlistFile:plistPath];

    [manager application:application didFinishLaunchingWithOptions:launchOptions];

    return YES;
  }

  - (void)applicationWillResignActive:(UIApplication *)application {
    [[FRDModuleManager sharedInstance] applicationWillResignActive:application];
  }

  - (void)applicationDidEnterBackground:(UIApplication *)application {
    [[FRDModuleManager sharedInstance] applicationDidEnterBackground:application];
  }

  - (void)applicationWillEnterForeground:(UIApplication *)application {
    [[FRDModuleManager sharedInstance] applicationWillEnterForeground:application];
  }

  - (void)applicationDidBecomeActive:(UIApplication *)application {
    [[FRDModuleManager sharedInstance] applicationDidBecomeActive:application];
  }

  - (void)applicationWillTerminate:(UIApplication *)application {
    [[FRDModuleManager sharedInstance] applicationWillTerminate:application];
  }

1.3 在特定模块,根据需求完成注册即可,比如以下为PushModule的模块

//这是一个遵守了FRDModule协议的模块PushModule.h
@interface PushModule : NSObject<FRDModule>

@end

//PushModule.m
 (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSLog(@"%@  PushModule", NSStringFromSelector(_cmd));
    
    [self zxc_configurationAccount:launchOptions];
    
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
  NSLog(@"%@  PushModule", NSStringFromSelector(_cmd));
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
  NSLog(@"%@  PushModule", NSStringFromSelector(_cmd));
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
  NSLog(@"%@  PushModule", NSStringFromSelector(_cmd));
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
  NSLog(@"%@  PushModule", NSStringFromSelector(_cmd));
}

- (void)applicationWillTerminate:(UIApplication *)application
{
  NSLog(@"%@  PushModule", NSStringFromSelector(_cmd));
}

-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
    
    NSLog(@"11111");
    return  [[UMSocialManager defaultManager] handleOpenURL:url];
}

1.4 这样就可以了。具体的请看demo

2.swfit版的UIAppDelehate解耦

swift的解耦也可以使用FRDModuleManager,但是自己觉得不是很好。所以在不停的学习中发现了 Massive App Delegate,使用了以后觉得不错。,下面说说具体的使用吧。给自己记个笔记

2.0 命令设计模式 启动时来初始化各种命令(比如 第三方库的初始化,根视图控制器等)
  var window: UIWindow?

    let mediator = AppLifecycleMediator.makeDefaultMediator()

    let appDelegate = AppDelegateFactory.makeDefault()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        StartupCommandsBuilder()
            .setKeyWindow(window!)
            .build()
            .forEach { $0.execute() }

        _ = appDelegate.application?(application, didFinishLaunchingWithOptions: launchOptions)

        return true
    }

//启动命令builder
//调用构建器来初始化命令然后触发它们。
final class StartupCommandsBuilder {
    private var window: UIWindow!

    func setKeyWindow(_ window: UIWindow) -> StartupCommandsBuilder {
        self.window = window
        return self
    }

    func build() -> [Command] {
        return [
            InitializeThirdPartiesCommand(),
            InitialViewControllerCommand(keyWindow: window),
            InitializeAppearanceCommand(),
            RegisterToRemoteNotificationsCommand()
        ]
    }
}
protocol Command {
    func execute()
}
////第三方在这里初始化
struct InitializeThirdPartiesCommand: Command {
    func execute() {
        // Third parties are initialized here
    }
}
////在这里初始化根视图控制器
struct InitialViewControllerCommand: Command {
    let keyWindow: UIWindow

    func execute() {
        // Pick root view controller here
        keyWindow.rootViewController = ViewController()
    }
}
//设置UIAppearance 全局设置 通过UIAppearance设置一些UI的全局效果,这样就可以很方便的实现UI的自定义效果又能最简单的实现统一界面风格
struct InitializeAppearanceCommand: Command {
    func execute() {
        // Setup UIAppearance
        UINavigationBar.appearance().tintColor = .black
        UISearchBar.appearance().tintColor = .red
    }
}
////在这里注册远程通知
struct RegisterToRemoteNotificationsCommand: Command {
    func execute() {
        // Register for remote notifications here
    }
}
2.1 复合设计模式 让复合和叶子委托每个都有一个责任。类似工厂一样复合了整个的AppDelegate,然后分发给相应的子叶的AppDelegate。(比如推送通知AppDelegate)
var window: UIWindow?

    let mediator = AppLifecycleMediator.makeDefaultMediator()

    let appDelegate = AppDelegateFactory.makeDefault()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        StartupCommandsBuilder()
            .setKeyWindow(window!)
            .build()
            .forEach { $0.execute() }

        _ = appDelegate.application?(application, didFinishLaunchingWithOptions: launchOptions)

        return true
    }
//AppDelegate工厂
//这些对象封装了触发自身所需的所有参数
enum AppDelegateFactory {
    static func makeDefault() -> AppDelegateType {
        return CompositeAppDelegate(appDelegates: [PushNotificationsAppDelegate(), StartupConfiguratorAppDelegate(), ThirdPartiesConfiguratorAppDelegate()])
    }
}

typealias AppDelegateType = UIResponder & UIApplicationDelegate

//复合AppDelegate
class CompositeAppDelegate: AppDelegateType {
    private let appDelegates: [AppDelegateType]

    init(appDelegates: [AppDelegateType]) {
        self.appDelegates = appDelegates
    }
    //将需要的
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        appDelegates.forEach { _ = $0.application?(application, didFinishLaunchingWithOptions: launchOptions) }
        return true
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        appDelegates.forEach { _ = $0.application?(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) }
    }
}

//推送通知AppDelegate
class PushNotificationsAppDelegate: AppDelegateType {
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // Registered successfully
        
    }
}

//启动配置AppDelegate
class StartupConfiguratorAppDelegate: AppDelegateType {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Perform startup configurations, e.g. build UI stack, setup UIApperance
        return true
    }
}

//第三方配置程序AppDelegate
class ThirdPartiesConfiguratorAppDelegate: AppDelegateType {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Setup third parties
        return true
    }
}
2.2 中介者模式 将UIApplication的生命周期通知底下的监听者。如定义AppLifecycleMediator将UIApplication的生命周期通知底下的监听者,这些监听者必须遵循AppLifecycleListener协议,如果需要监听者要能扩展新的方法。
// MARK: - AppLifecycleListener
protocol AppLifecycleListener {
    func onAppWillEnterForeground()
    func onAppDidEnterBackground()
    func onAppDidFinishLaunching()
}

extension  AppLifecycleListener {
    func onAppWillEnterForeground() {}
    func onAppDidEnterBackground() {}
    func onAppDidFinishLaunching() {}
}

//相应的通知应该做的事
class VideoListener: AppLifecycleListener {
    func onAppDidEnterBackground() {
        //停止视频播放
    }
}

class SocketListener: AppLifecycleListener {
    func onAppWillEnterForeground() {
        //开启长连接
    }
}

// MARK: - Mediator
//将UIApplication的生命周期通知底下的监听者,这些监听者必须遵循AppLifecycleListener协议,如果需要监听者要能扩展新的方法。
class AppLifecycleMediator: NSObject {
    private let listeners: [AppLifecycleListener]

    init(listeners: [AppLifecycleListener]) {
        self.listeners = listeners
        super.init()
        subscribe()
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    //添加通知
    private func subscribe() {
        NotificationCenter.default.addObserver(self, selector: #selector(onAppWillEnterForeground), name: .UIApplicationWillEnterForeground, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(onAppDidEnterBackground), name: .UIApplicationDidEnterBackground, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(onAppDidFinishLaunching), name: .UIApplicationDidFinishLaunching, object: nil)
    }

    @objc private func onAppWillEnterForeground() {
        listeners.forEach { $0.onAppWillEnterForeground() }
    }

    @objc private func onAppDidEnterBackground() {
        listeners.forEach { $0.onAppDidEnterBackground() }
    }

    @objc private func onAppDidFinishLaunching() {
        listeners.forEach { $0.onAppDidFinishLaunching() }
    }
}


//添加通知者
extension AppLifecycleMediator {
    static func makeDefaultMediator() -> AppLifecycleMediator {
        let listener1 = VideoListener()
        let listener2 = SocketListener()
        return AppLifecycleMediator(listeners: [listener1, listener2])
    }
}

2.3 这样就可以了。具体的请细看这篇文章 Massive App Delegate。我只是一个代码的搬运工。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,887评论 1 32
  • 关于组件化 网上组件化的文章很多。很多文章一提到组件化,就会说解耦,一说到解耦就会说路由或者runtime。好像组...
    朱大爷12138阅读 21,042评论 17 130
  • 1.属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作...
    曾令伟阅读 4,712评论 0 10
  • 模块化与解耦 简述 本文主要讲述了在iOS开发过程中,模块化工程架构的一种组织方式,本文主要讲述基于cocoapo...
    其实也没有阅读 3,226评论 0 4
  • 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知...
    莫离_焱阅读 11,608评论 1 8

友情链接更多精彩内容