在块方法IOS中读取多个数据

在块方法IOS中读取多个数据,ios,parse-platform,uiimage,Ios,Parse Platform,Uiimage,我试图通过以下方式从数据库下载一系列图像: - (void)dowloadAdditionalFileDataForFileObjectId:(NSString *)assignedObjectId andUserID:(NSString *)userID completition:(void (^) (BOOL success))block { if (userID != nil && assignedObjectId != nil) { PFQuery *query

我试图通过以下方式从数据库下载一系列图像:

- (void)dowloadAdditionalFileDataForFileObjectId:(NSString *)assignedObjectId andUserID:(NSString *)userID completition:(void (^) (BOOL success))block {
if (userID != nil && assignedObjectId != nil) {
    PFQuery *query = [PFQuery queryWithClassName:@"AdditionalFileData"];
    [query whereKey:@"fileAssignedObjectId" equalTo:assignedObjectId];
    [query whereKey:@"userID" equalTo:userID];

    [query findObjectsInBackgroundWithBlock: ^(NSArray *objects, NSError *error) {
        if (!error) {
            PFObject *object = [objects firstObject];

            dispatch_group_t group = dispatch_group_create();
            dispatch_group_enter(group);

            __block  UIImage *image1;
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            if (object[@"image1"] != nil)
                [self downloadDataForObject:object withParameter:@"image1" andCallback:^(NSData *data) {
                    image1 = [UIImage imageWithData:data];
                    dispatch_group_leave(group);
                }];
            });

            __block  UIImage *image2;
            if (object[@"image2"] != nil)
            [self downloadDataForObject:object withParameter:@"image2" andCallback:^(NSData *data) {
                image2 = [UIImage imageWithData:data];
            }];

            dispatch_group_wait(group,  DISPATCH_TIME_FOREVER);

            [DBManager storeAdditionalDataForFileWithObjectId:assignedObjectId forUserID:userID withImage1:image1 andImage2:image2 andImage3:image3 ...] local:NO completition: ^(BOOL finished) {
                if (finished)
                    block(YES);
                else
                    block(NO);
            }];
        }
        else
            block(NO);
    }];
}
else
    block(NO);
}

- (void)downloadDataForObject:(PFObject *)object withParameter:(NSString *)parameter andCallback:(void (^)(NSData *data))callback{
[object[[NSString stringWithFormat:@"%@", parameter]] getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
    callback(data);
}];
}
如果我只是写:

image1 = [UIImage imageWithData:[... getData]];
然后一切正常,但是用户界面被阻塞,直到过程结束
我想要一个系统,这样数据可以在后台下载。因为我可能有多于2个的图像,嵌套块解决不了任何问题。
我尝试使用上面的代码

有什么建议吗

编辑:

忘了明确提到所有下载方法,例如

getDataInBackground


调用解析SDK()。

杂项数据解决方案:

如果您愿意,您可以使用下载管理器来复制一些SDWebimages行为。另一种选择是AFNetworking,它可以帮助您以更简单的方式异步获取文件,并且文件状态为具有缓存。它们都可以在GitHub上获得


仅图像解决方案:

您可以使用SDWebImages这样的库来实现这一点。该库基本上为UIImageView提供了一个类别,支持来自web的远程图像。所有下载都是在后台完成的。它还保证您不会因为本地缓存而不断地下载同一个映像


杂项数据解决方案:

如果您愿意,您可以使用下载管理器来复制一些SDWebimages行为。另一种选择是AFNetworking,它可以帮助您以更简单的方式异步获取文件,并且文件状态为具有缓存。它们都可以在GitHub上获得


仅图像解决方案:

您可以使用SDWebImages这样的库来实现这一点。该库基本上为UIImageView提供了一个类别,支持来自web的远程图像。所有下载都是在后台完成的。它还保证您不会因为本地缓存而不断地下载同一个映像

这将阻塞直到完成:这不是一个异步操作

您在试图解决这个问题时似乎把自己弄得一团糟,代码也因此变得非常复杂,这可能对您没有多大帮助

如果
getDataInBackgroundithBlock
正在执行我想象中的操作,它将在数据可用时立即调用完成块。删除调度组并使用回调:让它们在共享方法中更新状态,一旦所有数据可用(即所有块都已触发)调用

如你所知,数据是可用的

这将阻塞直到完成:这不是一个异步操作

您在试图解决这个问题时似乎把自己弄得一团糟,代码也因此变得非常复杂,这可能对您没有多大帮助

如果
getDataInBackgroundithBlock
正在执行我想象中的操作,它将在数据可用时立即调用完成块。删除调度组并使用回调:让它们在共享方法中更新状态,一旦所有数据可用(即所有块都已触发)调用


正如您所知,数据是可用的。

尽管我认为您只需要在PFQuery上使用“includeKey”方法,但完整的查询应该看起来更像(参见includeKey部分):

