webentwicklung-frage-antwort-db.com.de

Ausführen von Rückrufen in Objective-C

Wie führe ich Rückruffunktionen in Objective-C durch?

Ich möchte nur einige fertige Beispiele sehen und ich sollte es verstehen.

117
ReachConnection

Normalerweise werden Rückrufe in Ziel C mit Delegierten durchgeführt. Hier ist ein Beispiel für eine benutzerdefinierte Delegatenimplementierung.


Header-Datei:

@interface MyClass : NSObject {
    id delegate;
}
- (void)setDelegate:(id)delegate;
- (void)doSomething;
@end

@interface NSObject(MyDelegateMethods)
- (void)myClassWillDoSomething:(MyClass *)myClass;
- (void)myClassDidDoSomething:(MyClass *)myClass;
@end

Implementierungsdatei (.m)

@implementation MyClass
- (void)setDelegate:(id)aDelegate {
    delegate = aDelegate; /// Not retained
}

- (void)doSomething {
    [delegate myClassWillDoSomething:self];
    /* DO SOMETHING */
    [delegate myClassDidDoSomething:self];
}
@end

Das verdeutlicht den allgemeinen Ansatz. Sie erstellen in NSObject eine Kategorie, die die Namen Ihrer Rückrufmethoden deklariert. NSObject implementiert diese Methoden nicht. Diese Art von Kategorie wird als informelles Protokoll bezeichnet. Sie sagen lediglich, dass viele Objekte diese Methoden möglicherweise implementieren. Sie sind eine Möglichkeit, die Typensignatur des Selektors weiterzuleiten.

Als nächstes haben Sie ein Objekt, das der Delegat von "MyClass" ist, und MyClass ruft die Delegatmethoden für den Delegaten entsprechend auf. Wenn Ihre Stellvertreter-Rückrufe optional sind, schützen Sie sie normalerweise am Versandort mit "if ([Stellvertreter antwortet auf Auswahl: @selector (myClassWillDoSomething :)) {". In meinem Beispiel muss der Delegat beide Methoden implementieren.

Anstelle eines informellen Protokolls können Sie auch ein mit @protocol definiertes formales Protokoll verwenden. Wenn Sie dies tun, ändern Sie den Typ des Stellvertreters und die Instanzvariable auf "id <MyClassDelegate> "statt nur" id ".

Außerdem werden Sie feststellen, dass der Delegat nicht beibehalten wird. Dies geschieht normalerweise, weil das Objekt, das Instanzen von "MyClass" "besitzt", in der Regel auch der Delegat ist. Wenn MyClass seinen Stellvertreter behalten würde, gäbe es einen Aufbewahrungszyklus. Es ist eine gute Idee, die Dealloc-Methode einer Klasse zu verwenden, die eine MyClass-Instanz hat und deren Stellvertreter es ist, diese Stellvertreterreferenz zu löschen, da sie ein schwacher Rückverweis ist. Andernfalls haben Sie einen baumelnden Zeiger, wenn die MyClass-Instanz durch irgendetwas am Leben bleibt.

93
Jon Hess

Der Vollständigkeit halber besteht die andere (neuere) Option darin, Blöcke zu verwenden, da StackOverflow RSS die Frage für mich nur zufällig wiederbelebt hat:

@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);
}];
135
Jens Ayton

Hier ist ein Beispiel, das die Konzepte von Delegierten fernhält und nur einen rohen Rückruf ausführt.

@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

Normalerweise ist die Methode [Foo doSomethingAndNotifyObject: withSelector:] asynchron, was den Rückruf nützlicher macht als hier.

49
Jon Hess

Um diese Frage auf dem neuesten Stand zu halten, bedeutet die Einführung von ARC in iOS 5.0, dass dies mit Blocks noch mehr erreicht werden kann prägnant:

@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);
}];

Es gibt immer F **** ng Block Syntax , wenn Sie jemals die Block Syntax von Objective-C vergessen.

8
Ryan Brodie

Rückruf: In Ziel C gibt es 4 Arten von Rückrufen

  1. Auswahltyp : Sie können NSTimer sehen, UIPangesture sind die Beispiele für Selector Callback. Wird für eine sehr eingeschränkte Ausführung von Code verwendet.

  2. Delegiertyp : Häufig und am häufigsten in Apple Framework. UITableViewDelegate, NSNURLConnectionDelegate. Sie werden normalerweise zum Anzeigen von Downloading many verwendet Bilder vom Server asynchron usw.

  3. NSNotifications : NotificationCenter ist eine der Funktionen von Objective C, mit denen viele Empfänger zum Zeitpunkt des Ereignisses benachrichtigt wurden.
  4. Blöcke : Blöcke werden in der Objective C-Programmierung häufiger verwendet. Es ist eine großartige Funktion, die zum Ausführen von Codebausteinen verwendet wird. Sie können auch auf das Lernprogramm verweisen, um Folgendes zu verstehen: Lernprogramm für Blöcke

Bitte lassen Sie mich eine andere Antwort darauf. Ich werde es zu schätzen wissen.

3
Anil Gupta