iPhone / Cocoa Touch - 多线程问题(Stanford Presence 3项目)

时间:2009-10-26 21:08:59

标签: iphone cocoa-touch multithreading nsoperation uiactivityindicatorview

我一直在解决斯坦福免费的iPhone课程项目Presence 3(在stanford网站上找到:www.stanford.edu/class/cs193p/cgi-bin/downloads.php,它从用户的twitter中提取数据,数据加载时可以看到UIActivityIndi​​cator(微调器)。加载数据后,TableView会在列表中显示带有照片的用户,并在单击用户单元格时显示用户状态。我可以成功地显示带有照片的TableView,并在点击时调出另一个具有状态的视图控制器。但是当我添加微调器时,我的程序崩溃。我设置的程序几乎与ThreadedFlickrTableView示例项目相同,也可以找到在上面的同一个链接(对不起,我是一个新用户,只能发布一个链接),这是有效的。我在我的代码中放置断点,看看问题出在哪里,我发现程序在加载时崩溃了cellForRowAtIndexPath方法中的单元格,具体为何时它正在从相应的数组中检索照片(followeesPhotoURLs)。这是因为数组是空的 - 从未下载照片,因为主线程决定在专用于从Internet下载的线程完成执行之前执行单元加载方法(它确实开始执行)。

我查看了审核员讨论组的页面,发现其他人有同样的问题,但是线程从未解决过这个问题,我通过电子邮件发送无效: http://groups.google.com/group/iphone-appdev-auditors/browse_thread/thread/ccfc6ae99b4cf45d/ef1b8935e749c7c2?hl=en&lnk=gst&q=presence3#ef1b8935e749c7c2

2 个答案:

答案 0 :(得分:1)

我的第一个UITableView规则永远不会报告未准备好的部分或行(有些东西,即使只是一个占位符),因为它每次都会崩溃。

在加载资源时,微调器正在旋转。因此,您正在等待可能准备或未准备好的资源,因为您不知道后台进程的确切状态。如何在主线程中设置一个值,指示事情尚未准备好。然后,当您的辅助线程完成加载时,您可以执行performSelectorOnMainThread以使某些主线程函数设置该值以指示您可以继续。在值继续之前,您的主线程不会尝试访问辅助线程可能正在触摸的那些值。在数据准备好之前,您的单元格可能会显示“加载”或类似信息,或者您只需在单元格准备就绪时添加它们。

还有一件事 - 主线程只能触及UI。除非明确说明,UIKit中的任何内容都不是线程安全的。进度指示器的更改必须由主线程处理,它应该启动指示器并将其停止(可能是当您的辅助线程通知“完成”时,如上所述)。

答案 1 :(得分:0)

我刚刚完成了今天的工作,这里是我观察到的一系列事件:

  1. 您的表视图将无法加载,因为您的数组不包含任何内容
  2. 您的主题将转到并检索Twitter数据
  3. 您的桌面视图将使用Twitter数据[self.tableView reloadData]
  4. 进行刷新

    如果您像我一样,则尝试使用与

    类似的设置来设置用户名
    cell.textLabel.text = [[userInfo objectAtIndex:indexPath.row] valueForKey:@"name"];
    

    我认为因为它非常具体,应用程序确实会尝试查找它,如果找不到任何内容则不会返回null,这与示例中的代码

    不同
    cell.text = [photoNames objectAtIndex:indexPath.row];
    

    ...所以当你第一次尝试使用空数组加载数据时,你的应用程序会出错。

    我解决这个问题的方法是创建一个数组,从一开始就从属性列表中加载用户名,这样我就知道在我的内容数组中应该有多少条目。关键部分是在设置单元格之前创建条件,以便您知道自己拥有所需的所有信息,例如......

        // Set up the cell...
    if ([userInfo count] == [userList count]) {
    

    userInfo是我的字典数组,其中包含来自Twitter的数据。

    userList是属性列表中的值数组。