草庐IT

ios - 在异步 REST 请求的 block 内调用 self

coder 2024-01-19 原文

当它在 withBlock block 内时,我无法调用 [self userLoggedIn]。它被调用但不显示 TITHomeViewController。如果我将它移到 block 的下方和外部,那么它就可以正常工作。显然,我希望从 withBlock 中调用它,因为它是异步 REST 请求的完成处理程序。

- (void)doAuth
{
    // Call the Facebook API /me method
    [FBRequestConnection startForMeWithCompletionHandler:
     ^(FBRequestConnection *connection, id result, NSError *error)
     {
         // Populate global Facebook user info
         self.fbAccessToken = [[[FBSession activeSession] accessTokenData] accessToken];
         self.fbUserID = [result objectForKey:@"id"];

         // Authenticate with the Titter API
         [self callAPI:@"auth" withBlock:^(NSDictionary *jsonData) {
             NSString *_id = [jsonData objectForKey:@"_id"];
             if (_id != nil) {
                 self.userID = _id;
                 [self userLoggedIn];
             }
         }];
     }];
}

- (void)userLoggedIn
{
    // Display the home view.
    self.window.rootViewController = [[TITHomeViewController alloc] initWithNibName:@"TITHomeViewController" bundle:nil];
}

- (void)callAPI:(NSString *)path withBlock:(void (^)(NSDictionary *jsonData))block
{
    // Initialize the API callback URL using global root and given path
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", apiRoot, path]];

    // The Titter API requires an authorization header formatted as [userID]@[accessToken]
    NSString *authorizationHeader = [NSString stringWithFormat:@"%@@%@", self.fbUserID, self.fbAccessToken];

    // Create the request and add our authorization header
    NSMutableURLRequest *restRequest = [[NSMutableURLRequest alloc] initWithURL:url];
    [restRequest addValue:authorizationHeader forHTTPHeaderField:@"authorization"];

    // Queue required for calling sendAsynchronousRequest
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // Make an asynchronous request to our API and if there is no errors, return formatted JSON data to the passed block.
    [NSURLConnection
     sendAsynchronousRequest:restRequest
     queue: queue
     completionHandler:^(NSURLResponse *response,
                         NSData *data,
                         NSError *error) {
         if ([data length] >0 && error == nil) {
             NSLog(@"Succeeded! Data as string: %@", [NSString stringWithUTF8String:[data bytes]]);

             // Convert received JSON data into a NSDictonary object.
             NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];

             // Call back the block passed in.
             block(result);
         }
         else if ([data length] == 0 && error == nil) {
             NSLog(@"Nothing was downloaded.");
         }
         else if (error != nil) {
             NSLog(@"Error = %@", error);
         }
     }];
}

最佳答案

上面的评论线程让您完成了大约 90% 的事情! UI 在主线程上运行,对它的任何更新都应该在 UI 线程上进行。您可以通过在主线程上调用 usedLoggedIn 在 block 代码中修复此问题:

dispatch_async(dispatch_get_main_queue(), ^{
  [self userLoggedIn];
});

还值得注意的是,您可能在 block 内使用self 时遇到问题:如果self 消失,此 block 将失败。在此用例中,这可能不是问题。您没有提及此代码来自哪个类:如果它来自 View Controller ,则可以安全地假设它不会去任何地方。但是,如果它是一个辅助对象或类似的东西,它可能会在请求 URL 时(或在该逻辑中的某个地方)从你下面消失。创建对 self 的弱引用以在 block 内使用是一种常见的做法,如下所示:

// Outside the block
MyViewController __weak *weakSelf = self;

// Inside the block
[weakSelf userLoggedIn];

关于ios - 在异步 REST 请求的 block 内调用 self,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23372265/

有关ios - 在异步 REST 请求的 block 内调用 self的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  4. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  5. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  6. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  7. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  8. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  9. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  10. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

随机推荐