【问题标题】:How to obtain the returned value of an uncalled method in Objective-CObjective-C中如何获取未调用方法的返回值
【发布时间】:2011-06-14 17:23:46
【问题描述】:

我正在使用 ASIHTTPRequest 使用我的 iOS 应用程序中名为 submitUserCredentials 的方法执行异步 URL 请求。请求发送得很好,但问题是当从服务器返回响应时,设置了 ASIHTTPRequest,以便另一个方法 requestFinished 接收并返回它。

当 submitUserCredentials 是我首先从视图控制器运行的方法时,我如何获取 requestFinished 返回的服务器响应?

【问题讨论】:

    标签: objective-c asihttprequest


    【解决方案1】:

    您将 ViewController 设置为符合 ASIHTTPRequestDelegate 协议:

    @interface MyViewController : UIViewController <ASIHTTPRequestDelegate>
    

    然后,你实现

    -(void) requestFinished(ASIHTTPRequest *)request;
    

    ViewController 实现中的方法。现在,当请求完成时,将调用 ViewController 中的 requestFinished: 方法。如果您需要将信息与请求一起传递并使其在 requestFinished: 方法中可用,则可以将 ASIHTTPRequest 的 userInfo 属性设置为您喜欢的任何值,它将在 requestFinished 的请求参数中可用:

    对评论的回应:
    如果你愿意在收到响应之前阻塞你的线程,你可以使用 startSynchronous 方法(代码来自 ASI 站点http://allseeing-i.com/ASIHTTPRequest/How-to-use):

    [request startSynchronous];
    NSError *error = [request error];
    if (!error) {
      NSString *response = [request responseString];
    }
    

    这样,您的 submitUserCredentials 方法将等待服务器响应,但它会将服务器响应返回给该方法。如果在等待响应时阻止您的 UI 对您不起作用(并且可能不会),您可以启动一个新线程来运行您的 submitUserCredentials 方法,然后从那里调用 startSynchronous:

    [NSThread detachNewThreadSelector:@selector(submitUserCredentials:)
            toTarget:self withObject: credentials];
    

    【讨论】:

    • 感谢您的回答,汤姆!不过,我希望将与 ASIHTTPRequest 相关的所有内容都保留在执行请求的外部类中。那么有没有可能我可以让 submitUserCredentials 方法返回值,这样我在我的视图控制器中只需要处理响应而不是设置一个新方法?
    • @Wstr 你可以在你的外部类中实现requestFinished:——你只需要通知你的视图控制器响应已经到达。我建议将您的视图控制器设置为外部类的委托。当外部类通过requestFinished: 收到 HTTP 响应时,它会调用视图控制器应该实现的委托方法。这应该保持关注点分离干净。
    • @Chaitanya 好主意。我就是这样做的。
    【解决方案2】:

    您可以在这里提出一些不同的要求。我不知道它是哪一个。因此,我将尝试回答所有问题。


    是不是你不知道requestFinished 什么时候被调用?你是这样设置请求的委托的吗?

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];
    

    如果你这样做了,那么你应该为上面提到的self 实现requestFinished: 方法。


    您不确定如何在requestFinished: 中获取响应字符串?在这种情况下,解决方案很简单:

    - (void)requestFinished:(ASIHTTPRequest *)request
    {
       // Use when fetching text data
       NSString *responseString = [request responseString];
    
       // Use when fetching binary data
       NSData *responseData = [request responseData];
    }
    

    即请求的 responseStringresponseData 将为您提供所需的内容。


    或者您是说您想以某种方式处理submitUserCredentials 中的响应(可能是因为此方法的局部变量中有很多上下文)?如果是这样,那么您最好的选择可能是使用blocks

    - (IBAction)grabURLInBackground:(id)sender
    {
       NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
       __block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
       [request setCompletionBlock:^{
          // Use when fetching text data
          NSString *responseString = [request responseString];
    
          // Use when fetching binary data
          NSData *responseData = [request responseData];
       }];
       [request setFailedBlock:^{
          NSError *error = [request error];
       }];
       [request startAsynchronous];
    }
    

    或者问题是您希望 ASIHTTPRequest 以同步方式工作?在这种情况下,您可以这样做:

    - (IBAction)grabURL:(id)sender
    {
      NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
      ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
      [request startSynchronous];
      NSError *error = [request error];
      if (!error) {
        NSString *response = [request responseString];
      }
    }
    

    但不建议您这样做。这样做会挂起应用程序的主线程(假设您在主线程中进行调用),这不是一件好事。如果这确实是您正在寻找的答案,那么您可能需要阅读事件驱动编程。


    注意:以上所有代码示例均复制自 ASIHTTPRequest 的优秀“How to use it”文档页面。

    【讨论】:

      猜你喜欢
      • 2016-03-27
      • 1970-01-01
      • 2011-01-29
      • 2019-01-28
      • 2010-12-14
      • 2016-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多