【问题标题】:Need explanation for this usage of block as method parameter需要解释块作为方法参数的这种用法
【发布时间】:2013-07-22 14:03:40
【问题描述】:

这是来自 AFNetworking 的示例代码的 sn-p:

+ (void)globalTimelinePostsWithBlock:(void (^)(NSArray *posts, NSError *error))block {
    [[AFAppDotNetAPIClient sharedClient] getPath:@"stream/0/posts/stream/global" parameters:nil success:^(AFHTTPRequestOperation *operation, id JSON) {
        NSArray *postsFromResponse = [JSON valueForKeyPath:@"data"];
        NSMutableArray *mutablePosts = [NSMutableArray arrayWithCapacity:[postsFromResponse count]];
        for (NSDictionary *attributes in postsFromResponse) {
            Post *post = [[Post alloc] initWithAttributes:attributes];
            [mutablePosts addObject:post];
        }

        if (block) {
            block([NSArray arrayWithArray:mutablePosts], nil);
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        if (block) {
            block([NSArray array], error);
        }
    }];
}

我不明白的是:

  1. (void (^)(NSArray *posts, NSError *error))block 部分。假设是block,是不是表示block是globalTimelinePostsWithBlock方法的参数?

  2. 在第一个问题之后,谁能为我解释一下语法?为什么最后有个block关键字?

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    如果你不知道块是如何工作的..那么不要费心通过查看代码来理解它(即使你在其他语言中使用过 lambda/匿名函数,如 javascript 或 ruby​​).. b /c Objective-c 语法是一个独立的类..

    我建议您花时间自己理解 obj-c 中的块语法。然后看看使用它们的示例。这个tutorial 很棒(两部分)..

    我做了你之前做过的事.. 拔掉了一半的头发.. 看了上面的教程之后.. 我的头发又长回来了 :)


    只是为了好玩,我会尝试解决您的具体问题:

    1. (void (^)(NSArray *posts, NSError *error)) 块部分。假设是block,是不是表示block是globalTimelinePostsWithBlock方法的参数?

    是的……所以这是调用此方法的一种方式:

    // first define the block variable
    void(^block)(NSArray *posts, NSError *error) = (NSArray *posts,NSError *error) {
    
       // block body
       // posts and error would have been passed to this block by the method calling the block.
       // so if you look at the code sample below.. 
       // posts would be [NSArray arrayWithArray:mutablePosts]
       // and error would just be nil
    }
    
    // call the function
    [AFNetworking globalTimelinePostsWithBlock:block];    
    

    2。在第一个问题之后,任何人都可以为我解释一下语法吗?为什么最后有block关键字?

    block 关键字基本上是参数的名称。注意它在方法体中的使用方式:

    if (block) {
                block([NSArray arrayWithArray:mutablePosts], nil);
            }
    

    再次了解如何/为什么.. 我建议你看看上面的文章.. obj-c 中的学习块有一些学习曲线.. 但是一旦你掌握了它.. 这是一个了不起的工具。请在此处查看我的answer 以查看块的一些示例用法。

    Here 也是一个示例问题/答案,它提供了将委托转换为基于块的方法的案例研究,它还可以说明块的工作原理。

    【讨论】:

    • 感谢您的回答!所以我想我接下来要问的是,如果教程中的示例是:(int)(^name)(int),名称位于返回类型之后,为什么在上面的 AFNetworking 上,名称 (block) 是写在参数后面?
    • 它们是两个不同的东西。(int)(^name)(int)是一个指向块的变量名,而(void (^)(NSArray *posts, NSError *error))block是一个参数type,这个参数被引用作为block.. 需要一段时间才能沉入其中.. 不要着急:) 现在我可以 +1 了吗? ;)
    • @hfz 如果你还在寻找块..检查this out!
    【解决方案2】:

    当 API 调用成功时,块作为要调用的东西传递到方法中。 globalTimelinePostsWithBlock 将调用传入数据的块(可能还有NSError

    block 在这种情况下不是关键字,它只是变量的名称。

    如果你想使用globalTimelinePostsWithBlock,你可以这样称呼它

    [ClassName globalTimelinePostsWithBlock:^(NSArray *posts, NSError *error) {
      // Check error, then do something with posts
    }];
    

    (其中ClassName 是定义在globalTimelinePostsWithBlock 上的类的名称)

    【讨论】:

    • 澄清一下,block 绝不是关键字。 __block 是一个关键字。
    【解决方案3】:

    块定义类似于 C 函数。

    (void (^)(NSArray *posts, NSError *error))block
    
    • 初始的void 定义函数的返回类型。
    • ^ 是块指针。类似于 * 的对象。
    • (NSArray *posts, NSError *error) 是带变量名的参数。
    • block 是存储此块的变量。 (这里的名字不好)

    【讨论】:

    • 感谢您的回答,尤其是bad naming here 部分。它最让我困惑,我很难找到为什么会这样使用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-06
    • 1970-01-01
    相关资源
    最近更新 更多