我的实施遇到了一些问题,我真的不知道如何解决。请你指教。
我尝试使用一个类方法实现NSManagedObject类别类Photo + Flickr.m +(void)photoWithFlickrData:inManagedObjectContext:
我想要做的是使用NSURLSessionDownloadTask从Flickr API下载数据,然后创建Photo对象并将这个新创建的对象插入数据库(如果它还没有存在)。这部分工作正常。
最后我想返回新创建的(或在db中找到的对象)Photo对象。这就是我遇到问题的地方。由于我使用类别I,因此无法使用实例变量。我无法找到任何好的解决方案来从此completionHandler块中获取此Photo对象。
我的代码:
@implementation Photo (Flickr)
+ (void)photoWithFlickrData:(NSDictionary *)photoDictionary
inManagedObjectContext:(NSManagedObjectContext *)context
{
NSString *placeId = [photoDictionary valueForKeyPath:FLICKR_PHOTO_PLACE_ID];
NSURL *urlInfoAboutPlace = [FlickrFetcher URLforInformationAboutPlace:placeId];
NSURLRequest *request = [NSURLRequest requestWithURL:urlInfoAboutPlace];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSURLSessionDownloadTask *task =
[session downloadTaskWithRequest:request
completionHandler:^(NSURL *localfile, NSURLResponse *response, NSError *error) {
if(!error) {
NSData *json = [NSData dataWithContentsOfURL:localfile];
NSDictionary *flickrPlaceDictionary = [NSJSONSerialization JSONObjectWithData:json
options:0
error:NULL];
dispatch_async(dispatch_get_main_queue(), ^{
Photo *photo = nil;
// flickr photo unique id
NSString *uniqueId = [photoDictionary valueForKeyPath:FLICKR_PHOTO_ID];
NSFetchRequest *dbRequest = [NSFetchRequest fetchRequestWithEntityName:@"Photo"];
dbRequest.predicate = [NSPredicate predicateWithFormat:@"uniqueId = %@", uniqueId];
NSError *error;
NSArray *reqResults = [context executeFetchRequest:dbRequest error:&error];
if (!reqResults || error || [reqResults count] > 1) {
//handle error
} else if ([reqResults count]) {
//object found in db
NSLog(@"object found!");
photo = [reqResults firstObject];
} else {
//no object in db so create a new one
NSLog(@"object not found, creating new one");
photo = [NSEntityDescription insertNewObjectForEntityForName:@"Photo"
inManagedObjectContext:context];
//set its properties
photo.uniqueId = uniqueId;
photo.title = [photoDictionary valueForKey:FLICKR_PHOTO_TITLE];
photo.region = [FlickrFetcher extractRegionNameFromPlaceInformation:flickrPlaceDictionary];
NSLog(@"title: %@", photo.title);
NSLog(@"ID: %@", photo.uniqueId);
NSLog(@"region: %@", photo.region);
}
});
}
}];
[task resume];
//how to get Photo *photo object???
//return photo;
}
我真的很感激有关如何实现这一点的任何建议。
答案 0 :(得分:2)
由于您在块中发生了异步操作,因此您需要将完成处理程序(块)传递给photoWithFlickrData:inManagedObjectContext:
方法,并在拥有有效的照片数据时调用它。
您需要在方法中添加一个新参数,以便传入完成处理程序。我会做这样的事情:
+ (void)photoWithFlickrData:(NSDictionary *)photoDictionary
inManagedObjectContext:(NSManagedObjectContext *)context
withCompletionHandler:(void(^)(Photo *photo))completionHandler
然后,当您拥有有效的photo
个对象时,请像这样致电completionHandler
:
completionHandler(photo);
看起来你想把它放在你传递给dispatch_async
的街区的最后:
/* ... */
dispatch_async(dispatch_get_main_queue(), ^{
Photo *photo = nil;
/* ... */
completionHandler(photo);
});
/* ... */
然后,您可以这样调用您的方法:
[Photo photoWithFlickrData:photoDictionary
inManagedObjectContext:context
withCompletionHandler:^(Photo* photo) {
/* use your valid photo object here */
}
];
答案 1 :(得分:-1)
在致电[session downloadTaskWithRequest:.....]
之前,在您的街区之外定义一个像这样的变量
__block Photo *photoObject = nil;
然后在完成设置其属性后在块内,设置
photoObject = photo;
现在,您可以使用块外的photoObject
变量执行任何操作。
查看this Apple developer documentation on Blocks and Variables。