Slide 1

Slide 1 text

NSProxy, messaging, многопоточность и асинхронность в ObjC Cyril @notorca Lashkevich wtorek, 10 września 13

Slide 2

Slide 2 text

"All problems in computer science can be solved by another level of indirection..." David Wheeler wtorek, 10 września 13

Slide 3

Slide 3 text

"All problems in computer science can be solved by another level of indirection..." David Wheeler "...except for the problem of too many layers of indirection." Kevlin Henney wtorek, 10 września 13

Slide 4

Slide 4 text

Задача Прозрачно пересылать вызовы методов обекта (например делегата) в другой поток wtorek, 10 września 13

Slide 5

Slide 5 text

Задача Прозрачно пересылать вызовы методов обекта (например делегата) в другой поток [obj performSelector:@selector(doThing:) onThread:thread withObject:param waitUntilDone:NO]; wtorek, 10 września 13

Slide 6

Slide 6 text

Задача Прозрачно пересылать вызовы методов обекта (например делегата) в другой поток [obj performSelector:@selector(doThing:) onThread:thread withObject:param waitUntilDone:NO]; wtorek, 10 września 13

Slide 7

Slide 7 text

Задача Прозрачно пересылать вызовы методов обекта (например делегата) в другой поток [obj performSelector:@selector(doThing:) onThread:thread withObject:param waitUntilDone:NO]; [obj doThing:param]; wtorek, 10 września 13

Slide 8

Slide 8 text

NSProxy Абстрактный класс Реализует протокол NSObject Минимальная реализация требует переопределения 2х методов - (void)forwardInvocation:(NSInvocation *) invocation - (NSMethodSignature *) methodSignatureForSelector:(SEL)aSelector // Всегда возвращает результат wtorek, 10 września 13

Slide 9

Slide 9 text

Интерфейс @interface ThreadProxy : NSProxy @property (weak) id target; - (id)initWithTarget:(id)target thread:(NSThread *)thread @end wtorek, 10 września 13

Slide 10

Slide 10 text

Приватная часть интерфейса @interface ThreadProxy () { @protected NSThread *_thread; id _target; Class _targetClass; } - (void)_invokeInvocation:(NSInvocation *)invocation; @end wtorek, 10 września 13

Slide 11

Slide 11 text

init - (id)initWithTarget:(id)target thread:(NSThread *)thread { if (!thread) self = nil; if (self) { _thread = thread; _target = target; _targetClass = [target class]; } return self; } wtorek, 10 września 13

Slide 12

Slide 12 text

- (NSMethodSignature *) methodSignatureForSelector: (SEL)aSelector { return [_targetClass instanceMethodSignatureForSelector: aSelector]; } - (BOOL)respondsToSelector:(SEL)aSelector { return [self.target respondsToSelector:aSelector]; } wtorek, 10 września 13

Slide 13

Slide 13 text

- (void)setTarget:(id)target { @synchronized(self) { _target = target; if (target) { _targetClass = [target class]; } } } - (id)target { @synchronized(self) { return _target; } } wtorek, 10 września 13

Slide 14

Slide 14 text

NSInvocation Вызов метода "замороженный" в виде объекта target, selector и параметры могут быть изменены Вызов можно делать сколько угодно раз Не для vararg и union параметров wtorek, 10 września 13

Slide 15

Slide 15 text

- (void)forwardInvocation:(NSInvocation *)invocation { [invocation retainArguments]; } wtorek, 10 września 13

Slide 16

Slide 16 text

@implementation NSThread (ProxyAdditions) - (void)_invokeWithThreadProxy:(NSInvocation *)invocation { ThreadProxy *p = invocation.target; [p _invokeInvocation:invocation]; } @end - (void)forwardInvocation:(NSInvocation *)invocation { [invocation retainArguments]; } wtorek, 10 września 13

Slide 17

Slide 17 text

@implementation NSThread (ProxyAdditions) - (void)_invokeWithThreadProxy:(NSInvocation *)invocation { ThreadProxy *p = invocation.target; [p _invokeInvocation:invocation]; } @end - (void)forwardInvocation:(NSInvocation *)invocation { [invocation retainArguments]; [_thread performSelector: @selector(_invokeWithTreadProxy:) onThread:_thread withObject:invocation waitUntilDone:NO]; } wtorek, 10 września 13

Slide 18

Slide 18 text

- (void)_invokeInvocation:(NSInvocation *)invocation { if (_target) { [invocation invokeWithTarget:_target]; } } wtorek, 10 września 13

Slide 19

Slide 19 text

- (void)_invokeInvocation:(NSInvocation *)invocation { if (_target) { [invocation invokeWithTarget:_target]; } } - (void)_invokeInvocation:(NSInvocation *)invocation { if ([_target respondsToSelector: invocation.selector]) { [invocation invokeWithTarget:_target]; } } wtorek, 10 września 13

Slide 20

Slide 20 text

- (void)forwardInvocation:(NSInvocation *)invocation { NSMethodSignature *s = invocation.methodSignature; NSInteger lastArg = s.numberOfArguments - 1; const void *block = nil; [invocation getArgument:&block atIndex:lastArg]; block = Block_copy(block); [invocation setArgument:&block atIndex:lastArg]; [invocation retainArguments]; Block_release(block); [_thread performSelector:@selector(_invokeWithTreadProxy:) onThread:_thread withObject:invocation waitUntilDone:NO]; } wtorek, 10 września 13

Slide 21

Slide 21 text

Usefull links http://clang.llvm.org/docs/Block-ABI-Apple.html https://github.com/ebf/CTObjectiveCRuntimeAdditions https://github.com/pandamonia/BlocksKit http://sourceware.org/libffi/ wtorek, 10 września 13