Saving UIImage to File instead of NSUserDefaults - objective-c

So I have an array with images that I want to store locally since downloading them each time will take unnecessary effort. I've read that I should NOT store images in NSUserDefaults, which is fine, but I can't for the life of me find any examples on how to store it as a file in a directory that does not change (iOS 8 changed the UUID with each build which creates a new folder each time I run it in Xcode).
I generally have two questions here:
Could someone help me translate this into ObjC? I can't comment on the post since I don't have enough rep...It's the swift part farther down the post that I need help with. Save images in NSUserDefaults?
The other question I have is that it seems to take a lot of time to save the data locally, no matter if it's to file or into the NSUserDefaults. What happens here is that the user of my app closes the app before the data has been stored locally. Is there any way to prevent this? I can add an ActivityIndicator, sure, but I can't seem to find any callback which tells me when the process of saving data has been completed.
Thanks!

So I managed to solve it. The problem was that I simply mixed up the paths. If anyone else wants the translation from Swift to ObjC from the link in the original post here it is:
Write
NSString* relativePath = [NSString stringWithFormat:#"image_%d.jpg", 1];
NSString* realPath = [self documentsPathForFileName:relativePath];
// Write image data to user's folder
[self.ImageData writeToFile:realPath atomically:YES];
// Store path in NSUserDefaults
[defaults setObject:relativePath forKey:#"path"];
Read
NSString *relativePath = [defaults objectForKey:#"path"];
NSString *realPath = [self documentsPathForFileName:relativePath];
self.ImageData = [NSData dataWithContentsOfFile:realPath];

Related

Save in plist to a program directory

i need to save a .plist file NOT to documents, but to the core of program.
For example my program called "123" and if i save data, then send my app to my friend and he opens this app he could see saved data, no matter where he puts this program. I can't find solution to this problem, please help me.
I'm making mac app.
and i save plist with
[NSKeyedArchiver archiveRootObject:FBCover1.text=
[NSString stringWithFormat:#"%#",Cover1.attributedStringValue]
toFile:#"/Users/admin/FBCover1.plist"];
General answer:
If you're trying to do this on iPhone (you didn't tag this for iOS or MacOS), this isn't going to work as this will break your code signing.
If you're doing this on MacOS and you're using code signing, you'll have the same problem.
There may be places where you could save and share data, such as Game Center or DropBox or Box or some other cloud storage mechanism, but you'll need to pick up and make use of some additional API's or frameworks.
Specific answer just for you:
Instead of:
[NSKeyedArchiver archiveRootObject:FBCover1.text=[NSString stringWithFormat:#"%#",Cover1.attributedStringValue] toFile:#"/Users/admin/FBCover1.plist"];
which is big and ugly and I don't know what the heck it's doing, why not save your string this way?
NSString * stringToSave = [NSString stringWithFormat:#"%#",Cover1.attributedStringValue];
if(stringToSave)
{
NSError * error = nil;
BOOL success = [stringToSave writeToFile: #"/Users/admin/FBCovert1.txt" atomically: YES encoding: NSUTF8StringEncoding error: #error];
if(!success)
{
NSLog( #"error in saving - %#", [error localizedDescription]);
}
}
This saves the raw string into a file.
If you want to do it as a plist, then create a NSDictionary and save your string as the value with some appropriate key.
Preamble: this is an awful idea. What you should do is create a document-based application and pass your document backwards and forwards.
Literal answer:
You can use NSBundle to get the path of the resources folder within your application bundle with something like:
[[NSBundle mainBundle] resourcePath]
The resources folder is where application resources, such as plists, are meant to go. You're supposed to consider your application bundle as read-only in general but that's as good a choice as any if you want to hack away.

Is there a better way to check for a newer file than my implementation?

I have an app that downloads PDFs that are updated every few months, and everytime I download a certain PDF, I also download a .txt file which contains one character. Everytime I upload the updated PDF on my server, I also increate the character count in the .txt file on the server by one.
When the user taps the Updates button in my app, I compare the string in the .txt file from the server to the string of the local .txt file.
This is a pretty lightweight way of checking to see if a new PDF is available, but I am asking if there is a better way or lighter way to do this without having to create a .txt file for each PDF file that I have on my server?
Thank you in advance for any help offered!
This is the code I use to check for new PDFs:
NSString *documentDirectory = [(AppDelegate *)[[UIApplication sharedApplication] delegate] applicationDocumentsDirectory];
NSString *path = [documentDirectory stringByAppendingPathComponent:#"test.txt"];
NSString *server = [NSString stringWithContentsOfURL:[NSURL URLWithString:#"foo.com/test.txt"] encoding:NSASCIIStringEncoding error:nil];
NSString *local = [NSString stringWithContentsOfFile:path encoding:NSASCIIStringEncoding error:nil];
if(![local isEqualToString:server])
{
// I Download the new PDF and the new .txt file here;
// simple NSURLConnection stuff, no need to elaborate
}
Off the top of my head, the HTTP HEAD method can be used to fetch just the headers rather than the data. If the creation date in the headers is later than the last date you downloaded the data, it's time to fetch a new copy. This can be done with NSURLRequest and NSURLConnection.
If your server doesn't support the HEAD request or something else prevents its use, you could have a second TXT file with a version/hash/unique identifier in it. Download that instead and compare against the stored value. If it's changed, download the full PDF and save the version text file to disk for reference later.
If security is an issue and you need to be able to trust the server, use HTTPS in either case.

can't open image with NSOpenPanel

I use below code for open image with NSOpenPanel but doesn't work
//panel=NSOpenPanel
NSString *imgg = [NSString stringWithFormat:#"%#",panel.URL];
self.imgUser.image=[NSImage imageNamed:imgg];
The problem is that +[NSImage imageNamed:] doesn't load an image by URL. If you read the documentation, it explains what it actually does: it looks for an image stored in the cache under that name, or stored in the app's bundle or AppKit's framework under that filename.
There are a large number of ways to actually open an image by URL. The one you're probably looking for is:
NSImage *image = [[[NSImage alloc] initWithContentsOfURL:panel.URL] autorelease];
Also, as a side issue, the way you're trying to turn a URL into a path is incorrect. If you have an NSURL for file://localhost/Users/user437064/Pictures/mypic.jpg, just converting that to a string just gives you #"file://localhost/Users/user437064/Pictures/mypic.jpg". That isn't a path that you can use with path-based APIs. What you actually want is #"/Users/user437064/Pictures/mypic.jpg", and the way you get that is -[NSURL path]. So "NSString *imgg = [panel.URL path];". But this is irrelevant; unless you need to deal with very old versions of OS X, or out-of-the-way APIs, there's almost always a method that takes a URL for each method that takes a path, and often the path-based ones are deprecated.
As an even farther-off-the-side issue, you don't need stringWithFormat: to convert something to a string; "[panel.URL description]" gives the exact same result as "[NSString stringWithFormat:#"%#", panel.URL]", much more simply and a little more efficiently.

<newbie> Objective C, saving a file in iPad apps

I am creating a sample application where it downloads 100 images from
server and stores it in iPad.
In XCode, I am using the NSURL to retrieve the image file and using
NSData to save it into my local folder.
I am able to save the images in my mac air desktop folder. But I want
my application to be deployed in iPad.
So here is my question:
Where do I store the file in my iPad, so that my application can
retrieve the images when needed?
If possible can someone give me the code for saving the images in
your iPad resource directory (or whatever directory needed). Just the
code where you build the path will do good.
I know this is kind of a basic question, since I am new to objective-C, I am kind of struggling with it.
Here is an example function how to retrieve the applications documents folder. In there you can create your own folder structure. This folder is also backed up by iTunes and will be preserved when doing application updates.
NSString* GetApplicationDocumentsDirectory() {
static NSString* documentsDirectory = nil;
if (documentsDirectory == nil) {
documentsDirectory = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES)
objectAtIndex:0] retain];
}
return documentsDirectory;
}
In my humble opinion, using a Core Data store would be the best approach for this.

URLCache - iPhone SDK

I need some help in using the NSURLCache to download a simple file. It would need to be saved in the Documents folder of the app. I have seen the URLCache example that apple presented, but I didn't find it useful since it was an image that was being shown. In addition there was some complex code on the modification date. I actually need something when the application opens it will begin the download process. Can someone guide me through just the download process of any file?
Thanks
Kevin
NSURL *myURL = [NSURL urlWithString:#"http://www.google.com/theInternet.zip"];
NSData *myData = [NSData dataWithContentsOfURL:myURL];
[myData writeToFile:#"ThePath" atomically:YES];
This will block, but should be ok for small downloads. If you are going to be downloading something that is many megabytes then look into asynchronous downloads. You can see an example here:
http://github.com/erica/iphone-3.0-cookbook-/tree/master/C13-Networking/07-Asynchronous%20Downloads/