سؤال

It's hard to explain, but basically what I am trying to do is call a completion handler in a block-based method from a delegate method.

I have the method where I call the upload function.

[[UploadManager sharedManager] uploadFile:@"/Path/To/Image.png" success:^(NSDictionary *response) {
    NSLog(@"Uploaded");
}];

Inside of the UpLoad manager, the method performs all the necessary actions to upload the file.

There is a delegate method that I want to call the success block from.

- (void)fileDidUploadAndReceiveData:(NSData *)data {
    NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError];
    // Call the completion method
    success(response);
}

success is defined in the uploadFile method. How would I go about calling this completion handler?

I wrote this late at night so if it doesn't make sense, let me know.

Thanks

هل كانت مفيدة؟

المحلول

Declare a property that is a copy of the block:

@property(nonatomic, copy) void (^completionBlock)(NSDictionary *);

Assign it in uploadFile:

- (void)uploadFile:(NSString *)url success:(void (^)(NSDictionary *))completionBlock {
    self.completionBlock = completionBlock;
    // ...

Then call it whenever you want:

if (self.completionBlock) self.completionBlock(someDictionary);
self.completionBlock = nil;  // see below

Remember that, if you don't need the block again (which you probably don't since the download is complete) that it's a good practice to nil out your copy of the block. This way, if the caller refers to the download manager within the block, you'll break the retain cycle for him (the block would retain the download manager which retains the block).

نصائح أخرى

Create an instance variable in your UploadManager class for the success block. Set this ivar in the uploadFile:success: method. Then use this ivar to call the block in your fileDidUploadAndReceiveData: method.

in addition to my comment above this is how I normally handle block operations

in your UploadManager.h file define a type

//// .h file

typedef void (^ActionNameBlock)(id responseObject);


- (void)setAction:(ActionNameBlock)actionBlock;

in your UploadManager.m file

//// .m file

@property (nonatomic, copy) ActionNameBlock action;

- setAction:(ActionNameBlock)_action
{
self.action = _action;
}


// now in your block operation code 

[[UploadManager sharedManager] uploadFile:@"/Path/To/Image.png" success:^(NSDictionary *response)
 {
    NSLog(@"Uploaded");
if (self.action) { self.action(response); }
}];

The fileDidUploadAndReceiveData is defined in the UploadManager ?

If yes then you could just store a copy of the success block and call it exactly the way you wrote it.

Inside your UploadManager header just add a copy block property:

typedef void (^OnUploadFileSuccesBlock)(NSDictionary *response);

@interface UploadManager : NSObject

@property (nonatomic, copy) OnUploadFileSuccesBlock uploadFileSucces;

Keep a copy of the success block in the uploadFile method :

- (void) uploadFile:(NSString*)path success:(OnUploadFileSuccesBlock)block {
  self.uploadFileSucces = block
  ...
}

And in your delegate method you can just call it :

- (void)fileDidUploadAndReceiveData:(NSData *)data {
    NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError];
    // Call the completion method
    self.uploadFileSucces(response);
}

Add property @property (nonatomic, copy) void (^tempSuccess)(NSDictionary * response); in UploadManager

in uploadFile method assign

self.tempSuccess = success;

and finally

- (void)fileDidUploadAndReceiveData:(NSData *)data {
    NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&parseError];
    // Call the completion method
    self.tempSuccess(response);
}

Hope it helps !

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top