Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从包含url';s到单元的图像视图-iOS Xcode Obj C_Ios_Objective C_Json_Image_Uitableview - Fatal编程技术网

从包含url';s到单元的图像视图-iOS Xcode Obj C

从包含url';s到单元的图像视图-iOS Xcode Obj C,ios,objective-c,json,image,uitableview,Ios,Objective C,Json,Image,Uitableview,为了更好地了解这篇文章的内容,它最终以以下问题结束: 如何从任意数量的url异步下载非预定义数量的图像,将它们添加到字典(或数组,如果更容易的话)中,以便按照下载开始的顺序添加它们,而不是按照下载完成的顺序添加它们 这是这篇文章的核心问题,但是为了更好地衡量并让人们真正理解我的意思,我在下面的文章中添加了我涉及这个问题的具体案例。我知道这很长,但解释我的案子很复杂 所以,这里什么都没有: 我有一个tableView,它可以从不同的数组加载一些东西。所有数组都是在每次启动应用程序时从JSON获取创

为了更好地了解这篇文章的内容,它最终以以下问题结束:

如何从任意数量的url异步下载非预定义数量的图像,将它们添加到字典(或数组,如果更容易的话)中,以便按照下载开始的顺序添加它们,而不是按照下载完成的顺序添加它们

这是这篇文章的核心问题,但是为了更好地衡量并让人们真正理解我的意思,我在下面的文章中添加了我涉及这个问题的具体案例。我知道这很长,但解释我的案子很复杂

所以,这里什么都没有:

我有一个tableView,它可以从不同的数组加载一些东西。所有数组都是在每次启动应用程序时从JSON获取创建的,其思想是我可以通过简单地更新JSON文本文件来更新应用程序中的信息。JSON文本文件中的一个条目包含指向图像的url,我想将其添加到tableView单元格的contentview中。我让JSON获取工作正常,并创建了一个包含获取信息的字典“dataDictionary”

然后,按如下方式创建阵列:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

   // Array is created from the dictionary created from the JSON fetch

    _dataArray = _dataDictionary[@"games"];

   // Arrays that will eventually hold info from JSON file is created

    _Titles = [[NSMutableArray alloc] init];
    _Descriptions = [[NSMutableArray alloc] init];
    _Date = [[NSMutableArray alloc] init];

    //images will be added to dictionary instead
    _imageDict = [[NSMutableDictionary alloc]init];


   // Info parsed from the JSON fetch, is now added to arrays

for (NSDictionary *eachData in _dataArray)
    {
        _Title = eachData[@"Title"];
        _Description = eachData[@"Description"];
        _Date = eachData[@"Release"];

   // Key for image url is created
        _image = eachData[@"ImageLink"];


        [_Titles addObject:_Title];
        [_Descriptions addObject:_Description];
        [_Dates addObject:_Date];
下面还有更多的代码,这就是我处理图像的地方(在这个简短的解释和下面的代码示例之后),您可以看到,我为JSON中的ImageLink条目指定了一个名为“image”的键。现在我调用这个方法,它开始异步下载图像:

- (void)downloadImageWithURL:(NSURL *)url completionBlock:(void (^)  (BOOL succeeded, UIImage *image))completionBlock
{
    NSMutableURLRequest *request = [NSMutableURLRequest    requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:^(NSURLResponse *response,  NSData *data, NSError *error) {
                               if ( !error )
                               {
                                   UIImage *image = [[UIImage alloc]  initWithData:data];
                                   completionBlock(YES,image);
                               } else{
                                   completionBlock(NO,nil);
                               }
                           }];


}
下面的代码中调用了此方法,因此要从前面继续代码:

// Just to be clear, we are now back in the "for (NSDictionary *eachData in _dataArray)" statement from the first code sample


//calling the above method here

[self downloadImageWithURL:[NSURL URLWithString:_image] completionBlock:^(BOOL succeeded, UIImage *image) {
            if (succeeded) {

//All this code runs when an image is successfully downloaded
NSLog(@"image download succesfull");

                UIImage *downloadedImage = [[UIImage alloc] init];

                // Doing this so I can resize the downloaded image to a proper size
                downloadedImage = image;

                //long boring code to resize image here


                UIImage *resizedImage = [[UIImage alloc] init];


                // resizedImage is as the name implies, the resized image that now has a proper size for the cell's content view



                 _number++; //Int that start out as -1, this increments each time an image is downloaded to allow the images to be added to the dictionary with the keys 0, 1, 2...

                // Wrapping the int in a NSNumber
                NSNumber *number = [NSNumber numberWithInt:_number];

                // Turning the NSnumber into a string
                NSString *key = [number stringValue];


                // Images finally being added to the dictionary, but, in the wrong "order" - or rather, with the wrong keys / numbers
                [_imageDict setObject:resizedImage forKey:key];




                //Update tableView when images are added to dictionary
                if (_imageDict.count == _gameTitles.count) {
                [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
                }


            }
        }];







      //Update tableView when data is added to array, this is to allow info to be shown even before the images are done downloading
        if (Titles.count == _dataArray.count) {


            // Update tableView with loaded content
            [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];

            }
        } // "for" statement ends here
}
总结一下最重要的部分:

