我需要在Objective-C代码中发生一系列很多事件。假设我有6件事 - thingA,thingB,thingC,thingD,thingE和thingF。 thingB和thingD返回BOOL。如果thingB为NO,那么thingC不需要被调用。如果thingD为NO,那么thingE不需要被调用。
- (void)doThings:(void(^)())completion {
[self thingA: ^{
[self thingB: ^(BOOL success) {
if (success) {
[self thingC: ^{
[self thingD: ^(BOOL success) {
if (thingD) {
[self thingE: ^{
[self thingF];
completion();
}];
return;
}
[self thingF];
completion();
}];
}];
return;
}
[self thingD: ^(BOOL success) {
if (success) {
[self thingE: ^{
[self thingF];
completion();
}];
return;
}
[self thingF];
completion();
}];
}];
}];
}
这很快就会变得笨拙。你可以把那些有不同结果的东西带回到循环中,并将它们变成新的方法,如下:
- (void)doThings:(void(^)())completion {
[self thingA: ^{
[self attemptThingB: ^{
[self attemptThingD: ^{
[self thingF];
completion();
}]
}];
}]
}
- (void)attemptThingB:(void(^)())completion {
[self thingB: ^(BOOL success) {
if (success) {
[self thingC: {
completion();
}];
return;
}
completion();
}];
}
- (void)attemptThingD:(void(^)())completion {
[self thingD: ^(BOOL success) {
if (success) {
[self thingE: ^{
completion();
}];
return;
}
completion();
}];
}
这减少了代码重复,但仍然很混乱,难以跟踪。它甚至会导致名称笨拙的方法,这实际上只是这种特殊情况的辅助方法。
必须有更好的方法。看起来很像同步编码的东西,但是是异步的。上面的代码很难阅读,如果我想在流程中添加一些新内容,就会很危险。
建议更好的解决方案?像这样的东西?
- (void)doThings {
[self thingA];
BOOL thingBSuccess = [self thingB];
if (thingBSuccess == YES) {
[self thingC];
}
BOOL thingDSuccess = [self thingD];
if (thingDSuccess == YES) {
[self thingE];
}
[self thingF];
return;
}
提出的解决方案的直接明显问题是完成处理程序可以传递多个对象,而块的返回值只能处理1个对象。但是格式与此类似的东西?它更清洁,更易于维护。
答案 0 :(得分:5)
我认为您已发现调度组!
关于它们的文章有1000篇,不需要在这里毫无意义地粘贴一些东西,
Wait until multiple networking requests have all executed - including their completion blocks
喝彩!
在更简单的层面上,您可能正在寻找的仅仅是“分离代码”,这是写作的关键部分,简单,整洁的代码。请注意,这并不总是解决方案,但经常 - 而且,我并不是100%清楚你要问的是什么。但是在脱离代码中,你会这样......
{
do something;
if ( failure, and you don't want to do any more ) return;
do some other important thing;
if ( failure of that thing, and you don't want to do any more ) return;
do yet another routine here;
if ( some other failed conditions, and you don't want to do any more ) return;
}
这是一个典型的例子。通常你会看到像这样的代码......
-(void)loadNameInToTheCell
{
if ( self.showname != nil && [self.showname notLike:@"blah"] && kount<3 )
{
// many many lines of code here
// many many lines of code here
// many many lines of code here
}
}
你和我在一起吗?但是这样写它会好得多:
-(void)loadNameInToTheCell
{
if ( self.showname == nil ) return;
if ( [self.showname notLike:@"blah"] return;
if ( kount<3 ) return;
// many many lines of code here
// many many lines of code here
// many many lines of code here
}
有道理吗?
请注意,在任何实际项目中,关键是文档而不是代码,所以你可以正确地讨论和评论......
-(void)loadNameInToTheCell
{
if ( self.showname == nil ) return;
// don't forget Steve's routine could return nil
if ( [self.showname notLike:@"blah"] return;
// should we worry about caps here?
if ( kount<3 ) return;
// client wants to change this to 4 in future - Steve
// screw that ... Biff, 8/2014
// many many lines of code here
// many many lines of code here
// many many lines of code here
}
有道理吗?我希望这有助于你所要求的。你必须想到你知道的“其他方式”吗?
一个可能的经验法则是,如果你有条件,然后是“非常长的代码块” - 那就错了。转向另一个方向,并有突破条件。只有这样,才有“实际的相关代码”。从某种意义上说,永远不要在if块中放置一长串重要的代码;如果是这样的话,你有点想错了。