Upload
mailru-group
View
191
Download
0
Embed Size (px)
Citation preview
Dependency Injection в iOS
Дугнист Владислав
План
• Что такое зависимости?
• Что такое внедрение зависимостей (DI)?
• Какие плюсы мы получаем при использовании DI?
• Почему я выбрал Blood Magic.
2
Зависимости
View Controller
3
Зависимости
View Controller
Service
Data
3
Зависимости
- (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wSelf = self; [??? citiesWeatherWithCallback:^(NSArray *array, NSError *error) { wSelf.cities = array; [wSelf.tableView reloadData]; }]; }
4
Зависимости
- (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wSelf = self; [??? citiesWeatherWithCallback:^(NSArray *array, NSError *error) { wSelf.cities = array; [wSelf.tableView reloadData]; }]; }
Зависимость
4
Зависимости
Singleton решение: - (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wSelf = self; [[WFCOpenWeatherService sharedInstance] citiesWeatherWithCallback:^(NSArray *array, NSError *error) { wSelf.cities = array; [wSelf.tableView reloadData]; }]; }
5
Зависимости
Singleton решение: - (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wSelf = self; [[WFCOpenWeatherService sharedInstance] citiesWeatherWithCallback:^(NSArray *array, NSError *error) { wSelf.cities = array; [wSelf.tableView reloadData]; }]; }
Неявная зависимость
5
Признак неявных зависимостей
// WFCViewController.h
@interface WFCViewController : UIViewController
@end
6
Inversion of control// WFCViewController.h
@interface WFCViewController : UIViewController
@property (nonatomic) id <WFCWeatherServiceProtocol> weatherService;
@end
// WFCViewController.m
- (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self) wSelf = self; [_weatherService citiesWeatherWithCallback:^(NSArray *array, NSError *error) { wSelf.cities = array; [wSelf.tableView reloadData]; }]; }
7
Чем полезен IoC?
• Повышает читаемость кода.
• Позволяет выставлять сервисы с заглушками в отладочной версии.
• Упрощает тестирование.
Демо
9
Blood Magic
• github: https://github.com/railsware/BloodMagic
• Podfile: pod 'BloodMagic/Injectable', :git => 'https://github.com/railsware/BloodMagic.git'
Blood Magic
BMInitializer *weatherServiceInitializer = [BMInitializer injectableInitializer];
weatherServiceInitializer.containerClass = [WFCViewController class];
weatherServiceInitializer.protocols =
@[@protocol(WFCWeatherServiceProtocol)];
weatherServiceInitializer.initializer = ^id (id sender) { return [WFCLocalWeatherService new]; }; [weatherServiceInitializer registerInitializer];
Blood Magic (синтаксис)
@interface BMInitializer : NSObject
@property (nonatomic, strong) Class propertyClass; @property (nonatomic, strong) Class containerClass; @property (nonatomic, strong) NSArray *protocols;
@property (nonatomic, copy) magic_initializer_t initializer;
- (void)registerInitializer;
@end
Blood Magic
// WFCViewController.h
@interface WFCViewController : UIViewController <BMInjectable>
@property (nonatomic) id <WFCWeatherServiceProtocol> weatherService;
@end
// WFCViewController.m
@dynamic weatherService;
Демо 2
Другие DI-фреймворки
Typhoon
• http://typhoonframework.org
• github: https://github.com/appsquickly/Typhoon
• Серия статей на хабре: http://habrahabr.ru/company/rambler-co/blog/258325/
• Доклад Rambler&Co: http://www.youtube.com/watch?v=LO59z3fjc9k
Typhoon
• Конфигурация зависимостей на уровне assembly.
• Auto-inject.
Typhoon
Удобные аннотации:
@interface WFCViewController : UIViewController
@property (nonatomic) InjectedProtocol(WFCWeatherServiceProtocol) weatherService;
@end
Typhoon@implementation WFCAssembly
- (id <WFCWeatherServiceProtocol>)defaultWeatherService { return [TyphoonDefinition withClass:[WFCLocalWeatherService class] configuration:^(TyphoonDefinition *definition) { definition.scope = TyphoonScopeSingleton; }]; }
@end
typedef NS_ENUM(NSInteger, TyphoonScope) { TyphoonScopeObjectGraph, TyphoonScopePrototype, TyphoonScopeSingleton, TyphoonScopeLazySingleton, TyphoonScopeWeakSingleton, };
Typhoon+ удобные аннотации
+ поддержка scope
+ больше community
- большие накладные расходы при работе с assembly
- нет возможности выставить условием containerClass при auto inject’ах
Objection
• http://objection-framework.org
• github: https://github.com/atomicobject/objection
Objection
@interface Car : NSObject { Engine *engine; Brakes *brakes; BOOL awake; }
// Will be filled in by objection @property(nonatomic, strong) Engine *engine; // Will be filled in by objection @property(nonatomic, strong) Brakes *brakes; @property(nonatomic) BOOL awake;
@implementation Car objection_requires(@"engine", @"brakes") @synthesize engine, brakes, awake; @end
Objection+ поддержка scope
+ второй по популярности после typhoon
- синтаксис
- отсутствие аннотаций
- нет возможности выставить условием containerClass при inject’ах
The end
cocoaheads slack: @dv
other: /vdugnist