1

I'm making an iOS 6 program which downloads JSON data from a website and displays it in a table view. I added a pull to refresh method witch works fine. I can go in the settings view controller (secondViewController) and change the address, everything works. Then, I use the pull to refresh method and my tableView is reloaded. But if I reload 3 times AFTER changing the address, my app crashes. I get this error :

*** Terminating app due to uncaught exception 'NSRangeException', 
reason: '*** -[__NSArrayM objectAtIndex:]: index 10 beyond bounds for empty array'
*** First throw call stack:
(0x1ca1012 0x10dee7e 0x1c430b4 0x3084 0xdd8fb 0xdd9cf 0xc61bb 0xd6b4b 0x732dd 0x10f26b0   0x229dfc0 0x229233c 0x2292150 0x22100bc 0x2211227 0x22bb333 0x22bb75f 0x1c60376 0x1c5fe06 0x1c47a82 0x1c46f44 0x1c46e1b 0x1bfb7e3 0x1bfb668 0x22ffc 0x1fbd 0x1ee5)
libc++abi.dylib: terminate called throwing an exception

What am I doing wrong ? And how can I fix that problem ? Thanks for your help !

4

1 回答 1

0

跳出的关键设计考虑因素是您的retreiveData方法显然是citiesArray异步更新模型(the ),这意味着在发生这种情况时与 tableview 的任何交互都可能失败。您永远不应该异步更新实际citiesArray本身。该数组的更新应该发生在主队列中。

您应该更改retrieveData为不触及现有的citiesArray,而是创建并返回一个新数组,然后在您分派回主队列的代码中,然后替换现有的citiesArray和调用reloadData,例如:

- (void)refresh:(UIRefreshControl *)refreshControl {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSArray *newCitiesArray = [self retreiveData];

        dispatch_async(dispatch_get_main_queue(), ^{

            if (newCitiesArray) {

                // you presumably only want to reload the data if `retrieveData` was successful

                citiesArray = newCitiesArray
                [myTableView reloadData];
            }

            [refreshControl endRefreshing];
        });
    });
}

显然,这也将涉及对 的一些更改retrieveData,但希望这是不言自明的。如果没有,请使用该代码更新您的问题,我们可以提出进一步的建议。但我们真的不需要去那里,因为我怀疑你理解那里需要发生的变化。

您可能还想解决其他更微妙的问题,例如考虑是否真的要使用并发的全局队列(例如,如果您在前一次刷新时点击刷新,您真的想要两个查询吗?与您的服务器同时进行......因为您将更新发送回主队列,您不会崩溃,但效率低下,您无法保证它们完成的顺序等)。您可能还想NSOperationQueue在其中编写代码以允许取消先前的请求等。

但是所有这一切都有点复杂,并且是您的主要问题(崩溃)的次要问题。如上所述,重构retrieveData代码以确保您不触摸它本身应该解决这个问题。citiesArray

于 2013-07-30T14:59:23.087 回答