How to load saved image in swift on ios simulator? - ios

I save an image using this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"Image.png"];
[UIImagePNGRepresentation(image) writeToFile:filePath atomically:YES];
Then, I exit the app in the simulator. Then I attempt to load the image with this:
let imageName = "Image.png"
let image = UIImage(named: imageName)
i1.image = image
I can think of two reasons the image does not load:
Exiting the app in the simulator is causing it to be uninstalled.
I am not getting the paths correct in swift vs. obj-c.

UIImage(named: imageName) does not fetch an image from the Documents directory. It fetches an image only from the inside of the app itself (the app bundle), which is a very different place. The inside of the app bundle is not where you saved it (nor is it possible to save anything there), so naturally UIImage(named: imageName) comes up empty-handed. It can't find the file, for the simple reason that the file is not there to be found.
If you want to read the image file from the Documents directory, read it exactly the same way you wrote it: by forming the file path (or file URL) and reading it as data from disk. For example, having formed the file path, call UIImage's init(contentsOfFile:).

Related

Writing big file on IOS [duplicate]

I save some run-time generated files inside the .app bundle of my iOS app. In the simulator it works fine, in the device it crashes:
Could create output files in the given shader cache path
'/var/mobile/Applications/CB064997-B40E-4FE3-9834-B3217CE33489/SimedTest.app/Ogre3D/assets/RTShaderLib/cache/
Is there a good overview of where I should and shouldn't put files - how to use Documents, Library and tmp, etc?
To clarify, these are files created at startup which pre-calculate some data to save time. IF they are not present they get created so it's fine they are deleted, but not while the app is running.
The bundle is read-only. You don't want to mess around with it for two reasons:
Code Signing: the signature is verified by against the contents of the bundle; if you mess around with the bundle, you break the signature.
App Updates: updates work by replacing the entire app bundle with a newly downloaded one; any changes you make will get lost.
Where you should save stuff:
Documents: if you want it to persist and be backed up
Library/Caches: if you just want to cache downloaded data, like profile pics; will be auto deleted by the system if it is low on room unless you specify with a special do-not-delete flag.
tmp: temporary files, deleted when your app is not running
For a full explanation check out File System Programming Guide and QA1719.
No, every time you change your bundle you invalidate your signature.
If you want to write files you`l need to write in the best folder depending on what you want to do with that file.
Documents folder for long duration files
Cache for small operations
and so on
EDIT
To get the path you`ll need something like this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"filename.ext"];
With this path you can write or read like this:
write:
NSString *content = #"One\nTwo\nThree\nFour\nFive";
[content writeToFile:fileName atomically:NO encoding:NSStringEncodingConversionAllowLossy error:nil];
read:
NSString *content = [[NSString alloc] initWithContentsOfFile:fileName usedEncoding:nil error:nil];

iOS - Reading an Audio file from Documents Directory

