4

我有一個Objective C中的異步方法,你傳遞一個完成處理程序。是否有可能避免寫這個塊調用代碼'倒退'?

我希望有條件地在兩個不同的對象上運行這個方法兩次,然後處理結果。

我可以找到做這項工作的唯一方法就是按照下面的方式寫代碼'向後'。

這意味着我的主要架構失敗。有沒有更好的辦法?

defines.h

#define BLOCK_SAFE_RUN(block, ...) block ? block(__VA_ARGS__) : nil 

myController.h

// Code executes in the order (0),(1),(2),(3),(4) - see comments 


    // (0) Create the origin completion handler 
    void (^originCompletionHandler)(FAPlacePoint *, BOOL, BOOL) = ^void (FAPlacePoint *savedOriginPP, BOOL geoCodeDidSucceed, BOOL saveDidSucceed) 
    { 

     // (2) Create the destination completion handler 
     void (^destinationCompletionHandler)(FAPlacePoint *, BOOL, BOOL) = ^void (FAPlacePoint *savedDestinationPP, BOOL geoCodeDidSucceed, BOOL saveDidSucceed) 
     { 

      // (4) 
      // Everything is finished. Do something with savedOriginPP and savedDestinationPP 


     }; 

     // (3) Conditionally run the geocode method with the dest point then call the destination completion handler 
     if (destinationPlacePoint.currentLocation) 
      [self reverseGeocodeThenSavePlacePoint:destinationPlacePoint completion:destinationCompletionHandler]; 
     else 
     { 
      FAPlacePoint * pp = [self storePlacePoint:destinationPlacePoint]; 
      BLOCK_SAFE_RUN(destinationCompletionHandler, pp, YES, YES); 
     } 


    }; 


    // (1) Conditionally run the geocode method with the origin point then call the origin completion handler 
    if (originPlacePoint.currentLocation) 
     [self reverseGeocodeThenSavePlacePoint:originPlacePoint completion:originCompletionHandler]; 
    else 
    { 
     FAPlacePoint * pp = [self storePlacePoint:originPlacePoint]; 
     BLOCK_SAFE_RUN(originCompletionHandler, pp, YES, YES); 
    } 

回答

2

你有重複的代碼,所以應該分離到的方法:

- (void) processPoint:(FAPlacePoint*)point completionHandler:(void (^)(FAPlacePoint *savedPP, BOOL geoCodeDidSucceed, BOOL saveDidSucceed))completionHandler 
{ 
    if (point.currentLocation) 
     [self reverseGeocodeThenSavePlacePoint:point completion:completionHandler]; 
    else 
    { 
     FAPlacePoint * pp = [self storePlacePoint:point]; 
     BLOCK_SAFE_RUN(completionHandler, pp, YES, YES); 
    } 
} 

這可以讓你避免存儲在變量塊只是爲了避免重複它們。所以,你的代碼減少到:

[self processPoint:originPlacePoint completionHandler:^void (FAPlacePoint *savedOriginPP, BOOL geoCodeDidSucceed, BOOL saveDidSucceed) { 
    [self processPoint:destinationPlacePoint completionHandler:^void (FAPlacePoint *savedDestinationPP, BOOL geoCodeDidSucceed, BOOL saveDidSucceed) { 

     // Everything is finished. Do something with savedOriginPP and savedDestinationPP 

    }]; 
}]; 
3

這意味着在我的部分主要的建築失敗。有沒有更好的辦法?

不,它不。也許你只需要調整你的觀點。

在定義它之前,您不能使用變量來調用塊,因此類似完成處理程序的代碼將始終位於調用它的代碼之前。這沒什麼錯。這就像在執行之前告訴別人你的計劃:離開辦公室後,我會在雜貨店停下來。計算機語言通常不會有實際的將來時態,但它可能有助於在將它們稱爲未來時編寫代碼之前定義塊。

如果真的困擾你有導致它運行的代碼之前完成代碼,有時你可以把這些代碼在其自己的方法,這樣完成塊本身是由多一點打電話到該方法。當然,該方法可以跟隨調用它的代碼(但在使用完成塊本身之前仍需要定義它)。

+0

我不知道你有什麼想法,你必須在使用它之前定義一個塊。任何採用block參數的方法都可以使用與調用內聯的塊進行定義。所以要運行一系列的程序段才能嵌套。 – 2014-12-04 21:44:51

+0

@jshier更確切地說,你必須定義一個block *變量*,然後才能使用它來調用該塊。當然,你可以使用塊本身作爲參數,但是你會注意到OP想要從兩個不同的地方調用同一個塊。 Ken Thomases的回答有助於避免在這種特殊情況下的需要。但是,一般來說,如果要在多個地方使用同一個塊,則需要將其分配給一個變量,而在使用該變量調用塊之前,您顯然需要這樣做。 – Caleb 2014-12-04 22:26:26

+0

我非常感謝你的回答。我給予Ken Thomases的答案的唯一原因是,嚴格地說,他提供瞭解決所述問題的代碼。 – 2014-12-17 17:07:49

相關問題