iOS - Can't Display Downloaded Image - ios

I am downloaded images using the below code, but whenever I try to display them nothing shows up. I have tested the downloading of the images to my desktop from the app (in simulator) and all the images are created just fine. So I know they are being saved into the App's Documents directory.
Any ideas on what I am doing wrong?
Download Image Code:
-(void)saveThumbnails:(NSMutableArray *)thumbnails{
for(NSNumber *videoID in thumbnails){
// Get an image from the URL below
NSURL *thumbnailURL = [self generateThumbnailURL:[videoID intValue]];
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:thumbnailURL]];
NSLog(#"%f,%f",image.size.width,image.size.height);
// Let's save the file into Document folder.
// You can also change this to your desktop for testing. (e.g. /Users/kiichi/Desktop/)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);//Find Application's Document Directory
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"DownloadedThumbnails"];
// NSString *dataPath = #"/Users/macminidemo/Desktop/gt";//DEBUG SAVING IMAGE BY SAVING TO DESKTOP FOLDER
//Check if Sub-directory exists, if not, try to create it
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath]){
NSError* error;
if([[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]){
NSLog(#"New Folder Created!");
}
else
{
NSLog(#"[%#] ERROR: attempting to write create new directory", [self class]);
NSAssert( FALSE, #"Failed to create directory maybe out of disk space?");
}
}
NSArray *splitFilename = [[self generateThumbnailFilename:[videoID intValue]] componentsSeparatedByString:#"."];//Break Filename Extension Off (not always PNGs)
NSString *subString = [splitFilename objectAtIndex:0];
NSString *formattedFilename = [NSString stringWithFormat:#"%#~ipad.png",subString];
NSString *localFilePath = [dataPath stringByAppendingPathComponent:formattedFilename];
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(image)];
[imageData writeToFile:localFilePath atomically:YES];
NSLog(#"Image: %# Saved!",formattedFilename);
}
}
Display Image Code:
if(currentVideo.thumbnail!=(id)[NSNull null] || ![currentVideo.thumbnail isEqualToString:#"missing_image.png"]){
NSArray *splitFilename = [currentVideo.thumbnail componentsSeparatedByString:#"."];//Break Filename Extension Off (not always PNGs)
NSString *subString = [splitFilename objectAtIndex:0];
NSString *formattedFilename = [NSString stringWithFormat:#"%#~ipad.png",subString];
UIImage *thumbnailImage = [UIImage imageNamed:formattedFilename];
NSLog(#"Image Name: %#",formattedFilename);
[videoThumbnail setImage:thumbnailImage];
[buttonVideo addSubview:videoThumbnail];
}else{
UIImage *thumbnailImage = [UIImage imageNamed:#"video-details-thumbnail"];
[videoThumbnail setImage:thumbnailImage];
[buttonVideo addSubview:videoThumbnail];
}
*And there are no issues displaying the buttonVideo or anything like that. I have tested just setting a test image and that one display just fine (i.e. the "else" statement when run individually works just fine using the default thumbnail)

The documentation for imageNamed says that it works with files that are in the app's main bundle. This suggests to me that it's only appropriate for images that are supplied as in-app resources. Try imageWithContentsOfFile: to get at the content of the documents directory.

Related

Image written through WriteToFile command is missing after app rerun

I am writing an app which downloads image from my server and stores them locally for offline viewing. The codes I use to store the image locally are shown below. Apart from storing the image, I am also able to read the image from the path (which I stored separately).
However when I re-run my code from Xcode to the iPhone (without uninstalling the app from the phone), the stored image file would be missing. Is this expected? Would I face similar issue when my app has been released on App Store and when the user updates the app? Is there a way to keep the file persistent when I re-run them when I update some codes in Xcode?
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imagePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"file.jpeg",]];
if (![imageData writeToFile:imagePath atomically:YES])
{
// Handling when there is an error
NSLog(#"Failed to store file at path %#",imagePath);
stored.text = #"";
}
else
{ // Handling when write is successful
NSLog(#"Imaged stored path is %#",imagePath);
stored.text = imagePath;
}
[imageView setImage:image];
The code to read the image is shown below:
NSString *imagePathToRead = stored.text;
NSLog(#"Retrieve image from %#",imagePathToRead);
UIImage *image = [UIImage imageWithContentsOfFile:imagePathToRead];
[imageView setImage:image];
I am posting the answer here from rmaddy which solved the issue I was facing. I am posting here so that others can benefit if they are facing similar issue.
For the storing portion:
The stored.text should never store the full path:
stored.text = imagePath;
Instead I should store #"file.jpeg" only.
For the Read portion:
I should always regenerate the full path below when I wanted to read the path instead of the code below:
NSString *imagePathToRead = stored.text;
The corrected codes are:
NSString *imagePathToRead = stored.text;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imagePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:imagePathToRead]];
NSLog(#"Retrieve image from %#",imagePath);
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
This solved the issue and the image is able to be read even though the app is re-installed through Xcode.

iPhone - Add UIImage to Folder

I have a folder called PhotoSet in my Xcode iOS App. I want to convert the UIImage to a jpg and put it into the folder. Here is what I have so far (by the way, if it is at all relevant, the UIImage is taken from a photo that the user takes):
NSData * imageData = UIImageJPEGRepresentation(chosenImage, 1.0);
if (imageData != nil) {
[imageData writeToFile:#"/Users/Toly/Desktop/PhotoMap/PhotoMap/PhotoSet/test.jpg" atomically:YES];
}
I get no errors or warnings. However, no picture gets saved to any folder. What should I do?
You need to write to a directory that is actually on the iPhone. Most of the time you'll want to write to the documents directory. You can get the path to it like this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
This gives you the base documents directory, if you want to place the folder in a sub directory you'll need to create that folder before you do like so.
NSString *folderPath = [documentsDirectory stringByAddingPathComponent:#"myFolder/images"];
NSError *error = nil;
NSFileManager *fm = [[NSFileManager alloc] init]
[fm createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:&error];
Then to save your image data to that folder you'll do something like this
NSString *imageDataPath = [folderPath stringByAppendingPathComponent:#"myImage"];
BOOL success = [imageData writeToFile:imageDataPath];
Also, you can NSLog the imageDataPath it'll give you the exact location that file is saved so you can navigate to the actual file in finder if you're using the iOS simulator.
Your phone does not contain a data structure of files mirroring "/Users/Toly/Desktop/PhotoMap/PhotoMap/PhotoSet/test.jpg"
If you want the image to persist in memory, try using nsuserdefaults, or xcassets or Coredata. If you are absolutely intent on writing to a file, check out the NSCoding and NSFileManager tutorial below:
http://www.raywenderlich.com/1914/nscoding-tutorial-for-ios-how-to-save-your-app-data

Setting UIImageView image from saved screenshot working in iOS 8 but not iOS 7

I have made an app that saves a screenshot of the device to the app's Documents directory.
This UIImageView then reads in the saved screenshot image and displays it. All good so far. But wait a minute, this works absolutely fine on iOS 8, but it simply doesn't show anything on iOS 7, both simulators and devices.
So I investigated and found that iOS 8 saves the image to the following directory (Simulator on OS X):
/Users/SunburstEnzo/Library/Developer/CoreSimulator/Devices/AE8252CE-38C1-4D81-BA87-34F50E743AEC/data/Containers/Data/Application/34562F4C-5DED-4F1C-9CB6-92948B6C5F89/Documents/2014-11-26-11-12-24.png
While iOS 7 saves it to here:
/Users/SunburstEnzo/Library/Developer/CoreSimulator/Devices/CE8E7B90-F00F-441B-8E70-17E968AB7AF7/data/Applications/994CD541-2730-4E32-93CD-23B9F996C2E3/Documents/2014-11-26-11-12-51.png
I know this has something to do with it but when I reference it, it can see the image fine, it's just having a problem putting it to the screen. And I know what I've done works (on iOS 8) so the code is fine, but I need a workaround for this bug.
Also, whatever my problem is should be similar to this question's problem regarding the change over to using App Containers (NOTE: saving images is fine for me, just displaying it) -- saving image to documents directory no longer works iOS8
Tl;dr bug in iOS 7 stops saved image in Documents directory from showing, works fine on iOS 8, help me work around it
My code:
Writing screenshot to Documents directory:
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *sourceImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//UIImageWriteToSavedPhotosAlbum(sourceImage,nil, nil, nil);
NSData *pngData = UIImagePNGRepresentation(sourceImage);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSError * error;
NSArray * directoryContents = [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:documentsPath error:&error];
NSString *dateString;
NSDate *now = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd-HH-mm-ss"];
dateString = [dateFormatter stringFromDate:now];
NSString *filePath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png",dateString]]; //Add the file name
[pngData writeToFile:filePath atomically:YES]; //Write the file
Code to read:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSError * error;
NSArray * directoryContents = [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:documentsPath error:&error];
directoryContentsPopover = [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:documentsPath error:&error];
NSLog(#"Number of images: %d",directoryContents.count);
if (directoryContentsPopover.count > 0) {
self.mainImageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#/%#",documentsPath,directoryContentsPopover[0]]];
NSLog(#"At least 1 image; Image location: %#/%#",documentsPath,directoryContentsPopover[0]);
}
****Answer by Nick Lockwood****
Replace
self.mainImageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#/%#",documentsPath,directoryContentsPopover[0]]];
with
self.mainImageView.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/%#",documentsPath,directoryContentsPopover[0]]];
You are trying to load the image using [UIImage imageNamed:], but this method is only intended for images in your app bundle or XCAssets, it doesn't accept an arbitrary file path.
Use [UIImage imageWithContentsOfFile:] instead.
If the image saved on ios8 then it was also get saved in ios7,
you are not getting to correct path of documents directory ios8 and ios7 both having different path for document directory
path for ios7 document directory:/Users/**********/Library/Application Support/iPhone Simulator
try this

how to store an image path in a plist?

I know this is probably a silly question but I'm storing most of my game data in a plist - with that I'd like to include references to images used within my game - same hierarchal level as 'supporting files'. I have different types of images stored in 3 separate folders. One folder for example is called imageclue. How could I store the path in my plist, I'm stuck because I can't just store the path in my plist as string - filename.jpg. I've tried getting the path of the file but when I log it out it .
Sorry if I'm not explaining well and thank you in advance for any help :)
EDIT**
I have a plist file added to my program I don't want to programatically add to it as the images are constants - the screenshots below show a tutorial instead of the filename.jpg (because that won't work seen as my images are stored in a file) I wondered what path name do I use as a string.
The image is from a tutorial off of appcoda.com - where it says thumbnails are the image path files. If you look at where the images are stored on the left - they are stored with the program files. My images are in a folder in there so I'm confused as to what to enter in my plist for the image file.
Hope this clears up what I meant, sorry :)
Store three variables in .h file
#interface YourViewController : UIViewController
{
NSString *folder1;
NSString *folder2;
NSString *folder3;
}
in viewdidload:
-(void) viewdidLoad
{
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//getting the folder name:
folder1 = [NSString stringWithFormat:#"%#/imageclue",
documentsDirectory];
folder2 = [NSString stringWithFormat:#"%#/folder2",
documentsDirectory];
folder3 = [NSString stringWithFormat:#"%#/folder3",
documentsDirectory];
}
-(NSArray*) getPlistFromFolder:(NSString*)folder imageName:(NSString*)image
{
NSString *imageTitle = [NSString stringWithFormat:#"%#/image",
folder];
NSArray *data = [[NSArray alloc] initWithContentsOfFile:plistName];
return data;
}
So in the plist file, just store the image name.
Hope this helps...
Do it like this,
NSDictionary *imagePaths = #{#"image 1": [NSHomeDirectory() stringByAppendingPathComponent:#"image 1"]};
[self writeToPlist:imagePaths];
- (void)writeToPlist:imagePaths:(id)plist{
NSError *error;
NSData *data = [NSPropertyListSerialization dataWithPropertyList:plist format:kCFPropertyListXMLFormat_v1_0 options:0 error:&error];
if(error){
NSLog(#"Could not write to file");
return;
}
[data writeToFile:[self plistPath] atomically:YES];
}
Like wise loading is simple as this;
[self loadImagePathForImageNamed:#"image 1"];
- (NSString*)loadImagePathForImageNamed:(NSString*)imageName{
}
- (NSString*)loadImagePathForImageNamed:(NSString*)imageName{
NSData *data = [NSData dataWithContentsOfFile:[self plistPath]];
NSString *error;
NSPropertyListFormat format;
NSDictionary *dictionary = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
if(error){
NSLog(#"Could not open plist %#", error);
return nil;
}
return dictionary[imageName];
}
You may have to handle the error when the file is not there by creating a new one, otherwise this should work.
You are storing path right way, just need to store filename of image with extension in plist when your images are in your Application Bundle, for more reference you can define key name Instead "item1", "item2" in your plist.
Now coming to actual Question, how to access image from plist
Step 1 : Read your recipes.plist from Application Bundle
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"recipes" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:bundlePath];
Step 2 : Now Get Image/Thumbnails name out of it, which you want to load
Step 3 : Define following Function in your Controller, which returns image from name
- (UIImage *)getImageWithName:(NSString *)imageFileName
{
NSString *ext = [imageFileName pathExtension];
NSString *imagePath = [[NSBundle mainBundle] pathForResource:[imageFileName stringByDeletingPathExtension] ofType:ext];
return [UIImage imageWithContentsOfFile:imagePath];
}
HOW TO USE
Suppose you want to load Image with key "Item2" then write following code
NSString *imageFileName = [[dict objectForKey:#"Thumbnail"] valueForKey:#"Item2"];
UIImage *item2Image = [self getImageWithName:imageFileName];
For "Item6"
NSString *imageFileName1 = [[dict objectForKey:#"Thumbnail"] valueForKey:#"Item6"];
UIImage *item6Image = [self getImageWithName:imageFileName1];

Creating image thumbnails to be loaded into tableview from files in app directory

I need some help for a problem which I can't solve but I think I am close to the solution. Here is it:
In a version of my app, I was able to populate a tableview (in CellforRowAtIndexPath) with images taken from the Assetlibrary using the following 2 lines:
ALAsset someAsset = [theAssets objectAtIndex:indexPath.row];
[cell.imageView setImage:[UIImage imageWithCGImage:[someAsset thumbnail]]];
Now, I am trying to read image files from the directory and stored in an NSMutableArray. I can see the filenames when I NSLog the NSMutableArray. But how do I now cause the files to be converted into images and displayed in my tableview in the same way I did why using the Assetlibrary? I have tried several times, but the app either crashes or it does not show the image thumbnails in the table view. For example, this statement does not display the image but the app does not crash:
UIImage *anImage = [UIImage imageWithContentsOfFile:[self.listTable objectAtIndex:0]];
When I setImage in the next line, it doesn't work. Someone please help!
UPDATED: The contents of self.listable when I NSLog it is something like this: "19-10-25 276-10-12.jpg",
"19-10-37 276-10-12.jpg",
"19-10-54 276-10-12.jpg",
"19-10-65 276-10-12.mov", etc.
When I NSLog my documents directory, it is: /var/mobile/Applications/8CB1368A-AAE2-4815-BD26-A7B7C8536193/Documents.
Apps can only imageWithContentsOfFile for files located within the app's sandbox (e.g. in Documents, the bundle, etc.) If these files are located in your Documents folder, you get the full path via:
NSString *documentsFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *imageFullPath = [documentsFolder stringByAppendingPathComponent:imageFilename];
You can then use that in imageWithContentsOfFile.
Update:
You asked:
my directoryContents is an NSArray; how do I convert it to NSString and then [documentsFolder stringByAppendingPathComponent ...] and store each fullpath in the NSMutableArray?
You might do something like:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSArray *filenames = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:nil];
NSMutableArray *paths = [[NSMutableArray alloc] initWithCapacity:[filenames count]];
for (NSString *filename in filenames)
{
[paths addObject:[documentsDirectory stringByAppendingPathComponent:filename]];
}
NSLog(#"%s filenames = %#", __FUNCTION__, filenames);
NSLog(#"%s paths = %#", __FUNCTION__, paths);

Resources