2

我正在创建解析 Flickr API 照片响应的类 FlickrImage 的实例。该类有一个 getLocation 方法,它执行另一个 API 调用来获取地理位置:

NSLog(@"getting location for %i",self.ID);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
OFFlickrAPIRequest *flickrAPIRequest = [[OFFlickrAPIRequest alloc] initWithAPIContext[appDelegate sharedDelegate].flickrAPIContext];
[flickrAPIRequest setDelegate:self];

NSString *flickrAPIMethodToCall = @"flickr.photos.geo.getLocation";
NSDictionary *requestArguments = [[NSDictionary alloc] initWithObjectsAndKeys:FLICKR_API_KEY,@"api_key",self.ID,@"photo_id",nil];

[flickrAPIRequest callAPIMethodWithGET:flickrAPIMethodToCall arguments:requestArguments];
[pool release];

我已经实现了回调方法,该方法将捕获来自 API 的响应并使用地理位置数据更新 FlickrImage 实例 - 但它永远不会被调用。这是创建实例的位置:

NSDictionary *photosDictionary = [inResponseDictionary valueForKeyPath:@"photos.photo"];
NSDictionary *photoDictionary;
FlickrImage *flickrImage;
for (photoDictionary in photosDictionary) {
    flickrImage = [[FlickrImage alloc] init];
    flickrImage.thumbnailURL = [[appDelegate sharedDelegate].flickrAPIContext photoSourceURLFromDictionary:photoDictionary size:OFFlickrThumbnailSize];
    flickrImage.hasLocation = TRUE; // TODO this is actually to be determined...
    flickrImage.ID = [NSString stringWithFormat:@"%@",[photoDictionary valueForKeyPath:@"id"]];
    flickrImage.owner = [photoDictionary valueForKeyPath:@"owner"];
    flickrImage.title = [photoDictionary valueForKeyPath:@"title"];
    [self.flickrImages addObject:[flickrImage retain]];
    [flickrImage release];
    [photoDictionary release];
}

之所以存在,retain是因为我认为它可能有助于解决这个问题,但它没有——而且 NSMutableArray(flickrImages 是一个 NSMutableArray)是否仍然保留其成员?

编辑我应该补充一点,该getLocation方法(第一个代码片段)是在一个线程中启动的: [NSThread detachNewThreadSelector:@selector(getLocation) toTarget:self withObject:nil];

4

6 回答 6

2

您的委托方法永远不会被调用,因为永远不会发出请求。当您调用 时callAPIMethodWithGET:,它会将通信设置为在当前线程的运行循环上异步运行,然后立即返回。这样你就可以安全地在主线程上调用它而不会阻塞。

因为您是从自己创建的线程中调用该方法,所以它看不到主运行循环,而是看到新线程的运行循环。但是,因为您从不执行运行循环,所以永远不会发送消息,永远不会收到响应,并且永远不会调用您的委托。

可以通过调用[[NSRunLoop currentRunLoop] run]新线程来解决此问题。这将使工作发生。但在这种情况下,从一开始就永远不分离新线程会更容易。您的程序不会阻塞,并且您不必担心您的委托方法需要可重入。

于 2009-12-11T20:38:38.780 回答
1

在另一个线程上请求和解析 XML 时,我也遇到了这个问题,我的解决方案是这样做:

while([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:start] && !isFinished){

}

start = [NSDate dateWithTimeIntervalSinceNow:3];这基本上是一个超时,因此它不会永远存在,并且在isFinished我的解析完成时设置为 true。

于 2009-12-10T17:11:36.947 回答
0

好的,在上面的一些建议的帮助下,我确实解决了它。

  • 我确实删除了额外的retain内容,因为它确实造成了内存泄漏。它从一开始就看起来不太对劲,所以我对此的直觉是值得的,这是一件好事;)
  • 我删除了多余的线程,因为 API 调用已经是异步的,并且不需要额外的线程是非阻塞的。之后,回调方法被调用,但我遇到了关于对象保留的不同问题。如果有兴趣,你可能也想看看那个问题

谢谢大家。

于 2009-12-12T11:08:48.453 回答
0

您能否发布您已实现的回调方法 - 这可能只是一个简单的错字,因为OFFlickrAPIRequest如果委托未实现所需的回调,它似乎不会做任何事情。

您是否还实现flickrAPIRequest:didFailWithError:了查看 API 调用是否返回错误?

于 2009-12-11T14:36:41.320 回答
0

我不熟悉这些闪烁 API 包装器,但在这段代码中:

NSDictionary *requestArguments = [[NSDictionary alloc] initWithObjectsAndKeys:FLICKR_API_KEY,@"api_key",self.ID,@"photo_id",nil];

您确定 FLICKR_API_KEY 和 self.ID 都不为零吗?如果其中任何一个为 nil,您最终会得到一个字典,其中包含的项目少于您的预期。

于 2009-12-09T02:49:54.413 回答
-1

OFFlickrAPIRequest的setDelegate方法不会像应有的那样保留委托。这意味着只要请求存在(或修补类以正确拥有自己的引用),您就无法确保您的委托仍然存在。

于 2009-12-09T17:16:14.430 回答