简体   繁体   中英

Saving images from the internet to iPhone app

I have this code working when I build for debug on my phone and simulator (using iOS 4.0 on the simulator, and iOS 5.0 on my phone). However, whenever I do an ad hoc build and install that on my phone, it acts as if the images save, but displays a blank area where the image should be. So I don't think it's a permissions issue because I first check to see if there is an image file to display, and if not I display a default picture. So if it were a permissions issue, it wouldn't be able to save a file name for the code to think there is a file to display, and would display the default. Here is my current code:

+(void)downloadImage:(id)image_path {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];

    NSString *urlString = [NSString stringWithFormat: @"http://www.vegashipster.com/%@",image_path];                        
    NSData *imageData = [[NSData alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]]];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *libraryDirectory = [paths objectAtIndex:0];

    NSString *myFilePath = [libraryDirectory stringByAppendingPathComponent:image_path];
    NSString *hotelsPath = [libraryDirectory stringByAppendingPathComponent:@"images/hotels"];

    NSLog(@"saving jpg %@",myFilePath);
    UIImage *image = [[UIImage alloc] initWithData:imageData];//1.0f = 100% quality

    BOOL isDir;
    NSError *error;
    if (!([[NSFileManager defaultManager] fileExistsAtPath:hotelsPath isDirectory:&isDir] && isDir)) {
        if (![[NSFileManager defaultManager] createDirectoryAtPath:hotelsPath withIntermediateDirectories:true attributes:nil error:&error]){
            NSLog(@"%@",error);
        }
    }

    NSData *dataImage = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0f)];
    if (![[NSFileManager defaultManager] createFileAtPath:myFilePath contents:dataImage attributes:nil]){
        NSLog(@"Not Saved!!!!");
    }
  //  [dataImage writeToFile:myFilePath atomically:YES];

    NSLog(@"saving image done");

    NSString *alertString = [NSString stringWithFormat: @"urlString: %@ || hotelsPath %@",urlString,hotelsPath];

    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Alert" message:alertString delegate:self cancelButtonTitle:@"Close" otherButtonTitles:nil] autorelease];
    [alert show];

    [pool drain];
}

The UIAlertView is just in there so that I could see, in the ad hoc build, what was going on. I had placed one in the if statement saving the image (where it says NSLog(@"Not Saved!!!!"); ), as well as in the area to catch an error if the hotelsPath variable is not a directory that already exists (where it says NSLog(@"%@",error); ). The UIAlertView did not appear for those two areas.

Again, this code works when I build from x-code directly onto my phone for debugging, but not when I archive with ad hoc and create an ipa file to place directly onto my phone. I'm pretty new to iPhone development, and do not understand the differences in the builds to know what it could even possibly be.

Edit

Here is the code checking if the file exists:

NSString *image_path = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 5)];
if ([image_path isEqualToString:@""]) {
    hotel_image = [UIImage imageNamed:@"hdrHotels.jpg"];
}else{
    NSFileManager* fileManager = [NSFileManager defaultManager];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSString *libraryDirectory = [paths objectAtIndex:0];

    NSString *myFilePath = [libraryDirectory stringByAppendingPathComponent:image_path];

    BOOL fileExists = [fileManager fileExistsAtPath:myFilePath];

    if (fileExists){
        hotel_image = [UIImage imageNamed:image_path];
    }else{
        [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:[HotelsDetailsViewController class] withObject:image_path];

        hotel_image = [UIImage imageNamed:@"hdrHotels.jpg"];
    }
}

I check to see if the database has a file name for the image, then check if the image exists, and download it if not while showing the default image for the time being.

Update

I added some code to check the file size of the file path. Prior to saving the file, it is 0Kb. After saving the file, the image I checked was 96,077Kb. This was on my phone. On the simulator, which is working fine, the file size is showing the same image to be 97,696Kb. Could it be that the image is just not completely saving? Or is there a type of compression on the iPhone?

File Path Example

Here is a path this application would check for:

/var/mobile/Applications/APP-NUMB3R-1D/Library/images/hotels/96.jpg

And again, the first time the hotel is looked at, it shows the default image because this file path is not found. The next time, it shows a blank image, indicating that the file path was found. Also, when I check the file path for it's content size, the first time it is zero. The next time, it is around 100Kb. So something is definitely being written. And lastly, when I run this same code in debug mode on my actual phone, it works and displays the image. When I run it with my ad hoc build, it does not show the image.

EDIT

There may be yet another problem. I just found that after changing my code back, the images are NOT showing up after download on my iPhone with the debug build. I must have changed something else in all the testing that I need to fix again. A previous debug build on another phone here is still working correctly though, so at least I know I'm not losing my mind. ;)

I found this was because I had changed the variable names for my file path. Changed them back and it worked again.

  1. are you programming with ARC? If no, you should release "image", "imageData" and "alert"
  2. I think you misunderstood the usage of

    [UIImage imageNamed:name];

Apple UIIMage Docs :

The name of the file. If this is the first time the image is being loaded, the method looks for an image with the specified name in the application's main bundle.

Its the name of the Image in the Main Bundle not in the Library Folder

If you want to load a file from your Library folder you should use :

[UIImage imageWithContentsOfFile:path];

can you post a NSLog with the complete path for an image?

I am still thinking that the problem may be a permissions issue. This would mean that there is something wrong with your code that conditionally checks for an image. I have seen from experience that the only directory you are safe to save to on iOS is the documents directory. You can save a photo to the users photo library using the UIImageWriteToSavedPhotosAlbum function, but cannot do it through direct file I/O.

I believe this could be more tough to go through your code. Also at first look it seems that you are performing NETWORK ACTIVITY on main thread, which is NOT advisable.

But one of the best example i can give you is follow the link below. You will get exact solution to download the image in your app and also contains code to UnZip zipped file or you can do whatever you want to do with that...

Follow the link:

http://www.raywenderlich.com/4295/multithreading-and-grand-central-dispatch-on-ios-for-beginners-tutorial

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