0

Objekt X muss ein Image herunterladen. Es hat URL des Bildes (könnte Datei des Netzes sein). Ich habe eine gemeinsame imageHandler-Klasse, die eine URL aufnehmen und die imageData abrufen kann. Ich möchte, dass diese Methode in der Lage ist, einen Abschlussblock zu nehmen, um anzupassen, was mit dem heruntergeladenen Bild zu tun ist.Objective-C: Wie gebe ich einer Methode einen Completion-Block, der ein Ergebnis der Methodenausführung verwendet

Ich bin vertraut mit, wie es zu tun ist mit Delegate-Muster. ZB

Also im Grunde objectX Klasse getImageFromURL: Delegate-Methode mit Delegate als selbst. Es entspricht dem ImageRequestor-Protokoll.

Das ImageHandler-Objekt speichert die URL, um die Zuordnung in einer Hash-Tabelle zu delegieren. Nachdem es fertig ist, ruft Bild: RetrievedForURL: withError: auf dem Delegaten auf. Und bei dieser Methode handle ich auf das Bild und den Fehler.

Wie erreiche ich den gleichen Effekt mit Completion-Blöcke, wo ich weitergeben, was ich mit dem abgerufenen Bild als ein Stück Code tun möchte.

Ein Ansatz, den ich sehe, ist wie folgt. Aber es sieht so aus, als ob die Implementierung der ImageHandler-Methode den Abschluss mit bestimmten Argumenten aufrufen muss. Ist dies der akzeptierte Weg, dies zu implementieren (d. H. Der Vervollständigungshandler verlässt sich auf die Methode, die ihn empfängt, um ihn mit korrekten Argumenten aufzurufen)?

@protocol ImageHandler: NSObject 
-(void) getImageFromURL:(NSURL *)url withCompletionHandler:(void (^)(UIImage *image, NSError * err))completionBlock; 
@end 

Die Implementierung von getImageFromURL:(NSURL *)url withCompletionHandler:(void (^)(UIImage *image, NSError * err))completionBlock sieht aus wie

getImageFromURL:(NSURL *)url withCompletionHandler:(void (^)(UIImage *image, NSError * err))completionBlock 
{ 
//Get UIImage from URL, store it UIIMage ObjectX 
//if error happens, store it in NSError objectY, else it is nil 
//call completion handler 
completionBlock(<UIIMage objectX>,<NSError objectY>); 
} 

Antwort

4

Ja, was Sie haben gezeigt ist die typische Art und Weise, dies zu tun. Schau dir Apples eigene APIs an, um zu sehen, dass sie es auf die gleiche Weise machen. Zum Beispiel -[NSURLSession dataTaskWithURL:completionHandler:], deren Erklärung:

- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url 
         completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler; 
0

folgendes in Ihrem ImageRequestor.h Datei schreiben:

#import <Foundation/Foundation.h> 

// Here you define your custom response block with the desired parameters 
// That in this case are UIImage and NSError 
typedef void (^ResponseBlock)(UIImage *image, NSError *error); 

@interface ImageRequestor : NSObject 

// Here you define the method that use your custom response block 
- (void)getImageFromURL:(NSURL *)url withCompletionHandler:(ResponseBlock)completionBlock; 

@end 

Fast fertig, jetzt öffnen Sie Ihre ImageRequestor.m Datei und fügen Sie die folgende:

#import "ImageRequestor.h" 

@implementation ImageRequestor 

- (void)getImageFromURL:(NSURL *)url withCompletionHandler:(ResponseBlock)completionBlock { 
    // Do all your stuff to get the image and the error 
    // And set them into your completion block 
    // if there is no error that should be nil 

    // completionBlock(YourFetchedImage, YourFetchedError); 
    // completionBlock(nil, YourFetchedError); 
    completionBlock(YourFetchedImage, nil); 
} 

@end 

Und schließlich können Sie es mit etwas wie t nennen sein:

ImageRequestor *imageRequestor = [[ImageRequestor alloc] init]; 
[imageRequestor getImageFromURL:yourURL withCompletionHandler:^(UIImage *image, NSError *error) { 
    // Your implementation in here 
}]; 

Diese Art des Stoffes in einem Singletonklasse viel viel besser aussieht:]

Hoffen, dass es hilft, Good Luck !!

Verwandte Themen