【问题标题】:Is there a way to pass methods as blocks?有没有办法将方法作为块传递?
【发布时间】:2012-07-05 19:48:39
【问题描述】:

我讨厌积木。它们旨在使代码更简洁,但我找不到更难看的东西。例如,使用 AFNetworking:

AFJSONRequestOperation* operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
             requestsuccess:^(NSURLRequest *request, NSURLResponse *response, id JSON) {
  // Some
  // very
  // long
  // (and as ugly as blocks)
  // processing
}
                    failure:^(NSURLRequest *request, NSURLResponse *response, NSError *error, id JSON )) {
  // Failure code
}]

这样会更好:

AFJSONRequestOperation* operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
             requestsuccess:@selector(requestSuccess:response:json:)
                    failure:@selector(requestSuccess:response:error:)]

那么,是否可以将方法的选择器用作块?如果没有,我怎样才能使块代码更好?

这让我很恼火,因为这些块似乎是 Objective-C 编程的未来,而且它们只是不可读。

【问题讨论】:

  • 块起初可能看起来“丑陋”,但它们很强大,并且有特定的原因它们“似乎是未来”。我会推荐你​​这篇文章有一个很好的洞察力:ios-blog.co.uk/articles/tutorials/…
  • 块不会让代码更简洁,而是让代码更强大。
  • 我认为这是一个有效的问题。由于块既可以接收参数(0..n)也可以返回参数或 void,方法应该能够用作块......或者换句话说,在类级别定义块会很好。我不认为你可以......

标签: objective-c objective-c-blocks afnetworking


【解决方案1】:

所以你认为块结构使代码更难阅读? 我认为它们有时可以使事情更容易理解,尤其是在异步上下文中,例如在网络代码中。

为了便于阅读,您可以将块分配给变量。 (实际上块是objective-c 对象。)

例子:

typedef void(^SuccessBlock)(NSURLRequest *request, NSURLResponse *response, id JSON);

SuccessBlock successBlock = ^(NSURLRequest *request, NSURLResponse *response, id JSON) {
    // code block
};

AFJSONRequestOperation* operation;
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
                                                            success:successBlock
                                                            failure:nil];

您还可以在块内调用单个处理程序方法以保持其较小。

【讨论】:

  • 它修复了很多“风格”问题,我认为这是最好的方法。谢谢!
【解决方案2】:

短块是好的,过长的不行,划线的地方当然是个人喜好...

对块使用方法并不难(反之则更具挑战性)。如果您想使用方法,最简单的方法:

- (void) requestSuccess:(NSURLRequest *)request
               response:(NSURLResponse *)response
                   json:(id)JSON
{
   // Some
   // very
   // long
   // (and as ugly as blocks)
   // processing
}

- (void) requestFailure:(NSURLRequest *)request
               response:(NSURLResponse *)response
                  error:(NSError **)error
                   json:(id)JSON
{
   // Failure code
}

...

AFJSONRequestOperation* operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
         requestsuccess:^(NSURLRequest *request, NSURLResponse *response, id JSON)
         {
            [self requestSuccess:request response:response json:JSON];
         }
         failure:^(NSURLRequest *request, NSURLResponse *response, NSError *error, id JSON ))
         {
            [self requestFailure:request response:response error:error json:JSON];
         }]

您可以使用宏走得更远,甚至可以使用performSelector/NSInvocation fun - 是否值得取决于您。

您还可以在调用本身之前移动块定义,如下所示:

var = block;
[object method:var];

您选择哪种方法是风格问题。

【讨论】:

    【解决方案3】:

    您可以剥离块,使它们不是方法调用的内联参数。它仍然涉及一些块丑陋,但仍然提高了一些可读性:

    void (^successBlock)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON);
    
    successBlock = ^ (NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
      // Some
      // very
      // long
      // (and as ugly as blocks)
      // processing
    };
    //do same for failure block as "failureBlock"
    ...
    
    AFJSONRequestOperation* operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
                 requestsuccess:successBlock
                        failure:failureBlock];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-30
      • 1970-01-01
      • 2017-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多