Initializable 2.0.0

Initializable 2.0.0

测试已测试
语言语言 SwiftSwift
许可证 MIT
版本发布最新版本发布2017年6月
SwiftSwift 版本3.0
SPM支持 SPM

Chris Stephan 维护。



  • 作者:
  • Chris

Initializable 是一组协议,它允许您在应用程序启动时初始化第三方框架和其他设置。它还允许您的框架与 applicationDidEnterForeground 绑定。

动机

当构建新的应用程序时,您有多少次在 application:didFinishLaunchingWithOptions 中添加大量代码来初始化第三方框架或其他全局设置呢?这个框架旨在帮助减少 AppDelegate 中的噪音,并允许这些代码分离到各自负责的对象中。

特色功能

  • 小型的公共 API 接口
  • 适用于您自己的自定义对象
  • 可通过方法实现自定义
  • 良好的文档
  • 测试通过
  • 支持 CocoaPods/Carthage 集成

展示代码

如果你选择 Swift 语言

您需要实现一些符合 Configurable 协议和 Initializable 协议的对象。

// Configuration.swift

class Configuration: NSObject, Configurable {
  static let sharedConfiguration = Configuration()

  var serviceStorage: [String : [Int : [String : String]]] = [:]

  override init() {
    serviceStorage = [
      "FakeService" : [
        ReleaseStage.development.rawValue : [
          "ApiKey": "abc123"
        ]
      ]
    ]
  }

  static func defaultConfiguration() -> Configurable {
    return sharedConfiguration
  }

  func currentStage() -> ReleaseStage {
    return .development
  }

  // Notice we don't define `value(for:key:)` in Swift
  // this is because of the default implementation provided by the
  // extension to Configurable
}
// ThirdpartyInitializer.swift

import Initializable

class ThirdpartyInitializer: NSObject, Initializable {
  func perform(with configuration: Configuration) {
    let apiKey = configuration.value(for: "ThirdParty", key: "apiKey")
    let _ = Thirdparty(apiKey: apiKey)
  }

  func shouldPerformWhenApplicationEntersForeground() -> Bool {
    return false
  }
}

然后进入您的应用程序代理,并将初始化器(们)连接到应用程序生命周期方法中。

// AppDelegate.swift

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  let initializers: [Initializable] = [
    ThirdPartyInitializer(),
  ]
  let configuration = Configuration.defaultConfiguration()

  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    for initializer in initializers {
      initializer.perform(with: configuration)
    }

    return true
  }

  func applicationWillEnterForeground(application: UIApplication) {
    for initializer in initializers {
      if initializer.respondsToSelector(#selector(Initializable.shouldPerformWhenApplicationEntersForeground)) {
        initializer.perform(with: configuration)
      }
    }
  }

  // ...
}

或者如果您更喜欢 Objective-C

您需要实现一些符合 Configurable 协议和 Initializable 协议的对象。

// Configuration.h

#import <Foundation/Foundation.h>

@import Initializable;

@interface Configuration : NSObject <Configurable>

@property (nonatomic, copy) NSDictionary<NSString *, NSDictionary<NSNumber *, NSDictionary<NSString *, NSString *> *> *> *serviceStorage;

@end
// Configuration.m

#import "Configuration.h"

@implementation Configuration

+ (Configuration *)defaultConfiguration
{
  static id instance = nil;
  static dispatch_once_t onceToken;

  dispatch_once(&onceToken, ^{
      instance = [[self alloc] init];
  });

  return instance;
}

- (ReleaseStage)currentStage
{
  return ReleaseStageDevelopment;
}

- (NSDictionary *)serviceStorage
{
  if (!_serviceStorage) {
    _serviceStorage = @{
      @(ReleaseStageDevelopment) : @{
        @"FakeService": @{
          @"apiKey": @"abc123"
        }
      }
    };
  }

  return _serviceStorage;
}

// Notice we define `valueFor:key:` in Objective-C
// this is because the default implementation provided by the extension
// to Configurable is not visible to Objective-C code.
- (NSString *)valueFor:(NSString *)service key:(NSString *)key
{
  Configuration *configuration = [Configuration defaultConfiguration];
  NSDictionary *serviceStorage = [configuration serviceStorage];
  NSDictionary *stageStorage = serviceStorage[@([configuration currentStage])];
  NSDictionary *serviceKeys;

  if (stageStorage) {
    if ((serviceKeys = stageStorage[service])) {
      return serviceKeys[key];
    }
  }

  return nil;
}

@end
// ThirdpartyInitializer.h

#import <Foundation/Foundation.h>

@import Initializable;

@interface ThirdpartyInitializer <Initializable>

@end
// ThirdpartyInitializer.m

#import "ThirdpartyInitializer.h"

@implementation ThirdpartyInitializer

// Notice we substitute id<Configurable> here for our custom class that
// implements the Configurable protocol in the method implementation
- (void)performWith:(Configuration *)configuration
{
  NSString *apiKey = [configuration valueFor:@"Thirdparty" key:@"apiKey"];
  [Thirdparty initWithApiKey:apiKey];
}

- (BOOL)shouldPerformWhenApplicationEntersForeground
{
  return NO;
}

@end

然后进入您的应用程序代理,并将初始化器(们)连接到应用程序生命周期方法中。

// AppDelegate.m

#import "AppDelegate.h"

@import Initializable;

@interface AppDelegate ()

@property (nonatomic, strong) NSArray<id<Initializable>> *initializers;

@end

@implementation AppDelegate

- (void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [self.initializers makeObjectsPerformSelector:@selector(performWith:) withObject:[Configuration defaultConfiguration]];

  return YES
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
  [self.initializers enumerateObjectsUsingBlock:^void(id<Initializable> initializer, NSUInteger index, BOOL *stop) {
    if ([initializer respondsToSelector:@selector(shouldPerformWhenApplicationEntersForeground)] &&
        [initializer shouldPerformWhenApplicationEntersForeground]) {
      [initializer performWithConfiguration:[Configuration defaultConfiguration]];
    }
  }];
}

- (NSArray<id <Initializable>> *)initializers
{
  if (!_initializers) {
    _initializers = @[
      [ThirdPartyInitializer new],
    ];
  }

  return _initializers;
}

@end