一对二完成块

时间:2012-07-26 09:44:38

标签: ios macos objective-c-blocks nserror

我正在使用network kit使用twoBlock方法,但我更喜欢在我自己的代码中使用oneBlock。如果twoBlock方法更好,这让我很困惑。不知怎的,我没有看到它。

有一种方法比其他方法更好吗?


oneBlock方法

组合数据和错误的1个块:

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

twoBlock方法

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

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

5 个答案:

答案 0 :(得分:4)

我认为你不能说任何一个更好。只有不同的利弊平衡。

这两种方法的主要优点是可以更好地分离“快乐”路径的代码和错误管理代码。 (这种分离听起来类似于使用异常提供的优势之一,但它是一种不同的野兽;实际上,catch块允许在一个地方收集,即在“功能”块之外,所有代码都可以管理在“功能”块中可能出现的一堆可能的错误条件,其管理通常会分散在它上面;在上面的2个块示例中,没有这个,因为管理错误条件的代码仍然是混合的与你的函数的其余代码一起)。

另一方面,很可能在两种情况下,即成功和失败,你想采取一些共同的行动。可以想象,例如,序列化一堆网络操作:当一个操作完成时,执行下一个操作,无论前一个操作是成功还是失败。如果使用2块方法,这显然是一些代码复制的情况。

总的来说,我不认为存在很大差异,因为您可以轻松地完成两种方法所需的操作,但在特定情况下,一种方法可以比另一种方法更适合您的工作流程。 / p>

只需2美分。

答案 1 :(得分:1)

我发现2块方法“更清洁”。您不需要if / else块,因此可以更好地分离错误处理。它也减少了1行。整体上没有太大差异,但它有助于保持代码更整洁,更容易阅读,这就是全部。

我认为另一件事使得2块更好的是错误处理自动推到最后。我更喜欢代码在“做所有这些东西,除非出现问题”形式的“假设出错了!它没有?哦,继续。”样式。也许我是一个乐观主义者。无论哪种方式,我宁愿在顶部看到重要的东西,也不要错误处理。

答案 2 :(得分:1)

我更喜欢#1。我认为应该由客户端代码决定实际错误是什么以及它在当前上下文中的含义,基于发回的NSError实例。

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

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

答案 3 :(得分:1)

我已经采用了两种方法。优点是:

  • 如果需要,它允许返回对象和错误
  • 不排序或是否可以调用其中一个或两个
  • 如果您曾将第三个变量添加到另一个回调中,那么事情就不那么混乱了

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

答案 4 :(得分: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];
        });
    }];
}

此外,如果成功阻止很长,则两个块只读得很差:

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