【问题标题】:Use threading to wait for another class's method to execute, or is there a simpler way?使用线程等待另一个类的方法执行,还是有更简单的方法?
【发布时间】:2012-01-18 15:13:59
【问题描述】:

我以前从未接触过线程,从外观上看,我可能需要深入研究它们,但我想知道是否有更简单的解决方案来解决以下问题。

我基本上是在UITableView 中显示用户的 Facebook 好友列表。我有一个包含我所有 Facebook 方法的 FacebookWrapper 类,以及一个包含各种按钮/选项的 FacebookViewController。最后,有一个FriendsViewController 显示好友列表。用户可以通过FacebookViewController中的相关按钮选择显示男性朋友列表或女性朋友列表。

如果他们打男性朋友,我使用 FBL 创建一个查询字符串,我将其添加到字典中并用于返回男性朋友列表(全部在包装器中)。

[facebook requestWithMethodName:@"fql.query" andParams:dictionary andHttpMethod:@"GET" andDelegate:self];

包装类中的委托方法处理返回的FBRequest。我有以下方法来确定什么时候发生:

- (void)requestLoading:(FBRequest *)request {
    NSLog(@"Loading...");
}

- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
    NSLog(@"Response received");
}

- (void)request:(FBRequest *)request didFailWithError:(NSError *)error {
    NSLog(@"Request failed");
}

- (void)request:(FBRequest *)request didLoadRawResponse:(NSData *)data {
    NSLog(@"Request did load raw response");
}

但是,例如,当我点击“男性朋友”按钮时,我想等到生成响应后再推送FriendsViewController 并显示列表。就目前而言,FriendsVC 在请求返回列表之前被推送,所以我得到一个空白列表。在刷新表格并显示结果之前,我必须等待“请求确实加载了原始响应”。目前FacebookViewController中调用和显示好友列表的方法如下:

- (IBAction)friendsButtonPressed:(id)sender {
    int selectionTag = [sender tag];

    //Get access to the instance of the wrapper in the app delegate (since it needs to remain refereced after app exits to log in and returns
    MiniBfAppDelegate *appDelegate = (MiniBfAppDelegate *)[[UIApplication sharedApplication] delegate];
    [appDelegate.facebookWrapper loadListDataFor:selectionTag];

    //Initialise the friends view controller
    FriendsViewController *friendsViewController = [[FriendsViewController alloc] init];

    //NEED TO WAIT UNTIL LISTDATA IS RETURNED?

    //Give the friends view controller the list data
    friendsViewController.listData = appDelegate.facebookWrapper.friendsList;

    //Push the friends view controller
    friendsViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    [self.navigationController pushViewController:friendsViewController animated:YES];
    [friendsViewController release];
}

因此,理想情况下,我希望在等待包装器返回列表时显示一个加载符号,一旦完成,推送 FriendsViewController 以便立即填充它。那么我需要使用线程还是有更简单的方法?

也许这是在回答我自己的问题,也可能是我在这里没有掌握一个基本概念,但是除了在我的 App Delegate 中创建 FriendsVC 的实例之外,还有什么方法可以发送当前的实例化来自 Wrapper 类的消息?所以我可以在包装器的request: didLoadRawResponse: 方法中将它告诉refresh,即在生成列表时。

【问题讨论】:

    标签: objective-c multithreading facebook cocoa-touch ios4


    【解决方案1】:

    我不确定我是否理解您的问题,但您可能需要查看 NSNotificationCenter。您可以使用它向您的控制器发送消息,这是触发通知的示例:

    [[NSNotificationCenter defaultCenter] postNotificationName:@"myNotificationName" 
                                                            object:self 
                                                          userInfo:[NSDictionary dictionaryWithObject:XXXX forKey:@"someObject"]];
    

    如您所见,您甚至可以向它发送参数。在目标控制器中,您只需注册一个观察者来响应这些消息:

    [[NSNotificationCenter defaultCenter] addObserver: self
                                                 selector: @selector(yourMethodHere:) 
                                                     name: @"myNotificationName"
                                                   object: nil];
    

    问候!

    【讨论】:

    • 嗯,这几乎奏效了。它现在一直等到通知才加载 FriendsVC,但它仍然第一次加载空白......直到我返回并再次按下按钮。我在输出中也遇到了这些错误:嵌套推送动画可能导致导航栏损坏,在意外状态下完成导航转换。导航栏子视图树可能会损坏,并且对 的开始/结束外观转换的不平衡调用。正如它所描述的那样,导航栏似乎重复了。这和通知有关吗?
    • 实际上我似乎已经通过在 FriendsVC 加载时删除观察者来删除这些错误 ([[NSNotificationCenter defaultCenter] removeObserver:self name:@"ListReady" object:nil];) 它仍然没有第一次加载列表...将继续调查,但看起来不错,谢谢。
    • 哦,我发现了问题 - 我是从请求 didReceiveResponse 方法而不是 request: request didLoad: 方法发送通知。现在一切都很好 - 谢谢!
    【解决方案2】:

    这很简单。将您的 VC 加载代码放入 didReceiveResponce 方法中。并在 didFailWithError 中显示 UIAlertView。

    - (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response {
        NSLog(@"Response received");
    
        //Give the friends view controller the list data
        friendsViewController.listData = appDelegate.facebookWrapper.friendsList;
    
        //Push the friends view controller
        friendsViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
        [self.navigationController pushViewController:friendsViewController animated:YES];
        [friendsViewController release];
    }
    

    【讨论】:

    • 除了包含 didReceiveResponse 方法的包装类没有将 FriendsVC 推送到其上的 navigationController...?
    • 或者有没有办法从包装类的实例中访问当前的导航控制器?
    • 这是你的包装类。所以你可以在这个类中添加导航控制器的属性。并在 FriendsVC 中创建包装类时填充它。
    • 甚至更灵活。您可以为 Wrapper 设置 onSuccess 和 onFail 块。并从 FriendsVC 中填充这些块,以便导航控制器可用并且代码看起来简洁明了。
    • wrapper.successBlock = ^{ friendsViewController.listData = appDelegate.facebookWrapper.friendsList; friendsViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; [self.navigationController pushViewController:friendsViewController animated:YES]; [friendsViewController release]; }; 之类的东西,然后在包装器中运行它。 successBlock(); 你应该阅读 obj-c 中的 Blocks 以获得更多细节。他们真的很强大。
    猜你喜欢
    • 1970-01-01
    • 2012-07-10
    • 1970-01-01
    • 2012-06-15
    • 2015-02-22
    • 2012-07-07
    • 2015-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多