我在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);
}
答案 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
}];
}];