I am saving audio data to the Documents directory and trying to read it back. If I play it back immediately it plays successfully, however, if I start a new session and try and play the song locally it will fail even though listing the files in the Documents directory shows that my file is still there. Note that the file is played back from the Documents folder in the same way (same code) if it is played immediately or during a new session.
Here is how I save the audio data to the Documents directory:
+(void)writeDataToAudioFile:(NSData*)data forTrack:(MediaItem*)track
{
// filename looks like "[track_id].mp3"
NSString *fileName = [NSString stringWithFormat:#"%#.%#",track.sc_id,track.original_format];
NSString *pathName = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES) firstObject]
stringByAppendingPathComponent:fileName];
[[NSFileManager defaultManager] createFileAtPath:pathName
contents:data
attributes:nil];
}
Then in my music player I want to load the local URL to this file to initialize the AVPlayer:
NSURL *url;
if(_currentTrack.is_local_item)
{
url = [NSURL fileURLWithPath:_currentTrack.local_file_path];
}
url does not get created properly as AVPlayer does not play. Furthermore, I have tried every different way to load the file as data into an NSData object to check the byte size but trying to access the file as data always returns nil. However, the file exists as if I use NSFileManager I am able to iterate over the items in the Documents directory and print their file names/paths, validating that I the path I have saved in "_currentTrack.local_file_path" does exist. Again, if I play the file immediately after saving the file to disk it will play back.
If there is more info I can provide to make this clearer I will. Thank you very much.
Do not write the full directory path to DB. It will change. You need to only save the file name to DB as reference. Then use as follows:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *fileName = #"SAVED_FILE_NAME.mp3"; // eg: [track_id].mp3
NSString *filePath = [documentsPath stringByAppendingPathComponent:fileName];
This will provide you the actual path of the file.
Keep coding........... :)
I found the solution after putting the problem down for a few days. I break-pointed and print-stated the heck out of the program and I found that the file path I was saving was not the same as the file path of the file.
I think this was a simulator issue, as the issue only occurred between different sessions of the simulator, and worked within the same session, so the device id (which is part of the absolute path) was changing - maybe someone more knowledgeable can weigh in on that.
Pay closer attention to the string values of your variables folks!

Loading UIImage from Directory no longer working

