【问题标题】:How to create an array of UIImages如何创建 UIImages 数组
【发布时间】:2015-08-08 19:26:48
【问题描述】:

我正在从 Parse 数据库中存储图像,如下所示:

PFFile *firstImageFile = self.product[@"firstThumbnailFile"];
[firstImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
    if (!error) {
        self.firstImage = [UIImage imageWithData:imageData];
    }
}];

我想将图像保存为数组以在滚动视图中显示它们。

如果我这样做,它会起作用:

self.galleryImages = [NSArray arrayWithObjects: [UIImage imageNamed:@"s2.jpg"], [UIImage imageNamed:@"s1.jpg"], nil];

但如果我尝试使用 UIImage 本身,则不会出现任何图像。

self.galleryImages = [NSArray arrayWithObjects: self.firstImage, self.secondImage, nil];

有什么帮助吗?谢谢。

【问题讨论】:

  • 您确定self.firstImageself.secondImage 在您尝试创建数组时不为零吗?
  • 看起来不像。我怎样才能确定不是零? @rmaddy
  • 查看调试器中的值或在创建数组之前记录它。
  • 不是,很可能是因为getDataInBackgroundWithBlock。如何设置我的代码,以便它首先保存 PFFile,然后将其分配给数组? @rmaddy
  • 您最后的评论令人困惑。 self.firstImage 在您创建数组时是否为零?你说不是,但评论的其余部分暗示它是nil

标签: ios objective-c parse-platform uiimage


【解决方案1】:

这是一个常见问题的形式:如何执行许多异步操作(没有深度嵌套的完成块)并知道它们何时完成。我使用的方法是将操作的参数视为待办事项列表,并构建一个递归处理列表的方法....

- (void)loadPFFiles:(NSArray *)array filling:(NSMutableDictonary *)results completion:(void (^)(BOOL))completion {
    NSInteger count = array.count;
    // degenerate case is an empty array which means we're done
    if (!count) return completion(YES);

    // otherwise, do the first operation on the to do list, then do the remainder
    PFFile *file = array[0];
    NSArray *remainder = [array subarrayWithRange:NSMakeRange(0, count-1)];

    [file getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
        if (!error) {
            UIImage *image = [UIImage imageWithData:imageData];
            results[file.name] = image;
            [self loadPFFiles:remainder filling:results completion:completion];
        } else {
            completion(NO);
        }
    }];
}

这样称呼它(稍微猜测一下你的模型):

NSArray *pfFiles = @[ self.product[@"firstThumbnailFile"], self.product[@"secondThumbnailFile"] ];
NSMutableDictionary *result = [@{} mutableCopy];

[self loadPFFiles:pfFiles filling:result completion:^(BOOL success) {
    if (success) {
        // result will be an dictionary of the loaded images
        // indexed by the file names
    }
}];

【讨论】:

    【解决方案2】:

    我猜(根据您上面关于 nil 的 cmets)您的代码看起来有点像这样:

    PFFile *firstImageFile = self.product[@"firstThumbnailFile"];
    [firstImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
        if (!error) {
            self.firstImage = [UIImage imageWithData:imageData];
        }
    }];
    
    self.galleryImages = [NSArray arrayWithObjects: self.firstImage, self.secondImage, nil];
    

    如果是这种情况,请将数组初始化移动到完成块内,如下所示:

    PFFile *firstImageFile = self.product[@"firstThumbnailFile"];
    [firstImageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
        if (!error) {
            self.firstImage = [UIImage imageWithData:imageData];
    
            dispatch_async(dispatch_get_main_queue(), ^{
    
                    self.galleryImages = [NSArray arrayWithObjects: self.firstImage, self.secondImage, nil];
                });
        }
    }];
    

    在第一种(您的)情况下发生的情况是数组初始化语句在完成块之前运行,因此当实际设置“第一个图像”时为时已晚,因为数组已经初始化。

    【讨论】:

    • 我认为您的想法是正确的,但是没有必要在完成块中分派到主节点......没有它,它将在主节点上运行。更重要的是,self.secondImage 假设它与第一张图像处于相同的状态,也将为 nil。它也是,必须加载。一种常见的方法是将第二个加载嵌套在第一个加载的完成块中,这对于少量固定数量的操作来说很好。我建议采用更通用的方法。
    猜你喜欢
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多