0

我的 iOS 应用程序出现了问题。

我正在向 Web api 发出请求,并且在后台线程中这样做。我有一个名为 Service 的类,它有这个方法:

- (void)searchForRoutesFrom:(NSNumber *)startStationId
                         to:(NSNumber *)endStationId
                   delegate:(id<WAMSServiceDelegate>)delegateOrNil
{
    RouteSearchRequest *request = [[RouteSearchRequest alloc] init];
    ...request populate ...
    [NSThread detachNewThreadSelector:@selector(searchForRoutesInTheBackground:) 
                             toTarget:self withObject:request];
}

- (void)searchForRoutesInTheBackground:(RouteSearchRequest *)request
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    ...make the request and call back...
}

这工作得很好,但是如果用户决定离开视图(使用这个服务),就在线程启动之前,服务对象被释放。当线程启动时,它将尝试调用 searchForRoutesInTheBackground 方法,我的应用程序将崩溃。

我可以使用哪些其他方法来运行此线程并处理正在释放的调用对象。

4

3 回答 3

0

但是如果用户决定离开视图(使用这个服务),就在线程启动之前,服务对象被释放。当线程启动时,它将尝试调用 searchForRoutesInTheBackground 方法,我的应用程序将崩溃。

这是不可能的。请参阅+detachNewThreadSelector:toTarget:withObject: 的文档。它说

对象 aTarget 和 anArgument 在分离线程执行期间被保留,然后被释放。

这意味着它在您调用时被保留detachNewThreadSelector:toTarget:withObject:。所以如果对象在那个时候是有效的,它将一直有效,直到新线程完成执行。

如果发生了不好的事情,那么您一定是在其他地方做错了内存管理。例如 1) 对象在detachNewThreadSelector:toTarget:withObject:被调用时已经被释放,或者 2) 您在其他不应该的地方过度释放对象。

于 2012-07-13T23:53:38.427 回答
0

您可以retain在启动线程之前调用对象,并在其处理结束时释放它(就在返回之前)。

 - (void)searchForRoutesFrom:(NSNumber *)startStationId
                     to:(NSNumber *)endStationId
               delegate:(id<WAMSServiceDelegate>)delegateOrNil
{
RouteSearchRequest *request = [[RouteSearchRequest alloc] init];
...request populate ...

[self retain];
[NSThread detachNewThreadSelector:@selector(searchForRoutesInTheBackground:) 
                         toTarget:self withObject:request];
}

- (void)searchForRoutesInTheBackground:(RouteSearchRequest *)request
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
...make the request and call back...

[self release];
}

如果您使用了块,这将自动为您完成,但保留/释放很容易管理这种情况。

于 2012-06-15T08:09:46.903 回答
0

由于您的逻辑信息不足,我不确定我是否会根据您的情况正确回答您,但是我以不同的方式处理这些情况。我所做的是创建单独的类(MVC 的模型),用于使用启动请求和处理回调的方法与 Web 服务进行通信。当回调执行时,有不同的场景 - (要么使用 CoreData 持久化结果并且我的 UI 捕获此事件并更新(如果可见),要么将块作为参数传递给发出请求的方法并在回调中被调用并执行该块,通常该块以if(!self.view.window) return;这意味着如果当前视图不可见,则不会发生任何事情)。但是在这两种情况下,我的请求和回调都完全独立于 UI,因此不会出现像你这样的问题。

于 2012-06-15T08:12:37.950 回答