2015-05-18 18 views
0

如何避免下面的代碼在iOS的編程如何避免在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. 在上面提到的場景中,我不確定我因爲它看起來很醜並且很難維護。
+0

使用較少的嵌套塊?有什麼問題?爲什麼你想避免多層次的嵌套? – rmaddy

+0

我同意@rmaddy,我沒有理由想限制這一點。事實上,能夠做到這一點使得編程更容易。 –

+0

我已更新我的問題,謝謝您的關注。 –

回答

1

如果可能(例如,當您的塊不依賴於上下文或使用它們的局部變量),您可以將函數聲明在函數之外或函數的開頭,將它們存儲在一個變量,然後在需要時按名稱使用它們。

你會避免一些嵌套,因爲你所有的開始/結束塊括號將在同一級別。

(void)my_function { 
    NSManagedObjectContext *childContext = [[[NSManagedObjectContext alloc] 
     initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease]; 
    childContext.parentContext = self.managedObjectContext; 

    void (^block4)(void) = ^{ /* Do something */ }; 

    void (^block3)(void) = ^{ /* Do something; */ 
           [childContext performBlock:block4]; }; 

    void (^networkBlock2)(AFHTTPRequestOperation *operation, id responseObject) = void (^){ 
     [self.operationManager POST:URL 
         parameters:nil 
           block:^(AFHTTPRequestOperation *operation, id responseObject) { 
       block3; } }; 

    dispatch_block_t block1 = ^{ [childContext performBlock:networkBlock2]; }; 

    dispatch_async(dispatch_get_main_queue(), block1); 
} 

這就是主意。你必須小心你捕獲的變量和上下文的範圍,並且看看(在這種情況下)你是否可以在聲明你的塊時實例化NSManagedObjectContext,而不是當你執行主隊列上的第一個塊(block1)時。

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

OR

- (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的塊內部做任何你需要做的事情。

0

我不想討論這樣的代碼是否可讀。我認爲這是一個熟悉塊的問題。

但是,有時您希望重新線性化代碼執行,因爲代碼中的嵌套塊會一個接一個地執行。如果你有一個期望block參數的方法的同步雙胞胎,只需使用它。如果沒有,你可以建立自己的。

讓我們有一個方法的異步版本:

@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 
… 

我做說,這應該是一個常見的模式。在大多數情況下,熟悉塊是更好的方法。