- PVSM.RU - https://www.pvsm.ru -

Уже много копий было сломанно о тему «обработка событий в Objective-C», о делегировании событий (к примеру, viewWillAppear:(BOOL)animated ), о том как это не удобно, когда надо слушать их одновременно в разных местах программы.
Я хочу предложить Вам свою реализацию шаблона Observer, который использует мощь C++0x и позволяет объявлять сигналы с жёстко типизированным списком параметров, например, вот так:
new TLSignal<NSString *, BOOL>(self);
Т.к. мои знания С++ довольно таки скудны, то буду признателен любым советам по улучшению данного кода.
Заинтересовавшихся прошу под кат.
Часто встречаются ситуации, когда необходимо уведомить другие объекты о каком-либо событии (свойство изменилось, смена состояния и так далее), при этом необходимо иметь возможность соблюдать соответствие «One-to-many», чтобы событие одновременно могли получить несколько слушателей. По этой причине вариант с делегатами сразу отпадает.
Какие варианты предлагают нам встроенные средства Objective-C?
Лучше статьи на википедии [1] думаю у меня рассказать не получится, поэтому я лишь уточню детали:
Итак, объявление сигнала выглядит вот так:
new TLSignal<NSString *, BOOL>(self);
Что означает, что:
При этом блок, слушающий данное событие, будет выглядеть вот так:
auto observerBlock = ^(id target, NSString *stringParam, BOOL boolParam)
{
NSLog(@"%@ %@ %d", target, stringParam, boolParam);
};
Обратите внимание на 1ый параметр id target, он передаётся всегда и равен «держателю» данного сигнала.
Код без примера использования — не код, поэтому хочу привести маленький пример программы, на примере которой хотел бы продемонстрировать, в чем собственно преимущество сигналов и как их можно использовать.
#import <UIKit/UIKit.h>
#import "Signals.h"
@interface ExampleViewController : UIViewController
@property (nonatomic, readonly) TLSignal<UIView *> *viewDidLoadSignal;
@end
Здесь всё просто, объявляем сигнал с идентификатором viewDidLoadSignal, который будет передавать экземляр UIView слушателям.
#import "ExampleViewController.h"
@implementation ExampleViewController
@synthesize viewDidLoadSignal = _viewDidLoadSignal;
-(TLSignal<UIView *> *)viewDidLoadSignal
{
if(!_viewDidLoadSignal)
{
// Лениво создаём экземпляр сигнала и передаём ему в конструктор ссылку на себя (источник события)
_viewDidLoadSignal = new TLSignal<UIView *>(self);
}
return _viewDidLoadSignal;
}
-(void)viewDidLoad
{
[super viewDidLoad];
// Рассылаем событие слушателям, передав в них наш UIView
self.viewDidLoadSignal->notify(self.view);
}
@end
#import "AppDelegate.h"
#import "ExampleViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)options
{
UIWindow window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ExampleViewController alloc] initWithNibName:@"ViewController" bundle:nil];
// Добавим сигналу слушателя, который по событию поменяет цвет переданного в него UIView
self.viewController.viewDidLoadSignal->addObserver(^(id target, UIView *targetView)
{
targetView.backgroundColor = [UIColor blackColor];
});
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
@end
Обратите внимание, что расширение файлов с кодом, в котором используются сигналы, должно быть .mm а не .m, иначе он будет воспринят как обычный Objective-C код и не поймёт нашей плюсовой магии!
Я искренне надеюсь, что в Objective-C (например, 2.5 или 3.0) появится что-то подобное на уровне стандарта, а пока это не произошло, предлагаю Вам использовать мою библиотеку (она крайне лёгкая в использовании, код так же понятен даже с небольшими знаниями в C++, коими я и обладаю:)):
TLSignals на GitHub [2]
На днях она появится в Cocoapods, а пока это не произошло, Вы можете просто скопировать файл TLSignals.h к себе в проект и начать работать с ним.
Код частично покрыт тестами, чтение которых поможет Вам лучше понять, как оно работает:
TLSignalsTests.mm на GitHub [3]
Буду благодарен за дополнения и улучшения, а так же тыкание носом меня в слабые моменты со стороны C++ и вообще, потому что все мы только учимся;)
При обнаружении опечаток или грамматических ошибок просьба писать о них личным сообщением, дабы не засорять этим комментарии.
Спасибо за внимание!
Автор: bsideup
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/objective-c/22369
Ссылки в тексте:
[1] статьи на википедии: http://en.wikipedia.org/wiki/Observer_pattern
[2] TLSignals на GitHub: https://github.com/bsideup/TLSignals
[3] TLSignalsTests.mm на GitHub: https://github.com/bsideup/TLSignals/blob/master/TLSignalsTests/TLSignalsTests.mm
[4] en.wikipedia.org/wiki/Variadic_Templates: http://en.wikipedia.org/wiki/Variadic_Templates
[5] habrahabr.ru/post/101430/: http://habrahabr.ru/post/101430/
[6] Источник: http://habrahabr.ru/post/162235/
Нажмите здесь для печати.