Storyboards Segregation
Storyboards Segregation
Зачем?
Обычная storyboard
Обычная storyboard
• Тесная связанность всех экранов,
• Запутанность логики переходов прямо пропорциональна количеству экранов,
• Невозможно работать совместно.
Решение
Метод банана
• В отдел покупается банан.
• Только разработчик, в руках которого он находится, может работать со storyboard.
• Профит.
Решение получше
Раздельные storyboards
1. Выделяем из карты экранов общие user stories.
2. Экстраполируем их на контроллеры Main.storyboard.
3. Переносим эти группы в отдельные storyboards.
Было
Стало
Несколько тезисов• Группа экранов выделяется в отдельную
storyboard в двух случаях:
• Самостоятельная user story (Settings User Story),
• Общая группа экранов для нескольких storyboards (Photos User Story).
• Не нужно бояться маленьких storyboards.
Storyboard-to-Storyboard
Программно
pushViewController:
pushViewController:
Segues
LinkedStoryboardSegueSegue Identifier:
MSAPhotoGalleryViewController_Photos
LinkedStoryboardSegue
@interface MSALinkedStoryboardSegue : UIStoryboardSegue
+ (UIViewController *)sceneNamed:(NSString *)identifier;
@end
LinkedStoryboardSegue
UITabBarController
UITabBarController- (UITabBarController *)tabBarController { return [TyphoonDefinition withClass:[UITabBarController class] configuration:^(TyphoonDefinition *definition) { [definition injectProperty:@selector(viewControllers) with:[self storyboardsInitialViewControllers]]; }]; }
- (NSArray *)storyboardsInitialViewControllers { return @[ [[UIStoryboard storyboardWithName:MSABreedsStoryboardIdentifier bundle:[NSBundle mainBundle]] instantiateInitialViewController], [[UIStoryboard storyboardWithName:MSABestCatStoryboardIdentifier bundle:[NSBundle mainBundle]] instantiateInitialViewController], [[UIStoryboard storyboardWithName:MSASettingsStoryboardIdentifier bundle:[NSBundle mainBundle]] instantiateInitialViewController] ]; }
Роутеры
Зачем?
• ViewController не должен знать о реализации переходов между экранами.
• ViewController не должен конфигурировать другие ViewController’ы.
Как?@interface UIViewController (Routing)
@property (nonatomic, strong) id<MSARoutingProtocol> router;
@end
@protocol MSARoutingProtocol <NSObject>
- (instancetype)initWithNavigationController:(UINavigationController *)navigationController;
- (void)dismissCurrentViewController:(UIViewController *)viewController animated:(BOOL)animated;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;
@end
А пример?@protocol MSABreedsRouter <MSARoutingProtocol>
- (void)showBreedViewControllerFromSourceController:(UIViewController *)sourceController withCatBreed:(MSACatBreed *)catBreed;
- (void)showPhotosViewControllerFromSourceController:(UIViewController *)sourceController withCatBreed:(MSACatBreed *)catBreed;
- (void)showWarningViewControllerFromSourceController:(UIViewController *)sourceController;
@end
А передача данных?
1. В UIViewController+Routing: prepareForSegue -> msa_prepareForSegue
2. И методы от Ильи: - (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender userInfo:(NSDictionary *)userInfo;
- (NSDictionary *)segueUserInfo:(UIStoryboardSegue *)segue;
Полезные мелочи
Переиспользование экранов
• Если экран входит сразу в несколько user stories, можно реализовать его отдельно.
• Storyboard сама подтягивает нужный xib по имени класса.
Переиспользование экранов
Storyboard Constants
• Receiver (<MSAPhotoGalleryViewController: 0x8cbd540>) has no segue with identifier ‘breedDetailSegue’
Storyboard Constants
• Receiver (<MSAPhotoGalleryViewController: 0x8cbd540>) has no segue with identifier ‘breedDetailSegue’
:(
Storyboard Constants
generate_constants.py -> MSAStoryboardsIdentifiers.h
/* Segue identifier constants */ @class NSString;
extern NSString * const sBreedDetailSegue; extern NSString * const sMSAPhotoGalleryViewController_Photos; extern NSString * const sMSAPhotoViewController_Photos; extern NSString * const sPhotoViewSegue; extern NSString * const sWarningSegue;
Storyboard Constants
• В списке Build Phases скрипт генерации констант должен быть на первом месте.
• Можно смело выпилить генерацию констант для ID контроллеров и ячеек.
• Да и вообще, жить можно и без него.
User Stories как структура
• Иногда красиво разбивать файлы проекта получается по User Stories:
Полезные ссылки
• Тестовое приложение: https://github.com/igrekde/MultipleStoryboardsSample
• Reusing Views with Auto Layout: http://cocoanuts.mobi/2014/03/26/reusable/
• Easier Multiple Storyboards: http://spin.atomicobject.com/2014/03/06/multiple-ios-storyboards/