如何在iOS编程中避免多个嵌套级别

时间:2015-05-18 03:45:59

标签: ios objective-c

如何避免iOS编程中的代码

                }];
            }];
        }];
    });

以下是我的代码中的一个场景:

(void)my_function {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSManagedObjectContext *childContext = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease];
        childContext.parentContext = self.managedObjectContext;
        [childContext performBlock:^{
            [self.operationManager POST:URL parameters:nil block:^(AFHTTPRequestOperation *operation, id responseObject) {
                //Do something
                [childContext performBlock:^{
                    //Do something
                }];
            }];
        }];
    });
}

为什么我问这个问题:

  1. 可读性
  2. 在我上面提到的场景中,我不确定我是否以正确的方式进行编码,因为它看起来很难看并且很难维护。

3 个答案:

答案 0 :(得分:1)

如果可能(即当你的块没有依赖于使用它们的上下文或局部变量时),你可以在函数之外或函数开头声明块,将它们存储在变量中,然后在需要时按名称使用它们。

您将避免一些嵌套,因为所有开始/结束块括号都将处于同一级别。

CrystalReportViewer1.SeparatePages = false;

这就是主意。您必须小心捕获的变量和上下文的范围,并查看(在这种情况下)是否可以在声明块时实例化NSManagedObjectContext,而不是在主队列上执行第一个(块1)时。 / p>

答案 1 :(得分:0)

这是我想出的(这个特定的例子):

- (void)my_function { // I'd use camelCase
    [self.operationManager POST:URL parameters:nil block:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSManagedObjectContext *childContext = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease]; // autorelease is gone with ARC
        childContext.parentContext = self.managedObjectContext;
        [childContext performBlock:^{
            // Do something
        }];
    }];
}

- (void)my_function { // I'd use camelCase
    [self.operationManager POST:URL parameters:nil block:^(AFHTTPRequestOperation *operation, id responseObject) {
        [self another_function:responseObject];

        // Uncomment if you really need to use the main thread
        //[self performSelectorOnMainThread:@selector(another_function:) withObject:responseObject waitUntilDone:NO];
    }];
}

- (void)another_function:(id)responseObject { // I'd use camelCase
    NSManagedObjectContext *childContext = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease]; // autorelease is gone with ARC
    childContext.parentContext = self.managedObjectContext;
    [childContext performBlock:^{
        // Do something with the 'responseObject'
    }];
}    

丢弃" dispatch_get_main_queue()" - 我认为你不必在主线程上使用主线程上下文,如果你想在Core Data中执行操作,你必须在主线程上。

提取了self.operationManager的POST,因为它不必在上下文的performBlock中。

然后在self.operationManager的块内做任何你需要做的事。

答案 2 :(得分:0)

我不想讨论这些代码是否可读。我认为这是一个熟悉积木的问题。

但是,有时您希望重新线性化代码执行,因为代码中的嵌套块是一个接一个地执行的。如果你有一个期望块参数的方法的同步双胞胎,只需使用它。如果没有,你可以自己构建它。

让我们拥有方法的异步版本:

@interface MyClass : …
- (void)doSomethingInBackgroundCompletion:…;
@end

具有典型用法:

…
[receiver doSomethingInBackgroundCompletion:
^(id result)
{
  // Do Something with result 
  …
}
…

您可以使用信号量线性化它。只需在类别中的同步版本:

@interface MyClass (Linearization)
- (id)doSomethingInBackgroundAndWait;
@end

@implementation MyClass (Linearization)
- (id)doeSomethingInBackgroundAndWait
{
  dispatch_semaphore_t done = dispatch_semaphore_create(0);
  __block id finally;  
  [receiver doSomethingInBackgroundCompletion:
  ^(id result)
  {
     finally = result;
     dispatch_semaphore_signal(done);
  }
  dispatch_semaphore_wait(done);
  dispatch_semaphore_release(done);

  return result;
}
@end

现在您可以使用该方法同步:

…
id result = [receiver doSomethingInBackgroundAndWait];
// Do Something with result 
…

说这应该是一种常见的模式。在大多数情况下,熟悉块是更好的方法。