Saving an NSDictionary to File, and Creating a New File - objective-c

I'm trying to discover a way to save an NSDictionary, (which will probably hold high scores and users on a particular system.) onto a new file. I would like to know how to create the file, and put it in the location that it should be, preferably where it can't be touched by the user. Is there any place that these kinds of files are meant to be?

There are many ways to do it.
Either make Plist of your NSDictionary and write to Documents Directory
OR
Make JSON string >> Convert it to NSData using NSJSONSerialization >> Write it to Documents Directory
You can write files in documents directory using NSFileManager

Have a look at this question:
How to save data into the User's Application Support?
The best place to save such files is the "Application Support" folder in the users "Library" folder. The user could go there, but most users won't.
The first answer also has a link on how to save an NSDictionary to a file.
Edit
My answer applies for osx applications only. If you making an app for ios, you should save your file to your app's "Documents" directory.

Related

Where should my application store large number of PDF files on iOS?

I am writing an iOS iPad app that will download several hundred large PDF files from the web and cache them on the iPad for offline use.
Where is the best place to store them on the iPad? The local file system, core data, or some other place? I am planning to use core data for an indexing and search mechanism (using thumbnail images etc), and will only access the PDF docs when a user specifically requests the full document.
The best place to do so is either the Documents directory or the Cache directory. Documents in the Documents directory are supposed to be user-generated content, so I believe this is not what you're looking for.
Instead, I think you should use the Cache directory, which you can access using this method :
- (NSString *)cacheDirectory {
{
NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [pathList objectAtIndex:0];
return path;
}
Note that the Cache directory can be emptied by the system if you don't have enough space on the device. In my experience this almost never happens, but you might want to store your documents in a subdirectory of the Library directory other than Cache if you want to be absolutely, absolutely sure that the files never ever get deleted.
In this case, you have to set the do not backup flag on both the directory and the files, or else your app will be rejected.
See the Apple guidelines (requires a developper account) for official information.
You should save them in the /documents folder. The purpouse for that folder is exactly that, store data that couldn't be redownloaded (or would be too big to do so). If it were temp data or data you could easily redownload, Apple suggests to use the /cache folder instead.
You can save the files with a specific name, and just save that name in CoreData to find them back.
I would save the PDFs under the Documents folder.
And create a core data sqlite datebase.
Create a core data entity with probably three attributes: thumbNail, localURL, and title.

Setting file permissions in Objective-C

I managed to get my hands on a nifty ftp object. It is very low level and easy to adapt. I'm using it to transfer files from one Mac to another via FTP.
Now, the issue I'm having is that when the file, that is transfered, reaches its destination, the other Mac, the access permissions is set , at random intervals, to "Everyone" : "No Access". So sometimes, whatever I do with the files fails randomly because my application can't access the files.
Is there a way I can change the file's access permissions in Objective-C?
Regards,
EZFrag
For permissons of local files, you'd want [NSFileManager setAttributes:ofItemAtPath:error:]
And the attribute dictionary you'd want to use would include NSFilePosixPermissions.

NSBundle, can it be used to save a project document?

I'm building a Mac OS X application that can be used to create 'projects'. When a user saves a project, they will be saving many resources: image files, text files, sqlite files etc.
I can either create a folder in Documents for each project, and within that folder I can place all the project assets, and just include a single project file that is used to open the project.
I've read about NSBundle which I'd like to use. But I've only read about them in the context of application bundles. Is it possible to use NSBundle in this way? Where the user only sees a single file, and can move it wherever they like.
Does it make sense to do what I'm trying, using NSBundle? Or is there another way to do this?
(I'm fairly new to MacOS X programming)
UPDATE
I believe iPhoto uses this method to store the "iPhoto Library", this is what I'd like to do with my application, is NSBundle what I should be looking into?
Yes, it is possible and was used in quite a few apps in the past. The method is described in this document. Once it's clearly declared in your app's Info.plist, Finder will show the resulting bundle as one file.
However, I can't recommend you to do that. Apple's own Keynote was using the bundle approach in the past, but it no longer uses it any more. Similarly, OmniGraffle (which is a diagramming app on OS X with a long history) used bundles to save projects, but it stopped doing that, too.
The reason is that the bundle is still seen as a directory by the non-Apple email software, or any browser, etc, although the Finder shows it as a file. It would be a mess if a user wants to attach your document in the bundle format to an email s/he is composing in Gmail inside a browser, say. That confused a lot of people.
So, it's possible, but I don't recommend it. One way out is to use the zipped bundle as the user-visible file, and to unzip it when the user opens it into a temporary directory. Then you can use NSBundle and/or NSFileWrapper apis to access files inside it.
Apple's File Wrapper sample seems to be what you want:
http://developer.apple.com/library/mac/#samplecode/PersistentDocumentFileWrappers/Introduction/Intro.html
It also demonstrates how to save a Core Data persistent store in the bundle. You can leave that part out if you just want to store resources.
The NSBundle class represents the application bundle, and can be used to access resources within the applicationm but you would you it for application data, not user data.
For each of the resources you mention, there's a way of saving this type, for example, for image files, you could use NSData to save the image data to disk, and for text files you could use the method writeToFile:atomically:encoding:error:.
You may very well want to take a look at Core Data (http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/CoreData/cdProgrammingGuide.html), a very good framework for managing the user's data model, to see if this would fit your needs.

Recommended document structure. File Wrappers? Roll my own?

I'm currently working out the best structure for a document I'm trying to create. The document is basically a core data document that uses sqlite as its store, but uses the Apple provided NSPersistentDocument+FileWrapperSupport to enable file wrapper support.
The document makes heavy use of media, such as images, videos, audio files, etc. with potentially 1000s of files. So what I'm trying to do is create a structure similar to the following:
/myfile.ext/
/myfile.ext/store.sqlite
/myfile.ext/content/
/myfile.ext/content/images/*
/myfile.ext/content/videos/*
/myfile.ext/content/audio/*
Now, first of all I went down the route of creating a temporary directory and placing all of my media in there. Basically creating the paths and file names '/content/images/image1.jpg' as I wanted them to appear in the saved file wrapper, and then upon save I attempted to copy these all into the filewrapper...
What I found was that the files were indeed copied into the wrapper with the file structure I wanted, but when the actual wrapper was saved, these files all magically disappeared.
Great.
So, I trashed my existing solution and tried to use file wrappers instead. This solution involved creating a content wrapper file directory when a new document was created, or loading in a content directory file wrapper upon opening a document.
When an image was added/modified, I created the necessary directory wrappers inside this root content wrapper (i.e. an images directory wrapper if it didn't already exist, or any other intermediary directory wrappers that needed to be created) and then created a regular file wrapper for the media, removing any existing wrapper for that file name if one was there.
Saving the document was just a case of making sure the content file wrapper was added to the document file wrapper, and the document would save.
Well... it did. The first time. However, any attempts to make any subsequent changes i.e add an image, save. Then replace image, save. Did not behave as expected, only showing the image from the first save.
So, my question is... first of all, which of the above approaches is the correct one, if at all, and what am I doing that wrong for them to fail.
And secondly, as I expect to be managing 1000s of images, is using file wrappers the correct way to go about things at all.
With that much media in play, you should likely give your users control over whether the media resides in the document or only a reference to the media is included in the document, and the media resides elsewhere, such as in a library/repository managed by your application. Then they could save out a (potentially many times larger) copy with all references resolved.
You might want to zip/unzip any directory so that users don't get confused trying to attach the document to an email. I believe iWork has been doing this with its document bundles for a while now.
As far as what you are doing wrong, no-one can say, as you haven't provided any code demonstrating what you are doing.
Why don't you create a one-off application that lets you select files on disk and saves those files in a document using a file wrapper? This would let you tackle this functionality without any interference from other issues in your application. Once you understand how to use file wrappers, you can port the code back or just write new code that works.

Objective-C / Cocoa: Uploading Images, Working Memory, And Storage

I'm in the process of porting an application originally in java to cocoa, but I'm rewriting it to make it much better, since I prefer cocoa a lot anyway.
One of the problems I had in the application, was that when you uploaded images to it, I had the images created, (as say an NSImage object) and then I just had them sitting in memory, the more I uploaded the more memory they took up, and I ended up running out of memory.
My question is this: if I am going to have users upload images to this application in cocoa, how should I go about storing them? I don't just want to copy the file paths, because I want what is saved to contain the images, etc. Is there any way to upload an image and copy it into a different place only for my application? Then load that image with the new path name as needed?
Only I would like it all to be consolidated. I'm going to implement saving by archiving one "master" object into an NSData*- so I'd like the images to be saved with that.
Is there a temporary location maybe where I could write the images to disk for my application, and then when I saved, they would all be archived into a single file? Also, how do I do this? Thanks.
If you only want to store the images temporarily, you can store the images in the temporary folder that you get by calling NSTemporaryDirectory(). You would then be able to load the images only when you need to display them.
If you want to save the images with your document then you should investigate using a package format for your document, so that the document is actually a folder containing your images and your archived data file. You can create a file wrapper containing all the files for your document bundle using the various methods of NSFileWrapper and then you would implement the -fileWrapperOfType:error: method of NSDocument in order to handle saving.
This would allow you to store the images unaltered and then lazily load them from the document bundle when required.