This is probably a naive question - but I want to double check to avoid wasting time with UIDocument if it doesn't do what I want.
Background: I have an app for which I have created a simple file system to save out user created documents as plists. I have my encoding/decoding all working. I am using some primitive types and handle that with the appropriate encoder method. I have a naming system and save the plists to a custom directory in the Library directory since these are docs the user should not have direct access to. (they can export their data to the documents directory if they so choose.
I started thinking about "autosave" and then discovered UIDocument - looks pretty great.
So given the above, does it seem like I can use UIDocument? What I save out is a custom class "Project" instance derived from NSObject. It contains a bunch of NSMutable arrays which contain instances of custom classes, NSDictionaries etc. I'm going through this UIDocument tutorial now: http://www.raywenderlich.com/6015/beginning-icloud-in-ios-5-tutorial-part-1 but don't want to discover that it's not going to work because of my data, etc.
Update:(for those reading along at home... ;-) Made some progress with this.
UIDocument uses NSKeyedArchiver rather than NSCoder (Wrong - see answer below) but the encoding method names are the same so it was easy to adjust what I already had.
Have been able to save out a plist that looks like it is capturing all the data - but I won't know until I try to read it all back in. Getting an error that I haven't sorted out:
NSFileCoordinator: A surprising server error was signaled. Details: Connection invalid
Not so surprising since I am saving locally not clear why it is trying to connect to iCloud at all. Hopefully I can switch that off.
I'm not sure where you get the thing about UIDocument using NSKeyedArchiver. For a simple implementation all you need to do is provide an NSData representation of your document contents -- it doesnt matter whether you generate that data from your model objects with NSCoder, NSKeyedArchiver, NSPropertyListSerialization, or some custom scheme.
Given that, I don't see any reason it shouldn't work with the data model you describe.
Related
Is there any way I can download json file from webserver and store it in a local folder for easy access for those with poor internet connection, so data will be downloaded once and user won't have to suffer every time.
I found similar questions on here1 and here2, but they were asked for objective-C, but I was looking something for Swift. Thanks
Yes, you can certainly do this. After you've read the remote JSON, it will be a Data object.1
Build a URL to a path in your app's caches directory and then use the Data method write(to:options:) to write that data into your file.
On read, check to see if the file exists in the caches directory before triggering a network read. Note that you need to be sure that the filenames you use are consistent and unique. (The same filename must always fetch the same unique data.)
1 Note that Mohammad has a good point. There are better ways of persisting your data than saving the raw JSON. Core Data is a pretty complex framework with a steep learning curve, but there are other options as well. You might look at conforming to the Codable protocol, which would let you serialize/deserialize your data objects in a variety of formats including JSON, property lists, and (shudder) XML.
Yes, you can create a .json file and store it in documents folder. First see how to create .json file, and then see how to store a file in documents folder.
Check this
I've used archiving, user defaults, and some Core Data in my apps before, but I'm running into a wall re: the best method for my current scenario. I have an app that needs to instantiate some objects from a resource file each time before it's used. An example of one of the objects could be a "MathQuestion" object that has the properties:
questionID (Int) - 2341
questionText (String) — "What is the square root of _?"
questionVariable (Float) – "4"
correctAnswer (a block/closure that returns a Float) – "{return sqrt(value)}".
Ideally, I'd just have something like a spreadsheet with columns for each of these properties and rows for each of the different questions. That way, I would really be able to visualize all the data and make quick changes during development.
My app uses Parse, which is great for visualization and easy editing of values, but for this case, I'd rather the resources remained on the device and not the Parse server. I've been considering Core Data up till this point, but (this could be my inexperience with C.D.), I'm unaware of any way to manually edit the data—and it seems like it may be overkill for what I'm looking for anyways. (I basically just need a way to upload and parse a CSV!) Any advice would be welcome!
I would still recommend Core Data. It is simply the most efficient and scalable mechanism to store and retrieve data.
When I work in your kind of scenario, what I often do is work with a spreadsheet where I can conveniently edit the data. You could edit a CSV version of it that you have included in your target. (If this does not work for you, you could also copy paste into a separate CSV file right into Xcode.)
On every start, you just trash the data store (using NSFileManager when creating the NSPersistentStoreCoordinator). Then you call a method that reads in the CSV and stores it in Core Data.
Once you are done with development, you simply keep the sqlite file (you can include it in the bundle and copy it over, or re-generate it from your CSV the first time the app runs).
First time asking a question on here, so please go easy if I don't provide enough info. Basically part of my iOS app allows users to take a picture which will be stored in a Core Data store. The attribute is a Transformable type, and I have created an NSManagedObject subclass which I simply use to set its image attribute to the new image provided by the user.
I know storing large files in Core Data is a bad idea, which is why I was excited when I saw the "Store in External Record File" option under the image attribute in the Core Data entity. However, my app performance says otherwise, taking several seconds on an iPhone 5 to load only a few images (which I know doesn't sound like much time, but considering how powerful the iPhone 5 is, older devices would likely take much longer with the same data).
I've looked around, and some people say that the Store in External Record File option is only applicable to the OS X environment, even though it is available in an iOS app. However, I also saw this under Apple's "What's New in iOS 5" doc (it's the next to last item under Core Data, near the end):
Managed objects support two significant new features: ordered relationships, and external storage for attribute values. If you specify that the value of a managed object attribute may be stored as an external record, Core Data heuristically decides on a per-value basis whether it should save the data directly in the database or store a URL to a separate file that it manages for you.
So my question is, who's right? Is it true that Apple made a mistake in giving this option for iOS apps, and that it actually does nothing unless you're on the Mac, or does it actually do something and I'm not configuring it the right way, or is it doing what it's supposed to do and the performance is bad anyway?
I've seen some guides explaining how to store large files (like images) as files, and save the URL to them in the Core Data store instead, but since this is essentially what this new option is doing, or maybe should be doing, I'm not sure if following these guides would even help.
I'm really sorry if this has been asked before. Normally I'd be fine with figuring this out on my own, but Core Data is totally new to me, and I'm still not sure how I managed to squeak by the initial setup. Thank you for any help you can offer!
who's right ?
the iOS docset for the NSAttributeDescription class does mention the allowsExternalBinaryDataStorage and the setAllowsExternalBinaryDataStorage: methods so there is little chance that there is a mistake from Apple.
are you doing something wrong or is slow anyway ?
You said that
The attribute is a Transformable type
But Core Data has a Binary data type. Maybe only this one is linked to the external storage capability.
if that's not it, we don't have enough info here:
How many pictures do you store ?
What are their sizes ?
Do you automatically fetch all the images ?
Also, the Apple doc states that:
Core Data heuristically decides on a per-value basis…
Did you use a migration or are you starting from scratch ?
You could have a look in your app's sandbox to see if your pictures are really saved outside of CoreData.
Hope this helps.
Good question!
Check this post:
Storing blobs in external location using built-in CoreData option
Apparently it should work. You should also try it in the simulator and inspect the application data folder to see if the folders are created as described (~/Library/Application Support/iPhone Simulator/... - you will figure out the rest of the path). Also you could inspect the sqlite file with the sqlite3 command to see if the binary data is in the database.
I haven't personally used this option as I would prefer to go for manually saving the images in a folder and store a reference to them in the database instead. This way it will be easier to create UIImage object from the file to be displayed, would have better control on what goes where and so on and so forth. Will take some extra labour though!
Hope that helps you out.
I am making a simple iPhone app that will basically be an editor.
As such, I need some way to store the documents the user creates.
Since on iPhone, the concept of the filesystem is not present for the user, I searched around to see what I should use.
I found this question & answer that basically says to use Core Data, but I recently found out about NSFileManager.
My question simply is, for user-created documents, what is the best storage system to use? Traditional files by using NSFileManager? Core Data? Something else?
Personally, I would use CoreData because it will abstract away all of the file-management code for you. If you are making simple text documents then this isn't such a big deal, but if you are working with a complex document architecture (i.e., a collection a numerous objects) then it can save you a lot of effort.
If the user wants to export their document it is very easy to write a function to do so with your CoreData objects.
The only downside to CoreData is that if you are using non-standard attributes it can get a little bit tricky, but it is certainly not a deal breaker in most cases.
People create document formats without CoreData all of the time, so there are plenty of examples out there, and it will just come down to personal preference. There really isn't any generalized right answer to this - it a design decision that should be evaluated on a per-app basis.
If all of your data for displaying the file is contained in one long string (like HTML) then I would recommend that you use the file manager, since it will be easy to get a list of files in a certain directory to display to the user for opening. However, if they are not self contained (like NSAttributedString, which has many stored formatting regions along with the actual content) then you should use CoreData, as it will be easier to keep all the pieces together.
I am writing a very simple application, for the iPhone. Unfortunately I am really a newbie.
What I am trying to do is to save data at the end of a user experience. This data is really simple, only string or int, or some array.
Later I want to be able to retrieve that data, therefore I also need an event ID (I suppose).
Could you please point out the best way, API or technology to achieve that, XML, plain text, serialization... ?
Use NSUserDefaults. Straight forward and easy to use. This will handle all File I/O for you, and takes only a couple lines of code.
NSUserDefaults is a good choice for small amounts of data.
If you need to manage something larger than a kilobyte or so, you might consider using the initWithContentsOfFile: methods of NSArray or NSDictionary to read in a .plist file. To write the file, use the writeToFile:atomically: methods. This file needs to go in your app's documents directory.
Me and my team created a simple class for this purpose which as Mark pointed out makes use of NSUserDefaults. Hopefully this helps you out...
http://getsetgames.com/2009/10/07/saving-and-loading-user-data-and-preferences/