NSInvocation For Dummies?
Jak dokładnie działa NSInvocation
? Czy jest dobre wprowadzenie?
Mam szczególnie problemy ze zrozumieniem, jak działa poniższy kod (z Cocoa Programming for Mac OS X, 3rd Edition), ale także z możliwością zastosowania tych pojęć niezależnie od próbki samouczka. Kod:
- (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];
}
Rozumiem, co to próbuje zrobić. (BTW, employees
jest NSArray
klasy custom Person
.)
To nie jest w 100% Jasne z książki, więc szukam czegoś uzupełniającego od prawdziwych ekspertów Cocoa / Obj-C, ponownie z celem, że rozumiem podstawowe pojęcie pod prostym (- owskim) przykładem. Naprawdę szukam możliwości samodzielnego zastosowania tej wiedzy . aż do rozdziału 9 nie miałem żadnych trudności z zrobieniem tego. Ale teraz ...
Z góry dzięki!
4 answers
Według klasy Nsinvocation firmy Apple :
An
NSInvocation
jest Komunikatem Objective-C renderowanym statycznie, to znaczy jest akcją zamienioną w obiekt.
I, w mały więcej szczegółów:
Pojęcie wiadomości jest centralne dla filozofii objective-C. Za każdym razem, gdy wywołujesz metodę lub uzyskujesz dostęp do zmiennej jakiegoś obiektu, wysyłasz jej wiadomość. NSInvocation
przydaje się, gdy chcesz wysłać wiadomość do obiektu na inny punkt w czasie, lub wysłać tę samą wiadomość kilka razy. NSInvocation
pozwala opisać wiadomość, którą chcesz wysłać, a następnie wywołać (W rzeczywistości wysłać ją do obiektu docelowego) później.
Na przykład, powiedzmy, że chcesz dodać łańcuch znaków do tablicy. Zazwyczaj wysyłasz addObject:
wiadomość w następujący sposób:
[myArray addObject:myString];
Załóżmy, że chcesz użyć NSInvocation
, Aby wysłać tę wiadomość w innym momencie:
Po pierwsze, ty przygotowanie obiektu NSInvocation
do użycia z selektorem NSMutableArray
'S addObject:
:
NSMethodSignature * mySignature = [NSMutableArray
instanceMethodSignatureForSelector:@selector(addObject:)];
NSInvocation * myInvocation = [NSInvocation
invocationWithMethodSignature:mySignature];
Następnie należy określić, do którego obiektu ma zostać wysłana wiadomość:
[myInvocation setTarget:myArray];
Określ wiadomość, którą chcesz wysłać do tego obiektu:
[myInvocation setSelector:@selector(addObject:)];
I podaj wszelkie argumenty dla tej metody:
[myInvocation setArgument:&myString atIndex:2];
Należy zauważyć, że argumenty obiektu muszą być przekazywane przez wskaźnik. Dziękujemy Ryanowi McCuaig za zwrócenie na to uwagi, a więcej informacji można znaleźć w dokumentacji Apple szczegóły.
W tym momencie {[14] } jest kompletnym obiektem, opisującym wiadomość, którą można wysłać. Aby faktycznie wysłać wiadomość, należy zadzwonić:
[myInvocation invoke];
Ten ostatni krok spowoduje wysłanie wiadomości, zasadniczo wykonując [myArray addObject:myString];
.
NSInvocation
), wpisujesz adres osoby (obiektu), do której chcesz go wysłać, wpisujesz wiadomość dla odbiorcy (podaj selector
i argumenty), a następnie klikasz "send" (call invoke
).
Zobacz używanie NSInvocation aby uzyskać więcej informacji. Zobacz używanie NSInvocation jeśli powyższe nie działa.
NSUndoManager
używa obiektów NSInvocation
, dzięki czemu może odwrócić polecenia . Zasadniczo, to, co robisz, to tworzenie NSInvocation
obiektu, który powie: "hej, jeśli chcesz cofnąć to, co właśnie zrobiłem, Wyślij tę wiadomość do tego obiektu, z tymi argumentami". Dajemy obiekt NSInvocation
NSUndoManager
, a on dodaje ten obiekt do tablicy nie do udźwignięcia. Jeśli użytkownik wywoła "Undo", NSUndoManager
po prostu wyszukuje ostatnią akcję w tablicy i wywołuje przechowywany obiekt NSInvocation
, aby wykonać wymaganą akcję.
Zobacz rejestrowanie operacji cofania Po Więcej Szczegółów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-14 21:37:53
Oto prosty przykład NSInvocation w akcji:
- (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];
}
Po wywołaniu - [self hello:@"Hello" world:@"world"];
- metoda będzie:
- Drukuj " Hello world!"
- Utwórz dla siebie NSMethodSignature.
- utworzyć i wypełnić NSInvocation, wywołując się.
- przekazać NSInvocation do NSTimer
- timer uruchomi się w około 1 sekundzie, powodując ponowne wywołanie metody z jej oryginalnymi argumentami.
- powtórz.
In the end, dostaniesz taki wydruk:
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!
...
Oczywiście obiekt docelowy self
musi nadal istnieć, aby NSTimer wysłał do niego NSInvocation. Na przykład obiekt Singleton lub AppDelegate, który istnieje przez czas trwania aplikacji.
UPDATE:
Jak wspomniano powyżej, gdy przekazujesz nsinvocation jako argument do Nstimera, NSTimer automatycznie zachowuje wszystkie argumenty NSInvocation.
If you are not passing NSInvocation jako argument dla Nstimera, i planujesz, że zostanie przez jakiś czas, musisz wywołać jego metodę -retainArguments
. W przeciwnym razie jego argumenty mogą zostać dealokowane przed wywołaniem wywołania, co ostatecznie spowoduje awarię kodu. Oto jak to zrobić:
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];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-19 15:20:51
Możesz spróbować po prostu skorzystać z biblioteki tutaj, która jest o wiele ładniejsza: http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-02 00:24:00
Buduję prosty przykład wywoływania różnych typów metod z NSInvocation.
Miałem problemy z wywołaniem wielu paramów przy użyciu obj_msgSend
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-28 15:33:26