Читая различные источники, я сталкиваюсь с проектами, реализованными с использованием xib-файлов.
Я сам предпочитаю использовать xib вместо раскадровки (пишу не ради холивара, раскадровка тоже хороша), но зачастую обучение навигации между экранами превращается в пытку.
И поэтому мне хотелось бы поделиться собственным опытом.
Почему раскадровка так хороша? Прежде всего, он позволяет собрать всю навигацию и наглядно отобразить большую часть переходов.
Да, используя xib для каждого экрана мы теряем возможность визуально увидеть все переходы (ну и еще пару возможностей), но получаем ряд своих преимуществ.
Я не буду подробно описывать плюсы и минусы использования того и другого во избежание холивара, покажу лишь, как можно собрать всю навигацию с помощью xib-файлов, избавиться от ненужного использования синглтонов, а также как исключить связь между контроллерами.
Подход очень простой.
Мы используем объекты Router для связи между экранами.
Разделим Router на пользовательские истории.
Взаимодействуем с помощью обратного вызова.
Мини демонстрация на практике
- Энажмите на таблицу и кнопку, чтобы добавить запись.
- ? Нажмите на создание записи
- Эдетальный просмотр записи
Начальная настройка
Давайте создадим маршрутизатор и отобразим пустой экран.RXAppDelegate.m
RXRouter.h#import "RXAppDelegate.h" #import "RXRouter.h" @implementation RXAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.rootViewController = [[RXRouter alloc] initRouter]; [self.window makeKeyAndVisible]; return YES; } @end
#import <UIKit/UIKit.h>
@interface RXRouter : UINavigationController
- (instancetype)initRouter;
@end
RXRouter.m
#import "RXRouter.h"
@implementation RXRouter
- (instancetype)initRouter {
UIViewController *rootViewController = [self createRootViewController];
self = [super initWithRootViewController:rootViewController];
if (self != nil) {
self.interactivePopGestureRecognizer.enabled = NO;
}
return self;
}
- (UIViewController *)createRootViewController {
UIViewController *controller = [[UIViewController alloc] init];
return controller;
}
@end
Выполнение
Давайте создадим контроллер, который будет показывать записи.Также мы сразу свяжем этот экран с другими экранами и взаимодействием между ними.
RXRoute.m #import "RXRouter.h"
#import "RXNoteListViewController.h"
#import "RXCreateNoteViewController.h"
#import "RXDetailNoteViewController.h"
@implementation RXRouter
- (instancetype)initRouter {
UIViewController *rootViewController = [self createRootViewController];
self = [super initWithRootViewController:rootViewController];
if (self != nil) {
self.interactivePopGestureRecognizer.enabled = NO;
}
return self;
}
- (UIViewController *)createRootViewController {
RXNoteListViewController *noteListController = [[RXNoteListViewController alloc] init];
__weak RXRouter *weakSelf = self;
__weak RXNoteListViewController *weakNoteListController = noteListController;
noteListController.createNoteBlock = ^{
RXCreateNoteViewController *createNoteViewController = [weakSelf createNoteViewController];
createNoteViewController.createNoteBlock = ^(RXNote *note){
[weakNoteListController addNote:note];
[weakSelf popViewControllerAnimated:YES];
};
[weakSelf pushViewController:createNoteViewController animated:YES];
};
noteListController.detailNoteBlock = ^(RXNote *note){
RXDetailNoteViewController *detailNoteViewController = [weakSelf createDetailNoteViewControllerWithNote:note];
[weakSelf pushViewController:detailNoteViewController animated:YES];
};
return noteListController;
}
- (RXCreateNoteViewController *)createNoteViewController {
return [[RXCreateNoteViewController alloc] init];
}
- (RXDetailNoteViewController *)createDetailNoteViewControllerWithNote:(RXNote *)note {
RXDetailNoteViewController *controller = [[RXDetailNoteViewController alloc] init];
[controller showNote:note];
return controller;
}
@end
RXNoteListViewController.h #import <UIKit/UIKit.h>
@class RXNote;
typedef void (^RXNoteListViewControllerCreateNoteBlock)();
typedef void (^RXNoteListViewControllerDetailNoteBlock)(RXNote *note);
@interface RXNoteListViewController : UIViewController
@property (copy, nonatomic) RXNoteListViewControllerCreateNoteBlock createNoteBlock;
@property (copy, nonatomic) RXNoteListViewControllerDetailNoteBlock detailNoteBlock;
- (void)addNote:(RXNote *)note;
@end
RXCreateNoteViewController.h #import <UIKit/UIKit.h>
@class RXNote;
typedef void (^RXCreateNoteViewControllerCreateNoteBlock)(RXNote *note);
@interface RXCreateNoteViewController : UIViewController
@property (copy, nonatomic) RXCreateNoteViewControllerCreateNoteBlock createNoteBlock;
@end
RXDetailNoteViewController.h #import <UIKit/UIKit.h>
@class RXNote;
typedef void (^RXDetailNoteViewControllerDoneBlock)();
@interface RXDetailNoteViewController : UIViewController
- (void)showNote:(RXNote *)note;
@end
Таким образом, мы сразу видим навигацию между экранами, и каждый экран ничего не знает о других экранах.
Более того, за счет использования блоков удалось исключить необходимость вывода на экран информации о роутере.
Мы также можем легко переносить данные с экрана на экран и сократить использование синглтонов.
Ссылка к проект Теги: #iOS #objective-c #OOP #storyboard #xib #Разработка для iOS #objective-c #OOP
-
Три Вещи, Которые Сделают Вас Продуктивнее
19 Oct, 24 -
Кейс-Стади: Как Обмануть Кризис?
19 Oct, 24 -
Консенсус – Это Ложь
19 Oct, 24