【问题标题】:how to execute completion block from another method in objective-c?如何从objective-c中的另一个方法执行完成块?
【发布时间】:2017-02-02 14:27:41
【问题描述】:

是否不可能获得完成块成功然后从另一个方法接收数据?

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

【问题讨论】:

    标签: objective-c listener objective-c-blocks completion-block


    【解决方案1】:

    有点难以理解您在寻找什么,但可能就是它。这就是我在应用程序中处理完成回调的方式:

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

    typedef 应该在 .h 文件中,以便此类和调用 createOrderWithsuccess: 的类都知道它。

    【讨论】:

    • 没有醒来。我在这一行遇到了错误 EXC_BAD_ACCESS (code=1, address=0xc) _myCompletion(data);
    • 你先打电话给createOrderWithSuccess:了吗?您可以将调用 _myCompletion(data) 包装在 if 子句中:if(_myCompletion) _myCompletion(data)
    • 谢谢,它有效 :) 我需要添加 if(_myCompletion) _myCompletion(data) _myCompletion = nil; 吗?根据 hanh answer.With _myCompletion = nil 它只会工作一次。我无法设置 _myCompletion = nil,因为监听器将被多次调用。
    • 不错。可以多次调用它并在完成后将其归零。但是,我不确定它是否会创建一个保留周期,据我所知,您可以在 SocketIOManager 回调中有一个保留周期。为了解决这个问题,您可以在调用 SocketIOManager 之前捕获对 self 的弱引用。 (__ weak TheClass *weakSelf = self;) 并在回调中使用weakSelf.myCompletion(data);(但不确定这在语义上是否正确)
    【解决方案2】:

    如果我正确理解您的意图,那么这个想法很好。调用者可以使用createOrderWithsuccess: 方法作为完成块的设置器。随后,调用者调用listeners,并理解他们之前设置的块将在成功时调用。

    没关系,但请考虑以下几点:(1)复制块...

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

    (1.5) 该块最好命名为“successHandler”或类似的名称,并且该属性可以公开,因此您可以删除createOrderWithsuccess: setter。

    (2) 由于你不确定调用者是否设置了阻塞,所以在调用之前检查 nil (否则会崩溃)

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

    (3) 在你完成它之后将块归零。如果 block 引用了这个对象,nil-ing 会破坏保持循环。

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

    【讨论】:

    • “createOrderWithsuccess”应该是什么样子?
    • 按照我的建议,如果块是一个属性,你可以把它设为公共属性,调用者可以直接赋值。如果你真的想把任务放在 createWithSuccess 中,那么一个一行的任务,就像你拥有它一样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    相关资源
    最近更新 更多