0

Is it impossible to get completion block success then data received from another method?

@property myCompletion;

// I have first call listeners, i can't add this in to "createOrderWithsuccess"

-(void)listeners {
    [[SocketIOManager sharedInstance].socket on:@"someAction" callback:^(NSArray* data, SocketAckEmitter* ack) {
        // data received
        myCompletion(data);

    }];

}

// this will be called <del>first</del> later
- (void)createOrderWithsuccess:^(NSArray *data) {
    // but it has to wait then data will be received  
    myCompletion = success;
 }

2 Answers2

0

If I understand your intent correctly, the idea is fine. Callers can use the createOrderWithsuccess: method as a setter for a completion block. Subsequently, callers call listeners with the understanding that the block they set earlier will be invoked upon success.

It's fine, but consider a few things: (1) Copy the block...

@property (nonatomic, copy) void (^myCompletion)(NSArray *);

(1.5) The block would be better named "successHandler" or something like that, and the property could be made public, so you could delete the createOrderWithsuccess: setter.

(2) Since you're not sure if the caller has set the block, check for nil before invoking (it's a crash otherwise)

if (self.myCompletion) self.myCompletion(data);

(3) nil the block after you're through with it. If the block references this object, nil-ing it will break the retain cycle.

if (self.myCompletion) self.myCompletion(data);
self.myCompletion = nil;
danh
  • 62,181
  • 10
  • 95
  • 136
  • how "createOrderWithsuccess" should look like? – Johnny Q Blue Feb 03 '17 at 06:42
  • As I suggested, if the block is a property, you can make it a public property, and callers can assign directly. If you really want to put the assignment in createWithSuccess , then a one line assignment, just as you have it if fine. – danh Feb 03 '17 at 15:25
0

It's a bit hard to understand what you are looking for, but this might be it. This is how I handle Completion callbacks in my app:

@import Foundation;

typedef void (^CompletionBlock)(NSArray *data);

@interface TheClass()

@property (nonatomic, copy) CompletionBlock *myCompletion;

@end

@implementation TheClass()

// ....


- (void) createOrderWithsuccess:(CompletionBlock)success {
    _myCompletion = success;
}

-(void)listeners {
    [[SocketIOManager sharedInstance].socket on:@"someAction" callback:^(NSArray* data, SocketAckEmitter* ack) {
        // data received
        _myCompletion(data);

    }];
}

// Alternatively, breaking possible retain cycles
-(void)listeners {
    __weak TheClass *weakSelf = self;
    [[SocketIOManager sharedInstance].socket on:@"someAction" callback:^(NSArray* data, SocketAckEmitter* ack) {
        // data received
        if(weakSelf.myCompletion) weakSelf.myCompletion(data);
    }];
}

The typedef should be in the .h file so that both this class and the one calling createOrderWithsuccess: knows about it.

Joakim
  • 3,224
  • 3
  • 29
  • 53
  • not woking. I have got ERROR **EXC_BAD_ACCESS (code=1, address=0xc)** on this line `_myCompletion(data);` – Johnny Q Blue Feb 03 '17 at 08:10
  • well did you call `createOrderWithSuccess:` first? you could wrap the call to `_myCompletion(data)` in an if clause: `if(_myCompletion) _myCompletion(data)`. – Joakim Feb 03 '17 at 08:44
  • thanks, it works :) do i need to add `if(_myCompletion) _myCompletion(data) _myCompletion = nil;` ? According to hanh answer.With `_myCompletion = nil` it will works only one time. I can't set _myCompletion = nil because, listener will be call multiple time. – Johnny Q Blue Feb 03 '17 at 12:11
  • Nice. It's ok to call it multiple times and nil it when you are done with it. However, I'm not sure that it would create a retain cycle, as far as I see it, you could have a retain cycle in the SocketIOManager callback. To solve it, you can capture a weak reference to self BEFORE the SocketIOManager call. (`__ weak TheClass *weakSelf = self;`) and use `weakSelf.myCompletion(data);` inside the callback (not sure if this is semantically correct though) – Joakim Feb 03 '17 at 12:57