在tableView中填充单元格时,我使用indexPath.row从每个数组中获取适当的信息。 图像下载后,我用0、1、2键将它们添加到字典中。。但是,当下载完成时,由于下载是异步的,下载不会按照初始化的顺序完成,相反,较小的图像会(毫不奇怪地)被下载并首先添加到图像字典中。这意味着图像的键不符合我所有其他数组中的顺序,因此在第一个单元格中使用indexath.row设置图像只是设置首先下载的图像,而不是首先开始的图像下载。基本上,即使首先下载了图像5,也应该添加键“4”,而不是“0”

我还应该提到,由于JSON获取,我不知道将提前下载多少图片,因为这可能会根据JSON而改变。这抵消了这里关于stackoverflow(以及其他地方)的许多答案

因此,所有这些文本和代码以及诸如此类的内容引出了一个开始的问题,我如何从任意数量的url异步下载非预定义数量的图像,将它们添加到字典(或数组,如果更简单的话)中,以便按下载开始的顺序添加它们,而不是按下载完成的顺序添加它们

非常感谢您花时间阅读本文

因此,所有这些文本和代码以及诸如此类的内容引出了一个开始的问题,我如何从任意数量的url异步下载非预定义数量的图像,将它们添加到字典(或数组,如果更简单的话)中,以便按下载开始的顺序添加它们,而不是按下载完成的顺序添加它们

您可以使用下载图像,它可以从给定的URL异步下载图像,还可以缓存图像并为您管理所有内容,它非常流行。您只需将以下代码添加到您的
-cellforrowatinexpath
委托方法:

[cell.imageView sd_setImageWithURL:[NSURL URLWithString:imageURLThatYouGetFromJSONResponse]
                  placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
另外,我建议您不要使用数组或字典。您可以将所有信息存储在一个对象中。在许多情况下,这是一种简单且最佳的做法,被称为面向对象的方法。您可以创建一个NSObject子类,并在其中创建属性“title”、“description”、“name”、“imageURL”。为了更好地理解,您可以遵循这些方法

您不关心图像的数量,因为您在
-numberofrowsinssection
中定义了行数,
-cellforrowtaindexpath
被称为您在
-numberofrowssection
中写入的时间。您可以添加:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    return [arrayOfYourObjects count];
}
编辑:如何在使用SDWebImage时操作图像

答:您可以使用SDWebImageManager,它还可以为您管理缓存

SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:imageURL
                      options:0
                     progress:^(NSInteger receivedSize, NSInteger expectedSize) {
                         // progression tracking code
                     }
                     completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
                         if (image) {
                             // Code to resize
                             //After resizing
                             cell.imageView.image = resizedImage;
                         }
                     }];

苹果公司提供了异步图像下载的示例代码,下载的顺序是初始化递归方法,所以可以开始第一个图像下载,下载完成后再开始第二个方法的下载。林克:我真的很喜欢这种方法,但是我现在已经太多地摆弄这种方法了,所以我真的希望它现在能起作用。。pandaren codemaster建议的SDWebImage库似乎更易于实现,特别是考虑到我已经编写的代码,但我将来可能会使用这种方法,这样我就可以更轻松地实现它,而不必重新思考我的代码;)不过还是要谢谢你!我不知道苹果公司已经制作了这样的示例代码。@Chikara你可以接受我的答案,如果这是你的解决方案,供将来参考。@pandarencodemaster dammit我一直认为是马来人Soni写的评论!我接受了你的回答,因为我很快就能用你的方法/答案让它按我所希望的那样工作。好吧,我让它工作了,但是我也希望它像以前那样调整图像的大小,在我将它们显示在表中之前,我如何能够操作这些图像?另外,我如何自动更新表格,这样您就不必先将单元格向外滚动,然后再进入视图,就可以将图像加载到单元格中?顺便说一句,感谢您对NSObject子类的介绍,我从来没有真正理解过NSObject是什么,现在我知道了;)另外,如何自动更新表格,