【问题标题】:Why can't I return an object from my block?为什么我不能从我的块中返回一个对象?
【发布时间】:2011-12-08 19:49:32
【问题描述】:

我试图在我的方法中从我的块返回一个NSMutableArray,但是当我添加return [responseString JSONValue]; 行时,我收到了一些编译器警告。

- (NSMutableArray*)getTodayData:(NSDate*)today
{
        ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
        [request setPostValue:[dateFormat stringFromDate:today] forKey:@"target_date"];
        NSError *error = [request error];

        [request setCompletionBlock:^{
            NSString *responseString;
            if (!error) {
                responseString = [request responseString];
                return [responseString JSONValue];
            } else {
                NSLog(@"error: %@", error);
            }
        }];
        [request setFailedBlock:^{
            NSString *responseString;
            if (!error) {
                responseString = [request responseString];
            } else {
                NSLog(@"error: %@", error);
            }
        }];
        [request startAsynchronous];
}

【问题讨论】:

  • 能否请您显示编译器给出的警告?
  • 什么对象在捕获返回值?
  • NSMutableArray 正在捕捉它。

标签: iphone objective-c cocoa-touch asynchronous nsmutablearray


【解决方案1】:

ASIFormDataRequest 中的 setCompletionBlock:setFailedBlock: 方法不接受带有返回值的块。你需要重构你的代码,这样就没有返回值了。

例如:

- (void)viewDidLoad
{
  [self getTodayData:self.datePicker.date];
}

- (void)getTodayData:(NSDate*)today
{
      self.appointmentsArray = [NSArray array]; // set it to an empty value now, so the table view displays nothing

      ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
      [request setPostValue:[dateFormat stringFromDate:today] forKey:@"target_date"];
      NSError *error = [request error];

      [request setCompletionBlock:^{
          NSString *responseString;
          if (!error) {
              responseString = [request responseString];
              self.appointmentsArray = [responseString JSONValue];

              [self.appointmentsArrayTableView reloadData]; // I'm assuming you want to display the appointments in some view
          } else {
              NSLog(@"error: %@", error);
          }
      }];
      [request setFailedBlock:^{
          NSString *responseString;
          if (!error) {
              responseString = [request responseString];
          } else {
              NSLog(@"error: %@", error);
          }
      }];
      [request startAsynchronous];
}

【讨论】:

    【解决方案2】:

    你期望返回一个对象做什么?大概您交给ASIFormDataRequest 的完成块被声明为void (^)()(或dispatch_block 或其他一些类型定义为void (^)())。鉴于此,调用该块的代码不需要返回值。这就像实现一个声明为- (void)foo 的方法并试图从中返回一个对象;只是没有意义。

    编辑:重新阅读您的代码后,我希望您真正想要做的是从-getTodayData: 返回一个值。但是,您正在执行异步请求。 -getTodayData: 方法早在你的块被执行之前已经返回了。

    【讨论】:

    • 好吧,在我的viewDidLoad 中,我有self.appointmentsArray = [self getTodayData:self.datePicker.date];。我将如何完成这项工作?
    • 好的,我看到了您编辑的评论,那么我将如何更改我的代码以使其正常工作?当用户更改datepicker 的日期以刷新表格时,我正在使用此方法重新加载我的tableview,并且还在viewDidLoad 中。
    • @Jon:最简单的方法是停止使用异步请求,除非在主线程上同步进行网络 IO 是一个可怕的想法。您需要更改您的方法,以便它本身接受一个完成块,它将数据传递给而不是返回对象。然后调用方法传递一个完成块,该块接受数组并用它更新表。这是一种完全不同的编程风格,但在很多方面它更好。
    • 我把它修好了。但你真的是说停止使用asynchronous 请求吗?
    • @Jon:如果您执行同步请求,那么您的块可以修改包含方法中的__block 变量,然后从该方法返回该变量。代码方面,这是最简单的。但是,在主线程上执行此操作非常糟糕。
    【解决方案3】:

    块定义为void。想想你是如何尝试与块进行交互的。你想从街区返回什么?它会归还给谁?怎么样?

    我认为您遇到的一个误解是处理异步编程。您的方法- (NSMutableArray*)getTodayData:(NSDate*)today 实际上只是发送一个请求不是返回一个数组。您发送请求,请求将在完成后执行该块。但是在执行块时,您的程序已经从您的getTodayData: 方法返回。它将有 no 返回值。

    您想要做的是使用delegate。当请求完成时执行块时,您可以通知委托响应现在存储在某个地方(最好作为实例变量)并且现在可以访问了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-28
      • 2013-05-09
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-29
      • 2021-08-17
      相关资源
      最近更新 更多