@接口MyParseObject:PFObject
@财产(保留)NSArray*图像;
@结束
@MyParseObject的实现
@动态图像;
int已完成;
无效(^加载图像完成)(布尔成功);
-(void)loadImagesWithItemCompletion:(void(^)(UIImage*relatedImage))图像已完成和完成:(void(^)(BOOL success))处理已完成{
loadingImagesComplete=processCompleted;
完成=0;
PFQuery*queryForItems=[PFQuery queryWithClassName:@“yourClassName]”;
[查询项,其中key:@“yourKey”等于:@“yourValue”];
//这就是我想你要找的部分
//你问题中的问题包括
//**[查询includeKey:@“image1”]**;
//**[查询includeKey:@“image2”]**;
[查询项包括:@“图像”];
调度异步(调度获取全局队列(调度队列优先级默认为0)^{
用于(PFFile*imageFile在self.images中){
如果(!imageFile.isDataAvailable){
[imageFile GetDataInBackgroundithBlock:^(NSData*数据,NSError*错误){
imageCompleted([UIImage imageWithData:data]);//可能会为此回调到主队列
已完成++;
[自检加载完成];
}];
}否则{
imageCompleted([UIImage imageWithData:[imageFile getData]]);
已完成++;
[自检加载完成];
}
}
});
}
-(无效)检查加载已完成{
if(completed==self.images.count){
loadingImagesComplete(YES);//在更新任何UI元素时,此处调用的块应引用MainQueue
}
}
@结束
@其他类的实现
-(void)加载图像{
[self.myParseObject loadImagesWithItemCompletion:^(UIImage*relatedImage){
//这将在每次下载完图像时触发
}和完成:^(BOOL success){
//这将在下载完所有图像后触发
}];
}
@结束

虽然我认为您只需要在PFQuery上使用“includeKey”方法,但完整的查询应该看起来更像(参见includeKey部分):

@接口MyParseObject:PFObject
@财产(保留)NSArray*图像;
@结束
@MyParseObject的实现
@动态图像;
int已完成;
无效(^加载图像完成)(布尔成功);
-(void)loadImagesWithItemCompletion:(void(^)(UIImage*relatedImage))图像已完成和完成:(void(^)(BOOL success))处理已完成{
loadingImagesComplete=processCompleted;
完成=0;
PFQuery*queryForItems=[PFQuery queryWithClassName:@“yourClassName]”;
[疑问词在哪里
[UIImage imageWithData:] 
storeAdditionalDataForFileWithObjectId
@interface MyParseObject:PFObject<PFSubclassing>
@property (retain) NSArray *images;
@end

@implementation MyParseObject
@dynamic images;

int completed;

void (^loadingImagesComplete)(BOOL success);
- (void)loadImagesWithItemCompletion:(void(^)(UIImage *relatedImage))imageCompleted andCompletion:(void(^)(BOOL success))processCompleted{

    loadingImagesComplete = processCompleted;
    completed = 0;

    PFQuery *queryForItems = [PFQuery queryWithClassName:@"yourClassName"];
    [queryForItems whereKey:@"yourKey"  equalTo:@"yourValue"];



    //This is the part I THINK YOURE LOOKING FOR
    //THE QUERY IN YOUR QUESTION WOULD INCLUDE
    //**[query includeKey:@"image1"]**;
    //**[query includeKey:@"image2"]**;
    [queryForItems includeKey:@"images"];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for(PFFile *imageFile in self.images){
            if (!imageFile.isDataAvailable){
                [imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
                    imageCompleted([UIImage imageWithData:data]); //maybe callback to main queue for this
                    completed++;
                    [self checkLoadingCompleted];
                }];
            }else{
                imageCompleted([UIImage imageWithData:[imageFile getData]]);
                completed++;
                [self checkLoadingCompleted];
            }
        }
    });
}

- (void)checkLoadingCompleted{
    if(completed == self.images.count){
        loadingImagesComplete(YES);// the block called here should make reference to MainQueue when updating any UI Elements
    }
}
@end

@implementation SomeOtherClass
- (void)loadImages{
    [self.myParseObject loadImagesWithItemCompletion:^(UIImage *relatedImage) {
        //this will fire every time an image is done downloading
    } andCompletion:^(BOOL success) {
        //this will fire after all images are done downloading
    }];
}
@end
    // do your query
    PFObject *object = [objects firstObject];
    PFFile *file1 = object[@"image1"];
    PFFile *file2 = object[@"image2"];
    BFTask* task1 = [file1 getDataInBackground];
    BFTask* task2 = [file2 getDataInBackground];
    [BFTask taskForCompletionOfAllTasks:@[task1, task2]] continueWithBlock:^id(BFTask *task) {
        if(!task.error){
            UIImage* image1 = [UIImage imageWithData:task1.result];
            UIImage* image2 = [UIImage imageWithData:task2.result];
            // do your thing with the images
        }
        return nil;
    }];
#import "Superman.h"
Superman *downloadImages = [[Superman alloc] init];
[downloadImages setDownloads: @"http://...../image1.png", @"http://...../image2.png", @"http://...../image3.png", @"http://...../image4.png", nil];