是否有可能避免将此块调用代码“向后”写入?

时间:2014-12-04 20:17:31

标签: ios objective-c objective-c-blocks grand-central-dispatch

我在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 个答案:

答案 0 :(得分:3)

  

这意味着我的主要建筑失败了。还有更好的方法吗?

不,不。也许你只需要调整自己的观点。

在定义块之前,不能使用变量来调用块,因此像完成处理程序之类的代码总是先于调用它的代码。这没什么不对。这就像在执行之前告诉某人你的计划:离开办公室后,我会停在杂货店。计算机语言通常不会有实际的未来时态,但它可能有助于思考在将它们称为将来时编写代码之前定义块。

如果确实让你在导致它运行的代码之前拥有完成代码,那么你有时可以将代码放在自己的方法中,这样完成块本身就可以了。而不是对该方法的调用。当然,该方法可以遵循调用它的代码(但是在使用它之前仍需要定义完成块本身)。

答案 1 :(得分: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

    }];
}];