简体   繁体   中英

Storing and retrieving images from documents directory in tableView?

I am trying to store images from webservice in documents directory.For a stored image I want to load it from documents directory in table view. The images are accessible from a url such as :- http://Address/App/User/Image/Puegeot_E7

Fetching from webservice is successful however from the documents directory I keep getting null image.Can't seem to find what's wrong here.

- (void)saveImage:(UIImage*)image withName:(NSString *)imageName
{
    if (image != nil)
    {
        NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString* path = [documentsDirectory stringByAppendingPathComponent:imageName];

        NSLog(@"Saving path %@",path); // Saving path /Users/computername/Library/Developer/CoreSimulator/Devices/7277F3D3-298C-451A-8607-8070A08650C7/data/Containers/Data/Application/D3AF4DD9-A4CD-42C8-A8EB-0F15C271EE61/Documents/CabImage/Puegeot_E7

        NSData* data = UIImagePNGRepresentation(image);
        [data writeToFile:path atomically:YES];
    }
}

- (UIImage *)getImageFromURL:(NSString *)fileURL
{
   NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                     NSUserDomainMask, YES);
   NSString *documentsDirectory = [paths objectAtIndex:0];
   NSString *path = [documentsDirectory stringByAppendingPathComponent:fileURL];
   NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:path]];
   NSLog(@"data %@",data); //This returns (null)
   UIImage *result = [UIImage imageWithData:data];
   return result;
}

In tableView this is how I am trying to load from documents directory.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   //default initialisation stuff
   NSDictionary *obj = [responseArray objectAtIndex:indexPath.row];
   cell.imgVW.image = [UIImage imageNamed:@"default-car.png"];
   NSString *imgPath = obj[@"cabimage"];
   NSLog(@"imgPath : %@",imgPath); // imgPath : Image/Puegeot_E7 
   UIImage *imgFromDisk = [self getImageFromURL:imgPath];
   NSLog(@"imgFromDisk - %@",imgFromDisk); -> (null)
   if (imgFromDisk) 
   {
       cell.imgVW.image = imgFromDisk;
   }
   else
   {
       //download
       NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@User/%@",BASE_URL,imgPath]];

       self.task = [self.session downloadTaskWithURL:imageURL 
                   completionHandler:^(NSURL *location,NSURLResponse *response,NSError *error)
       {
            NSData *img_data = [NSData dataWithContentsOfURL:imageURL];
            if (img_data) 
            {
                 UIImage *img = [UIImage imageWithData:img_data];
                 dispatch_async(dispatch_get_main_queue(), ^{
                    ListCell *cell = (id)[tableView cellForRowAtIndexPath:indexPath];
                    cell.imgVW.image = img;                                 
                    [self saveImage:img withName:imgPath];

                });
            }
       }];
       [self.task resume];
   }
}

The problem seems apparent from what you're seeing in the logs:

NSLog(@"imgPath : %@",imgPath); // imgPath : Image/Puegeot_E7

That path isn't in the documents directory.

To get firmer control of this, have the save method return the path to where the image was saved:

- (NSString *)saveImage:(UIImage*)image withName:(NSString *)imageName{
    // op code, then:
    return path;
}

Test that you can read back an image. (This code is for test, not for the app).

UIImage *testImage = [UIImage imageNamed:@"some_test_image"];
NSString *path = [self saveImage:testImage withName:@"test_name"];
UIImage *didItWork = [self getImageFromURL:path];
NSLog(@"did it work? %@", didItWork);

Back to the real app... After the path returned from writing the image in your model:

UIImage *downloadedImage = // however you get this
NSString * downloadedImageName = // however you get this
NSDictionary *obj = [responseArray objectAtIndex:indexPath.row];
obj[@"cabbage"] = [self saveImage: downloadedImage withName:downloadedImageName];

Now we know that your cellForRowAtIndexPath method will see the saved path, and we know from the test that image creation from that path will work.

You're getting nil because you're not providing the correct path where to retrieve the image. You just use the name of the image but you should use the same path as where you saved it.

So put:

NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:imageName];

In your getImageFromURL method.

Do not just use the image name to retrieve your image. Hope this helps!

(Sorry for the bad layout of my text, I'm typing on my phone)

To start with, I recommend you use SDWebImage library - an asynchronous image downloader with cache support. Usage is easy enough:

[cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                      placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                             completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
                                ... completion code here ...
                             }];

However, if you wish to do it your own way. You should change thess 2 line of code:

UIImage *imgFromDisk = [self getImageFromURL:imgPath];

into this:

UIImage *imgFromDisk = [self getImageFromURL:[imgPath lastPathComponent]];

and

[self saveImage:img withName:imgPath];

into this:

[self saveImage:img withName:[imgPath lastPathComponent]];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM