This used to work: Displaying image using imageWithContentsOfFile - ios

This was working for me yesterday morning and now it doesn't. So, I suspect something else changed to cause it...but I can't find the change. I've spent hours reverting my code back almost a week and still it's not working (and I know it was working yesterday morning). So, I'm hoping that in posting this specific issue (a symptom?) some ideas will surface that I can evaluate. Thanks.
I download images as they're needed:
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
NSString *targetFile = [NSString stringWithFormat:#"%#/%#.%#", documentDirectory, imageName, imageType];
// only download those where an image exists
if(![imageType isEqualToString:#""])
{
// only download the file if there is not already a local copy.
if([filemgr fileExistsAtPath:targetFile] == NO)
{
NSMutableData *imageData = [[NSMutableData alloc] initWithLength:0];
[imageData appendData:data];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *thumbNailFilename = [NSString stringWithFormat:#"%#.%#", imageName, imageType];
NSString *thumbNailAppFile = [documentsDirectory stringByAppendingPathComponent:thumbNailFilename];
}
}
Then display them:
NSString *imageFullName = [NSString stringWithFormat:#"%#%#", [greetingObject valueForKey:#"gid"], [greetingObject valueForKey:#"itp"]];
NSString *fullImagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:imageFullName];
UIImage *greetingImage = [UIImage imageWithContentsOfFile:fullImagePath];
self.greetingImage.image = greetingImage;
The variables "imageFullName" and "fullImagePath" are populated with the correct data and the image files are present on the simulator in the specified directory. Yet, "greetingImage" equals nil.
Here's what I get for "fullImagePath": /Users/Steve2/Library/Application Support/iPhone Simulator/7.1/Applications/8C9F8417-F6E2-4B38-92B3-82A88477CB7F/Documents/165.jpg
Here are the image files:
I have also tried variations using initWithContentsOfFile and dataWithContentsOfFile and get the same result. The greetingImage variable is nil.
I appreciate your ideas. I've even reinstalled Xcode in hopes that something got corrupted. No dice.
Added: One thing I just thought of... I did add the SystemConfiguration.framework to the project yesterday for an unrelated feature. It's currently at the top of the Linked Frameworks and Libraries list. I have no experience working with this. Could it be causing the problem?
Thanks.

Your code looks correct.
I would check that the images themselves are still okay. Looking at the screenshot you posted Finder isn't showing previews of the images which it should do with a valid JPEG. You say that the images are being downloaded so I suspect that they are being corrupted somehow on the way down.
EDIT:
Didn't notice that you were using initWithContentsOfFile. Since you are saving the files as NSData objects you will need to load them into memory as NSData objects and then init a UIImage with the data object, like so:
NSData *imageData = [NSData dataWithContentsOfFile:filePath];
[UIImage imageWithData:imageData];

Related

Convert a downloaded image to in-memory static image -IOS

My scenario goes in this way. At the start of application a list of images will be downloaded from server & once downloaded all images will be converted into the static images and onwards will be using those static images everywhere in application. I think in android this thing can be achieved using BITMAP. (Not confirm).
Currently i'm using SDWEBIMAGE library for downloading and caching images. But i don't want to use this library anymore. I just want to download all images once and then everywhere i want to add below code snippet for displaying downloaded images.
[ImageView setImage:[UIImage imageNamed:#"DownloadedImageName"]];
Is there any way to get this thing done in ios?
You have to download each Image and save it into "Documents" Directory, and then whenever you need them use that.
For saving image into documents directory, use code like this:
- (IBAction)saveImage:(UIImage*)img {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.png"];
NSData *imageData = UIImagePNGRepresentation(img);
[imageData writeToFile:savedImagePath atomically:NO];
}
And for getting and show image on imageview, use this code:
- (UIImage*)getImage
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *getImagePath = [documentsDirectory stringByAppendingPathComponent:#"savedImage.png"];
UIImage *img = [UIImage imageWithContentsOfFile:getImagePath];
return img;
}
[UIImage imageNamed:] method is only for getting images that already exist in your app bundle. So if you have dynamic content that is downloaded from internet, you cannot use this method. Rather, create your own method to load the images from sandbox Documents folder.

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.

How can I get the file path from a UIImage?

Usually it's the other way around, you use the path to display the image. I was wondering if you can get the path if you already have the image.
if you already have the image i.e. have added the file to your resources, you can use this to get the file path;
NSString *string = [[NSBundle mainBundle] pathForResource:#"IMAGE_FILE_NAME" ofType:#"jpg"]; // or ofType:#"png", etc.
I don't believe it is possible to get it directly from UIImage.
Best way is to save the image in a directory, then you will have the file path.
//image is your UIImage;
if (image != nil)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
#"test.png" ];
NSData* data = UIImagePNGRepresentation(image);
[data writeToFile:path atomically:YES];
}
path will be your filepath.
Once a UIImage is created, the image data is loaded into memory and no longer connected to the file on disk. As such, the file can be deleted or modified without consequence to the UIImage and there is no way of getting the source path from a UIImage.

How to download dataset for Vuforia app?

I'm developing sample apps from Vuforia SDK 1.5.9 in Xcode 4.2 with iOS 5.1. In that version I could not make my trackable datasets on my own - I have to use online solution from Qualcomm. Does anyone know or have anyone tried to download datasets from remote location? So you generate them as usual but download them into app from server, so I can for example choose which one to download and use on fly?
Yesterday I've given it a quick try with this:
-(void)setupMarkers{
NSString *filePathX;
//connect to the remot location
NSURL *urlD = [NSURL URLWithString:[NSString stringWithFormat:#"%#/frames.dat",kURLServer]];
NSData *urlData = [NSData dataWithContentsOfURL:urlD];
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"frames.dat"];
[urlData writeToFile:filePath atomically:YES];
}
NSURL *urlX = [NSURL URLWithString:[NSString stringWithFormat:#"%#/frames.xml",kURLServer]];
NSData *urlDataX = [NSData dataWithContentsOfURL:urlX];
if ( urlDataX )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"frames.xml"];
[urlDataX writeToFile:filePath atomically:YES];
filePathX = filePath;
}
//put them into markersArray
[self.markersArray addObject:filePathX];
}
I know it is ugly, but as I said it was a quick try, but it didn't work at all. I know there is new Vuforia SDK 2.0 with clouds and stuff, but afaik I would have to use iOS6 & Xcode 4.5 - which is not a solution for me right now.
Actually my "quick try" wasn't that bad after all :)
Here's what i did:
wrote a method -(void)setupMarkers in which I dwonload .dat and .xml files (like in question)
in QCARUtils.mm I changed in - (QCAR::DataSet *)loadDataSet:(NSString *)dataSetPath one line:
// Load the data set from the App Bundle
// If the DataSet were in the Documents folder we'd use STORAGE_ABSOLUTE and the full path
if (!theDataSet->load([dataSetPath cStringUsingEncoding:NSASCIIStringEncoding], QCAR::DataSet::STORAGE_ABSOLUTE))//STORAGE_APPRESOURCE)){
...
}
works like a charm :)
p.s. I'll wait a while so if anyone will come up with better answer ;)

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