Как именно NSInvocation
работает? Есть хорошее введение?
У меня конкретно возникают проблемы с пониманием того, как работает следующий код (из Cocoa Programming для Mac OS X, 3rd Edition ), но я также могу применять концепции независимо от учебного примера. Код:
- (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index
{
NSLog(@"adding %@ to %@", p, employees);
// Add inverse of this operation to undo stack
NSUndoManager *undo = [self undoManager];
[[undo prepareWithInvocationTarget:self] removeObjectFromEmployeesAtIndex:index];
if (![undo isUndoing])
[undo setActionName:@"Insert Person"];
// Finally, add person to the array
[employees insertObject:p atIndex:index];
}
- (void)removeObjectFromEmployeesAtIndex:(int)index
{
Person *p = [employees objectAtIndex:index];
NSLog(@"removing %@ from %@", p, employees);
// Add inverse of this operation to undo stack
NSUndoManager *undo = [self undoManager];
[[undo prepareWithInvocationTarget:self] insertObject:p
inEmployeesAtIndex:index];
if (![undo isUndoing])
[undo setActionName:@"Delete Person"];
// Finally, remove person from array
[employees removeObjectAtIndex:index];
}
Я понимаю, что он пытается сделать. (Кстати, employees
это NSArray
особый Person
класс.)
Будучи специалистом по .NET, я пытаюсь связать незнакомые концепции Obj-C и Какао с примерно аналогичными концепциями .NET. Это похоже на концепцию делегата .NET, но нетипизировано?
Это не на 100% ясно из книги, поэтому я ищу что-то дополнительное от настоящих экспертов по Cocoa / Obj-C, снова с целью понять фундаментальную концепцию, лежащую в основе простого (-ish) примера. Я действительно ищу возможность самостоятельно применить полученные знания - до главы 9 у меня не было проблем с этим. Но сейчас ...
Заранее спасибо!
источник
setArgument:atIndex:
, поэтому назначение arg должно фактически читать[myInvocation setArgument:&myString atIndex:2]
.Вот простой пример NSInvocation в действии:
- (void)hello:(NSString *)hello world:(NSString *)world { NSLog(@"%@ %@!", hello, world); NSMethodSignature *signature = [self methodSignatureForSelector:_cmd]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setTarget:self]; // index 0 (hidden) [invocation setSelector:_cmd]; // index 1 (hidden) [invocation setArgument:&hello atIndex:2]; // index 2 [invocation setArgument:&world atIndex:3]; // index 3 // NSTimer's always retain invocation arguments due to their firing delay. Release will occur when the timer invalidates itself. [NSTimer scheduledTimerWithTimeInterval:1 invocation:invocation repeats:NO]; }
При вызове -
[self hello:@"Hello" world:@"world"];
- метод:В итоге вы получите такую распечатку:
2010-07-11 17:48:45.262 Your App[2523:a0f] Hello world! 2010-07-11 17:48:46.266 Your App[2523:a0f] Hello world! 2010-07-11 17:48:47.266 Your App[2523:a0f] Hello world! 2010-07-11 17:48:48.267 Your App[2523:a0f] Hello world! 2010-07-11 17:48:49.268 Your App[2523:a0f] Hello world! 2010-07-11 17:48:50.268 Your App[2523:a0f] Hello world! 2010-07-11 17:48:51.269 Your App[2523:a0f] Hello world! ...
Конечно, целевой объект
self
должен продолжать существовать, чтобы NSTimer отправил ему NSInvocation. Например, объект Singleton или AppDelegate, существующий на время работы приложения.ОБНОВИТЬ:
Как отмечалось выше, когда вы передаете NSInvocation в качестве аргумента в NSTimer, NSTimer автоматически сохраняет все аргументы NSInvocation.
Если вы не передаете NSInvocation в качестве аргумента NSTimer и планируете оставить его на некоторое время, вы должны вызвать его
-retainArguments
метод. В противном случае его аргументы могут быть освобождены до вызова вызова, что в конечном итоге приведет к сбою вашего кода. Вот как это сделать:NSMethodSignature *signature = ...; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; id arg1 = ...; id arg2 = ...; [invocation setTarget:...]; [invocation setSelector:...]; [invocation setArgument:&arg1 atIndex:2]; [invocation setArgument:&arg2 atIndex:3]; [invocation retainArguments]; // If you do not call this, arg1 and arg2 might be deallocated. [self someMethodThatInvokesYourInvocationEventually:invocation];
источник
invocationWithMethodSignature:
инициализатор используется, вам все равно нужно позвонитьsetSelector:
. Это кажется лишним, но я только что протестировал, и это необходимо.Вы можете попробовать просто использовать здесь библиотеку, которая намного лучше: http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html
источник
Я создаю простой пример вызова различных типов методов с помощью NSInvocation.
У меня возникли проблемы с вызовом нескольких параметров с помощью obj_msgSend
https://github.com/clearbrian/NSInvocation_Runtime
источник