Come eseguire le funzioni di richiamata in Objective-C?
Vorrei solo vedere alcuni esempi completi e dovrei capirlo.
Come eseguire le funzioni di richiamata in Objective-C?
Vorrei solo vedere alcuni esempi completi e dovrei capirlo.
Risposte:
Normalmente, i callback nell'obiettivo C vengono eseguiti con i delegati. Ecco un esempio di implementazione di un delegato personalizzato;
File di intestazione:
@interface MyClass : NSObject {
id delegate;
}
- (void)setDelegate:(id)delegate;
- (void)doSomething;
@end
@interface NSObject(MyDelegateMethods)
- (void)myClassWillDoSomething:(MyClass *)myClass;
- (void)myClassDidDoSomething:(MyClass *)myClass;
@end
File di implementazione (.m)
@implementation MyClass
- (void)setDelegate:(id)aDelegate {
delegate = aDelegate; /// Not retained
}
- (void)doSomething {
[delegate myClassWillDoSomething:self];
/* DO SOMETHING */
[delegate myClassDidDoSomething:self];
}
@end
Ciò illustra l'approccio generale. Crea una categoria su NSObject che dichiara i nomi dei tuoi metodi di callback. NSObject non implementa effettivamente questi metodi. Questo tipo di categoria è chiamato protocollo informale, stai solo dicendo che molti oggetti potrebbero implementare questi metodi. Sono un modo per dichiarare in avanti la firma del tipo del selettore.
Successivamente hai un oggetto che è il delegato di "MyClass" e MyClass chiama i metodi delegate sul delegato come appropriato. Se i callback dei delegati sono facoltativi, in genere li proteggerai sul sito di invio con qualcosa come "if ([delegate respondsToSelector: @selector (myClassWillDoSomething :)) {". Nel mio esempio, il delegato deve implementare entrambi i metodi.
Invece di un protocollo informale, puoi anche utilizzare un protocollo formale definito con @protocol. Se lo fai, cambierai il tipo di setter delegato e la variabile di istanza in " id <MyClassDelegate>
" invece che solo "id
".
Inoltre, noterai che il delegato non viene mantenuto. Ciò si esegue in genere perché l'oggetto che "possiede" istanze di "MyClass" è in genere anche il delegato. Se MyClass ha mantenuto il suo delegato, ci sarebbe un ciclo di conservazione. È una buona idea nel metodo dealloc di una classe che dispone di un'istanza MyClass ed è il suo delegato per cancellare quel riferimento delegato poiché è un puntatore indietro debole. Altrimenti, se qualcosa mantiene in vita l'istanza MyClass, avrai un puntatore penzolante.
Per completezza, dal momento che StackOverflow RSS ha appena resuscitato casualmente la domanda per me, l'altra opzione (più recente) è quella di utilizzare i blocchi:
@interface MyClass: NSObject
{
void (^_completionHandler)(int someParameter);
}
- (void) doSomethingWithCompletionHandler:(void(^)(int))handler;
@end
@implementation MyClass
- (void) doSomethingWithCompletionHandler:(void(^)(int))handler
{
// NOTE: copying is very important if you'll call the callback asynchronously,
// even with garbage collection!
_completionHandler = [handler copy];
// Do stuff, possibly asynchronously...
int result = 5 + 3;
// Call completion handler.
_completionHandler(result);
// Clean up.
[_completionHandler release];
_completionHandler = nil;
}
@end
...
MyClass *foo = [[MyClass alloc] init];
int x = 2;
[foo doSomethingWithCompletionHandler:^(int result){
// Prints 10
NSLog(@"%i", x + result);
}];
Ecco un esempio che tiene fuori i concetti di delegati e fa solo una semplice richiamata.
@interface Foo : NSObject {
}
- (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector;
@end
@interface Bar : NSObject {
}
@end
@implementation Foo
- (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector {
/* do lots of stuff */
[object performSelector:selector withObject:self];
}
@end
@implementation Bar
- (void)aMethod {
Foo *foo = [[[Foo alloc] init] autorelease];
[foo doSomethingAndNotifyObject:self withSelector:@selector(fooIsDone:)];
}
- (void)fooIsDone:(id)sender {
NSLog(@"Foo Is Done!");
}
@end
Tipicamente il metodo - [Foo doSomethingAndNotifyObject: withSelector:] sarebbe asincrono, il che renderebbe il callback più utile di quanto non sia qui.
Per mantenere questa domanda aggiornata, l'introduzione di ARC in iOS 5.0 significa che ciò può essere ottenuto utilizzando i blocchi in modo ancora più conciso:
@interface Robot: NSObject
+ (void)sayHi:(void(^)(NSString *))callback;
@end
@implementation Robot
+ (void)sayHi:(void(^)(NSString *))callback {
// Return a message to the callback
callback(@"Hello to you too!");
}
@end
[Robot sayHi:^(NSString *reply){
NSLog(@"%@", reply);
}];
C'è sempre F **** ng Block Syntax se dimentichi la sintassi di Objective-C.
+ (void)sayHi:(void(^)(NSString *reply))callback;
+ (void)sayHi:(void(^)(NSString *))callback;
- (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName;
(Nota parameterTypes
no parameters
)
CallBack: ci sono 4 tipi di callback in Objective C
Tipo di selettore : puoi vedere NSTimer, UIPangesture sono gli esempi di callback del selettore. Utilizzato per un'esecuzione molto limitata del codice.
Tipo delegato : comune e più utilizzato nel framework Apple. UITableViewDelegate, NSNURLConnectionDelegate. Di solito vengono utilizzati per mostrare Download di molte immagini dal server in modo asincrono, ecc.
Per favore lasciami se qualsiasi altra risposta per questo. Io lo apprezzerei.