For the past 5 or 6 months i have been saving images to a Photos folder in which i created within the documents directory on the users device. The photos would then be loaded into an imageView when the user entered a specific screen, until recently this has been working perfectly.
Now the images no longer show in the image view and when using the URL to print out the image width and height, the values are zero even though the URL has not changed.
I am using the following code to display the image within the image view.
outputImageView = [[UIImageView alloc] init];
[outputImageView setFrame:originalImageViewSize];
outputImageView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:photoURL]];
NSLog(#"width %f, height %f", outputImageView.image.size.width, outputImageView.image.size.height);
the photoURL is as follows: /Users/fernandosantos/Library/Developer/CoreSimulator/Devices/6F3FCE2A-F7F9-4F77-B66D-3DA2A25BE166/data/Containers/Data/Application/C3867EFA-6AA8-4B71-A856-DCF7F83DEFF0/Documents/AUDIBURY/Photos/COMMTRCIAL-CSRSignature--2014-10-13 10-49-16.jpg
Thanks
In iOS8 the application documents directory dynamically changes its name on every running. You have to use the following method from Appdelegate in order to get the current documents directory path:
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
You should only save the relative path of the file, not the full path. This method also works on iOS7.
You can use the iOS simulator and check that the full path actually doesn't exist.
Thanks to everyone that replied with a suggestion.
I combined what everyone had suggested and came up with this solution which works for me.
//get the documents directory, in iOS 8 this is now dynamic everytime you run the app.
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//Create the CurrentPhotoURL by using the current documents directory and the appending the photo name which
//was created when saving the image originally.
NSString *currentPhotoURL = [[documentsDirectory stringByAppendingString:#"/"] stringByAppendingString:photoName];
Since i had created a new a folder within the documents directory called Photos, the photoName variable holds the name of the Photos folder followed by the name of the image when it was originally saved.
I then append the photoName variable to the current documents directory to get the full directory path for that photo.
This may not be the best solution but its what i came up with and it works.
If anyone else needs further information then please contact me.

iOS - write jpeg file to file system

I'm new to iOS development and I'm trying to write an image as a jpeg file to the file system. From the logs I know that those file are indeed written to the file system, but when I try to save them to the camera roll they all appear black. I'm using the following code to write them as jpeg files:
[UIImageJPEGRepresentation(image, 1.0) writeToFile:jpegPath atomically:YES];
And the following code to write to camera roll:
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
Anybody know how to verify that those jpeg files are indeed written to the file system? And what I might be doing wrong in the second line of code?
EDIT: So here is the entire method:
- (BOOL)createImagesForSlides:(NSString *)documentsPath destinationURL:(NSURL *)destinationURL
{
NSFileManager *manager = [NSFileManager defaultManager];
CPDFDocument *document = [[CPDFDocument alloc] initWithURL:destinationURL];
NSString *folderName = [NSString stringWithFormat:#"/%#", document.title];
// create new folder
NSString *newFolderPath = [documentsPath stringByAppendingString:folderName];
BOOL result = [manager createDirectoryAtPath:newFolderPath withIntermediateDirectories:NO attributes:nil error:nil];
// create a jpeg file for each page of the pdf file
for (int i = 1; i <= document.numberOfPages; ++i) {
NSString *jpegPath = [NSString stringWithFormat:#"%#/%d.jpg", newFolderPath, i];
[UIImageJPEGRepresentation([[document pageForPageNumber:i] image], 1.0) writeToFile:jpegPath atomically:YES];
UIImageWriteToSavedPhotosAlbum([[document pageForPageNumber:i] image], nil, nil, nil);
}
return result;
}
document is a pointer to a CPDFDocument instance, and it's from some open source reader code available on github (iOS-PDF-Reader). What I basically do here is grab each page of the pdf document, generate an image, and then save them to the file system as jpeg file. Weird enough, even though there are more than 10 pages in the document, UIImageWriteToSavedPhotosAlbum only writes 5 files to camera roll. Any idea why?
It would probably be useful to see how you construct jpegPath here.
First, writeToFile:atomically: returns a BOOL, so check that for your first indication of success or failure.
There are a couple of ways you can verify that the image is written to the file system. If you are running on a device use something like iExplorer to access the file system and look at the file written. Since it is NSData* you can cheek the file size to make sure it looks reasonable. On the simulator, dig into the folder structure under ~/Library/Application Support/iPhone Simulator/ and examine the file. Without looking into the filesystem itself try reading the image back into another UIImage (imageWithData: in your case since you are writing a NSData* object).
There doesn't appear to be anything wrong with your UIImageWriteToSavedPhotosAlbum call according to the docs. It is OK for the last 3 arguments to be nil (all are marked as optional), you just have to be sure the UIImage is valid. Have you set a breakpoint to be sure you have a valid image (Xcode Quick Look feature)?

Using NSTemporaryDirectory without increasing tmp folder size

In my app the user has the possibility to upload and download 700*700mb images. These images are downloaded and displayed in a few UIImageViews.
My app itself is quite small, but the Documents & Data folder is enormous e.g. 17gb and it keeps increasing exponentially. My app runs on both ipad and on iPhone. Will the docs & data folder in my ipad is 6mb, on my ipod it is 17gb. I have downloaded the app package, and found out that the tmp folder is huge. there are some Stack-log files 1gb big. I found out the problem was related to the NSTemporarydirectory.
I save an image in this way:
NSString *title = [[NSUserDefaults standardUserDefaults]objectForKey:#"Folder3"];
PhotoiPhoneViewController* sharedSingleton = [PhotoiPhoneViewController sharedManager];
NSString *destDir = [[NSUserDefaults standardUserDefaults]objectForKey:#"Folder2"];
NSString *filename3 = [NSString stringWithFormat:#"%#%#sizefile.pages.%#", destDir, title, sharedSingleton.tagString];
NSString *SizePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"%#sizefile.pages.%#", title, sharedSingleton.tagString]];
[self.restClient loadFile:filename3 intoPath:SizePath];
Is this the right way to do it, or should I use:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *CommentPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#commentfile.txt.%ld", title, (long)sharedSingleton.tagNumber]]
Since I want the files to be deleted after use, I thought that the NStemporaryDirectory would be deleted as soon as the file was used. What should I do??
You could look into using NSURLCache as these manage the purging.
See also NSHipster/NSURLCache
Or you could use a library like SDWebImage which will handle a cache size as well
Edit: In answer to your question
The operating system used to leave files in the temporary directory, however, since iOS 5.0 it will purge files from this directory if it sees the need. See this link for more information

Resources