ObjC委托方法永远不会被调用

时间:2009-12-08 23:52:42

标签: objective-c delegates callback retain

我正在创建解析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];

6 个答案:

答案 0 :(得分:2)

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

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

可以通过在新主题中调用[[NSRunLoop currentRunLoop] run]来解决此问题。这将使工作成功。 但是在这种情况下,首先永远不会分离新线程。您的程序不会阻塞,您也不必担心您的委托方法需要重入。< / p>

答案 1 :(得分:1)

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

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

}

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

答案 2 :(得分:0)

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

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

你确定FLICKR_API_KEY和self.ID都不是零吗?如果它们中的任何一个为零,那么你最终会得到一个字典,其中的项目数量少于你想要的数量。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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

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

谢谢大家。

答案 5 :(得分:-1)

OFFlickrAPIRequest的setDelegate方法不会像它应该保留委托。这意味着只要请求是(或修补类以正确拥有自己的引用),就会卡住以确保您的委托处于活动状态。