NSInvocation для чайников?

Как работает 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]; } 

Я получаю то, что он пытается сделать. (BTW, employeesNSArray пользовательского classа Person .)

Будучи человеком .NET, я пытаюсь связать незнакомые концепции Obj-C и Cocoa с примерно аналогичными понятиями .NET. Это похоже на концепцию делегата .NET, но нетипизируется?

Это не на 100% ясно из книги, поэтому я ищу что-то дополнительное от реальных экспертов Cocoa / Obj-C, опять же с целью понять, что фундаментальная концепция под простым (-ish) примером. Я действительно стараюсь самостоятельно применять знания до 9-й главы, мне это не сложно. Но сейчас …

Заранее спасибо!

Согласно ссылке classа NSInvocation от Apple :

NSInvocation – это сообщение Objective-C, статичное, т. NSInvocation Это действие, превращенное в объект.

И, немного подробнее:

Концепция сообщений занимает центральное место в философии объектива-c. Каждый раз, когда вы вызываете метод или получаете доступ к переменной какого-либо объекта, вы отправляете ему сообщение. NSInvocation пригодится, когда вы хотите отправить сообщение объекту в другой момент времени или отправить одно и то же сообщение несколько раз. NSInvocation позволяет вам описать сообщение, которое вы собираетесь отправить, и затем вызывать его (фактически отправить его на целевой объект) позже.


Например, предположим, вы хотите добавить строку в массив. Обычно вы отправляете сообщение addObject: следующим образом:

 [myArray addObject:myString]; 

NSInvocation вы хотите использовать NSInvocation для отправки этого сообщения в какой-то другой момент времени:

Во-первых, вы должны подготовить объект NSInvocation для использования с NSMutableArray : addObject: selector:

 NSMethodSignature * mySignature = [NSMutableArray instanceMethodSignatureForSelector:@selector(addObject:)]; NSInvocation * myInvocation = [NSInvocation invocationWithMethodSignature:mySignature]; 

Затем вы должны указать, какой объект отправить сообщение:

 [myInvocation setTarget:myArray]; 

Укажите сообщение, которое вы хотите отправить этому объекту:

 [myInvocation setSelector:@selector(addObject:)]; 

И заполните любые аргументы для этого метода:

 [myInvocation setArgument:&myString atIndex:2]; 

Обратите внимание, что аргументы объекта должны передаваться указателем. Спасибо Райану МакКуаигу за указание на это, и, пожалуйста, см . Документацию Apple для получения более подробной информации.

На этом этапе myInvocation является полным объектом, описывающим сообщение, которое может быть отправлено. Чтобы отправить сообщение, вы должны позвонить:

 [myInvocation invoke]; 

Этот последний шаг приведет к отправке сообщения, по существу выполняя [myArray addObject:myString]; ,

Подумайте, как отправить электронное письмо. Вы открываете новое электронное письмо (объект NSInvocation ), заполняете адрес человека (объекта), которому вы хотите его отправить, введите сообщение для получателя (укажите selector и аргументы), а затем нажмите «отправить», (вызов invoke ).

Дополнительную информацию см. В разделе Использование NSInvocation . См. Использование NSInvocation, если вышеуказанное не работает.


NSUndoManager использует объекты NSInvocation чтобы он мог отменить команды. По существу, вы делаете создание объекта NSInvocation чтобы сказать: «Эй, если вы хотите отменить то, что я только что сделал, отправьте это сообщение этому объекту с этими аргументами». Вы предоставляете объект NSInvocation для NSUndoManager и добавляет этот объект в массив отмененных действий. Если пользователь вызывает «Отменить», NSUndoManager просто ищет последнее действие в массиве и вызывает сохраненный объект NSInvocation для выполнения необходимых действий.

Подробнее см. « Регистрация операций отмены» .

Вот простой пример 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"]; – метод будет:

  • Печать «Привет, мир!»
  • Создайте NSMethodSignature для себя.
  • Создавайте и заполняйте NSInvocation, вызывая себя.
  • Передайте NSInvocation в NSTimer
  • Таймер будет срабатывать (приблизительно) 1 секунду, в результате чего метод будет вызван снова с его исходными аргументами.
  • Повторение.

В конце вы получите распечатку следующим образом:

 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! ... 

Конечно, сам объект-объект должен продолжать существовать, чтобы 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]; 

Вы можете попробовать использовать библиотеку здесь, которая намного приятнее: http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html

Я создаю простой пример вызова различных типов методов с помощью NSInvocation.

У меня возникли проблемы с вызовом нескольких параметров с помощью obj_msgSend

https://github.com/clearbrian/NSInvocation_Runtime

  • Есть ли простой способ разделить NSString на массив символов?
  • Objective C - получение номера строки или полной трассировки стека из-за ошибки отладчика?
  • Динамическое обновление UILabel
  • Можно ли использовать Swift's Enum в Obj-C?
  • Как предотвратить циклическую ссылку, когда Swift-заголовок заголовка импортирует файл, который импортирует сам Hopscotch-Swift.h
  • Глобальная переменная int c
  • Использовать C ++ с Cocoa вместо Objective-C?
  • Исключение SQLite: SQLite Занято
  • Почему переменная NSInteger должна быть отброшена дольше при использовании в качестве аргумента формата?
  • Путь вычитания UIBezierPath
  • Извлечение текста pdf в Objective C
  • Interesting Posts

    Почему возникла связанная с сетью или конкретная ошибка экземпляра при установлении соединения с SQL Server?

    Детали реализации оборудования с плавающей запятой

    Как удалить каталог с файлами только для чтения в C #?

    Окно прокрутки без фокуса

    Почему javac не работает при annotations @Override

    Могу ли я показать прогресс копирования файла с помощью FileInfo.CopyTo () в .NET?

    jQuery, выберите элемент внутри iframe, который находится внутри iframe

    Встроенный MongoDB при выполнении интеграционных тестов

    Наблюдайте за изменениями файлов с помощью node.js

    Простое описание streamов работника и ввода-вывода в .NET.

    Как создать временный файл с определенным расширением с .NET?

    Плагин загрузки файла jQuery: Можно ли сохранить структуру загруженных папок?

    Android: Как я могу проверить ввод EditText?

    Включить ping в брандмауэре Windows 7?

    Что представляют собой Mbps и Kbps на вкладке Performance Manager?

    Давайте будем гением компьютера.