2
typedef void (^RequestProductsCompletionHandler)(BOOL success, NSArray * products);

我很难理解这行代码在 .h 文件中的作用。

请详细解释

  1. 类型定义。
  2. void (我知道 void 做什么,但这里的目的是什么?)。
  3. (^RequestProductsCompletionHandler)(BOOL 成功, NSArray * products);
  4. 怎么称呼它?
4

3 回答 3

9

这是objective-c类型的定义,其名称带有RequestProductsCompletionHandler2个参数(BOOL和NSArray)并且没有返回值。您可以像调用 c 函数一样调用它,例如:

RequestProductsCompletionHandler handler = ^(BOOL success, NSArray * products){
    if (success){
       // Process results
    }
    else{
       // Handle error
    }
}
...
handler(YES, array);
于 2013-08-12T12:35:17.213 回答
7

弗拉基米尔描述得很好。它定义了一个变量类型,它表示一个将传递两个参数的,一个布尔值success和一个数组products,但块本身返回void。虽然您不需要使用typedef,但它使方法声明更加优雅(并且避免了您必须参与块变量的复杂语法)。

举一个实际的例子,可以从块类型的名称及其参数中推断出它定义了一个完成块(例如,当一些异步操作(如慢速网络请求)完成时要执行的代码块)。请参阅使用模块作为方法参数

例如,假设您有一些InventoryManager类,您可以从该类中请求产品信息,并使用具有这样定义接口的方法,使用您的typedef

- (void)requestProductsWithName:(NSString *)name completion:(RequestProductsCompletionHandler)completion;

你可能会使用这样的方法:

[inventoryManager requestProductsWithName:name completion:^(BOOL success, NSArray * products) {

    // when the request completes asynchronously (likely taking a bit of time), this is
    // how we want to handle the response when it eventually comes in.

    for (Product *product in products) {
        NSLog(@"name = %@; qty = %@", product.name, product.quantity);
    }
}];

// but this method carries on here while requestProductsWithName runs asynchronously

而且,如果您查看 的实现requestProductsWithName,可以想象它看起来像:

- (void)requestProductsWithName:(NSString *)name completion:(RequestProductsCompletionHandler)completion
{
    // initiate some asynchronous request, e.g.

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // now do some time consuming network request to get the products here

        // when all done, we'll dispatch this back to the caller

        dispatch_async(dispatch_get_main_queue(), {
            if (products)
                completion(YES, products); // success = YES, and return the array of products
            else
                completion(NO, nil);       // success = NO, but no products to pass back
        });
    });
}

显然,这不太可能正是您的特定完成处理程序块正在做的事情,但希望它说明了这个概念。

于 2013-08-12T13:07:13.587 回答
2

Mike Walker 创建了一个不错的单页站点,展示了在 Objective-C 中声明块的所有可能性。这也有助于理解您的问题:

http://fuckingblocksyntax.com

引用他的网站,这是定义块的方式:

作为局部变量:

returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};

作为财产:

@property (nonatomic, copy) returnType (^blockName)(parameterTypes);

作为方法参数:

- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName {...}

作为方法调用的参数:

[someObject someMethodThatTakesABlock: ^returnType (parameters) {...}];

作为类型定义:

typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^(parameters) {...}
于 2013-09-13T15:56:42.457 回答