Save in plist to a program directory - objective-c

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.

Related

Saving UIImage to File instead of NSUserDefaults

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];

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.

iPhone 4 iOS5 how to include a text configuration file with the app?

I know how to read/write to local files on iOS using file handles. I can dynamically create and read/write form them.
What I'm trying to do right now is to include a file, about 200 lines long with the app bundle, which I hope to parse and extract configuration settings from. I really do not want to have to create an array of 200 numbers by hand.
How would I go about including a text file with the app, and making it accessible from my application?
Thank you!
You can include a file in the bundle by adding it to your Resources folder in Xcode and making sure that it is included in your target as well. To access a file in the bundle (e.g., a text file called info.txt), you can get the path using:
[[NSBundle mainBundle] pathForResource:#"info" ofType:#"txt"]
Then access it using the normal NSFileManager methods.
EDIT:
With this said, you can't write anything into this file inside the bundle on iOS. Instead, you can copy the file from the bundle to a file system location (say, your app's Application Support folder) on first launch, then access it there elsewhere in your app.
Why don't you create a dictionary with Property List Editor and load it like
NSString *configurationPath = [[NSBundle mainBundle] pathForResource: #"configuration" ofType: #"plist"];
NSDictionary *configuration = [NSDictionary dictionaryWithContentsOfFile: configurationPath];
So you can access its settings with
[configuration objectForKey: #"someSetting"];
If you want to write, I recommend registering that dictionary with NSUserDefaults so you could write to a copy like
[[NSUserDefaults standardUserDefaults] setObject: someSetting forKey: #"someSetting"];

<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.

Is it possible to copy a different plist into the application bundle code wise?

My question is stated above in the title but I'll write it here again
Is it possible to copy a different plist into the application bundle code wise??
This is actually a bit related on my previous question ;) Create a dictionary property list programmatically
But since I can write out the plist (and test if I'm doing something wrong ) I was wondering if I can copy my written file
[testBook writeTofile:#/Users/jack/testbook2.plist" atomically:NO];
to my application bundle in code (so that it can read from here with
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *dataPath = [path stringbyAppendingPathcomponent:#"testbook2.plist"];
Another alternative is good as well for instance if I can read my plist directly from another path instead of the mainBundle
Physically, yes it is possible sometimes.
NO, DON'T DO THAT!!
Okay... copying stuff into your App Bundle is bad, your app bundle is not where you keep settings or data. You should think of your app bundle as readonly. You should do this for several reasons:
While most of the time a user on a Mac OS X system has permission to write to an app sometimes they don't. Think about children who are not using admin accounts, or lab deployments at schools.
It will invalidate codesigning. If you sign your application this will change the signature and break the codesign, causing all sorts of weird issues (losing any firewall permissions the app has, telling the user the app has changed and asking them for keychain permission again, etc). In the future this may also pop up all sorts of warnings since tampering with an app is a big security red flag.
It won't work on iPhone. That may not be an issue, but if you every intend to use this code on an iPhone the apps bundles are sandboxed readonly
The correct place to put this sort of stuff is into a sub folder of the Application Support folder
I don't know exactly what you're doing, but depending on your application, you might want to use the Application Support directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
if ([paths count] > 0) {
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"App Name"];
// Create the directory if it doesn't exist, etc.
} else {
NSLog(#"Fail!");
// ...
}