一个 vs. 两个完成块

4
我正在使用一个使用twoBlock方法的网络套件,但我更喜欢在我的代码中使用oneBlock。这让我困惑了,因为我不知道twoBlock方法是否更好。不知何故,我看不到它的优势。
有没有一种方法比另一种方法更好?

oneBlock方法

将数据和错误结合在一起的1个块:

-(void)oneBlock {
    [self startWithCompletionBlock:^(id obj, NSError* error) {
        if(error) {
            NSLog(@"error: %@", error);
        } else {
            NSLog(@"success: %@", obj);
        }
    }];
}

twoBlock 方法

两个块专门处理数据和错误:

-(void)twoBlocks {
    [self startWithCompletionBlock:^(id obj) {
        NSLog(@"success: %@", obj);
    } errorBlock:^(NSError* error) {
        NSLog(@"error: %@", error);
    }];
}
5个回答

4
我认为不能说哪种方法更好,只是在优缺点的平衡上有所不同。
使用两个块的主要优点是可以更好地分离代码,使其适用于“正常”路径和错误管理的代码。(这种分离听起来类似于使用异常时提供的优点之一,但它是一个不同的问题;事实上,catch块允许将所有代码收集到一个地方,即在“功能”块之外,以便管理可能出现在“功能”块内并且通常会分散在整个代码中的一堆可能的错误条件;在上面的2个块示例中,没有这样的情况,因为管理错误条件的代码仍然与函数的其他代码混合在一起)。
另一方面,很可能在两种情况下,即成功和失败,您都希望采取一些共同的操作。例如,想象一下序列化一堆网络操作:当一个操作完成时,您执行下一个操作,无论前一个操作是成功还是失败。如果使用两个块的方法,则在此情况下会出现一些代码复制。
总体而言,我认为它们之间的差异不大,因为您可以轻松地使用这两种方法来做您需要做的事情,但在特定情况下,一种方法可能比另一种更适合您的工作流程。
以上仅为个人意见。

1
基于@sergio提到的原因,我认为oneBlock方法更加简洁。它使调用者在管理代码路径方面更具灵活性。对于这样的回调API,通常需要在回调结束时调用清理(或下一步)代码,无论成功与否。
-(void)oneBlock {
    [self startWithCompletionBlock:^(id obj, NSError* error) {
        if (error) {
            NSLog(@"error: %@", error);
        } else {
            NSLog(@"success: %@", obj);
        }
        self.connection = nil;
        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateUI];
        });
    }];
}

此外,如果成功块很长,使用twoBlocks会读起来不太好。
-(void)twoBlocks {
    [self startWithCompletionBlock:^(id obj) {
        [self doSomething];
        [self doSomethingElse];

        [self setUpSomeOtherRequestWithCompletionBlock:^(id obj) {
            [self doSomething];
            [self doSomethingElse];

            NSLog(@"inside request succeeded");
        } errorBlock:^(NSError* error) {
            NSLog(@"error: %@", error);
        }];

        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateUI];
        });
    } errorBlock:^(NSError* error) {
        NSLog(@"error: %@", error);
    }];
}

1

我认为采用两个块的方法更加“简洁”。您不需要if/else块,因此错误处理的分离更好。这也少了一行代码。总体上差别不大,但它有助于使代码变得更整洁、更易读。

我认为另一个使两个块更好的事情是错误处理自动推到了最后。我更喜欢代码以“做所有这些事情,除非出现问题”形式呈现,而不是“假设出现了问题!没有?哦,继续。”的风格。也许我是个乐观主义者。无论如何,我宁愿看到重要的东西在顶部,而错误处理则被搬到一边。


1

我更喜欢选项#1。我认为应该由客户端代码决定实际错误是什么以及在当前上下文中意味着什么,这取决于发送回来的NSError实例。

在选项#2中,如果完成块包含超过几行代码(例如在视图控制器中使用),则很可能希望在两个块中执行许多相同的完成代码,无论是否发生错误(更新UI,恢复某些状态等)。这将导致不必要的代码重复。

此外,如果您不关心错误情况,选项#1的代码量较少。


1

我已经决定采用两个块的方法。优点如下:

  • 如果需要,它允许返回一个对象和一个错误
  • 不需要考虑顺序或是否可以调用其中一个或两个
  • 如果您将第三个变量添加到另一个回调中,事情会变得更加清晰

在我的看法中,多个块应该保留给多个连续的回调。想想UIView动画的工作方式。


1
两块式方法...你是不是指单块式方法? - neoneye

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接