First, I am an objective-c newbie. Just thought I would get that out of the way ;)
I am trying to handle objects but I'm a bit confused about the best way to go around doing so. Let me put this into a bit of context:
I have a preference area where a user can add a new Foo to the app. Once the input fields are validated it should spawn a new object of type Foo (according to my Foo class). The user could have anywhere from 1 to 100 of these in the app. What is the best way of keeping track of all of these? How can I create them in the code and keep track of them?
I bet that made no sense, but I have tried to explain it the best I can. Please feel free to ask for more details.
Thanks in advance for any help
Oh, I thought you said lots. :-) I was already planning an explanation on the flyweight pattern when I read 'up to 100'. You can just put these in an array.
It depends somewhat on what you want to do with them. To just keep them in RAM, you can store pointers to those objects in an NSArray (or NSMutableArray), or if you need to be able to find them with a key use an NSDictionary (or NSMutableDictionary). To save them so that they persist even after your app exits so you can load them again next time you can them write them to a file (plist, sqllite, coredata, ...).
Related
I'm currently looking for the best way to save data in my iPhone application; data that will persist between opening and closing of the application. I've looked into archiving using a NSKeyedArchiver and I have been successful in making it work. However, I've noticed that if I try to save multiple objects, they keep getting overwritten every time I save. (Essentially, the user will be able to create a list of things he/she wants, save the list, create a few more lists, save them all, then be able to go back and select any of those lists to load at a future date.)
I've heard about SQLite, Core Data, or using .plists to store multiple arrays of data that will persist over time. Could someone point me in the best direction to save my data? Thanks!
Core Data is very powerful and easy to use once you get over the initial learning curve. here's a good tutorial to get you started - clicky
As an easy and powerful alternative to CoreData, look into ActiveRecord for Objective-C. https://github.com/aptiva/activerecord
I'd go with NSKeyedArchiver. Sounds like the problem is you're not organizing your graph properly.
You technically have a list of lists, but you're only saving the inner-nested list.
You should be added the list to a "super" list, and then archiving the super-list.
CoreData / SQL seems a bit much from what you described.
Also you can try this framework. It's very simple and easy to use.
It's based on ActiveRecord pattern and allow to use migrations, relationships, validations, and more.
It use sqlite3 only, without CoreData, but you don't need to use raw sql or create tables manually.
Just describe your iActiveRecord and enjoy.
You want to check out this tutorial by Ray Wenderlich on Getting started with CoreData. Its short and goes over the basics of CoreData.
Essentially you only want to look at plists if you have a small amount of data to store. A simple list of settings or preferences. Anything larger than that and it breaks down specifically around performance. There is a great video on iTunesU where the developers at LinkedIn describe their performance metrics between plists and CoreData.
Archiving works, but is going to be a lot of work to store and retrieve your data, as well as put the performance challenge on your back. So I wouldn't go there. I would use CoreData. Its extremely simple to get started with and if you understand the objects in this stack overflow question then you know everything you need to get going.
I am pulling data from an API and then building out my data objects with it. I want to cache this data for the future. I have been storing the string from the api in NSUserDefaults and then re-parsing it each time the app loads. This works, but it really seems like the wrong way to go about it.
How can I do this?
Have you noticed the NSCache?
An NSCache object is a mutable collection that stores key-value pairs, similar to an NSDictionary object. The NSCache class provides a programmatic interface to adding and removing objects and setting eviction policies based on the total cost and number of objects in the cache...
Personally I'm quite fond of the EGOCache classes, I use them quite a lot in my projects:
https://github.com/enormego/EGOCache
The classes are easy to use, I used to have my own classes with a similar design, but these are just more well-rounded, so I decided to stick with them (don't wanna reinvent the wheel).
There are many different solutions to this problem and there is no "right" way to do it. A few popular options are:
Core Data - Apple's framework for persistence. Very performant, but more difficult.
SQLite - Fast and flexible, but bare bones.
Plists - Basically writing a file to disk, you have to read and write manually.
NSUserDefaults - The lightest weight "key-value" option.
I would encourage you to read up on all four and see which one works best for you.
I vote Core Data
What type of data? If its text/string bases SQLLite would probably be the best.
I'd store the computed/parsed data in either a Core Data store, or in NSData flat files in your application's Documents directory. You're correct that storing that in NSUserDefaults and then re parsing feels a little overkill.
I've been using the Game State Management sample which has worked so far. I've hit a snag though: when Tombstoning, the screens are serialised; the only trouble is, the MessageBoxScreen has event handlers for Accepted and Cancelled.
What's the best way to serialise these? I did a bit of research on using Expression Trees but this seemed overly complex for what I wanted to do.
How do you serialise these? Or... What alternative approach do you use to save the state of a screen that contains delegates?
I'd definitely steer clear of attempting to serialize anything remotely resembling a lambda, or for that matter, named methods. Remember: you're storing state, and nothing else.
Depending on how far and wide your various assignments to these delegates are, you might be able to get away with maintaining a Dictionary<String, WhateverDelagateType>, serializing the keys and looking up the callbacks after deserialization.
Another thing to consider--I'm no expert, but reading between the lines it sounds as if you're working towards tombstoning a very temporary modal dialog. Do you really want that? You might be better off bringing your user right to the high scores table, or whatever follows your dialog, on his/her return.
I decided against this. I instead persists game flow as a kind of 'flow chart'.
The flow chart is declared in code and has properties 'LastShape' and 'LastResultFromShape'.
In my code, I rebuild the flow chart definitions each time, something like this:
flowChart.AddShape( "ShowSplash" );
flowChart.AddLine( "MainMenu", ()=>lastResult=="Clicked" || lastResult=="TimedOut");
flowChart.AddShape( "MainMenu");
flowChart.AddLine( #"ShowOptions", ()=>lastResult=="OptionsClicked");
flowChar.AddLine( #"ShowSplash", ()=>lastResult==#"TimedOut");
etc.etc.
The flow goes from the top down, so 'AddLine' relates to the last shape added.
After tombstoning, I just read the last shape and the last result and decide where to go in the flowchart based on that.
There are a multitude of key-value stores available. Currently you need to choose one and stick with it. I believe an independent open API, not made by a key-value store vendor would make switching between stores much easier.
Therefore I'm building a datastore abstraction layer (like ODBC but focused on simpler key value stores) so that someone build an app once, and change key-value stores if necessary. Is this API too simple?
get(Key)
set(Key, Value)
exists(Key)
delete(Key)
As all the APIs I have seen so far seem to add so much I was wondering how many additional methods were necessary?
I have received some replies saying that set(null) could be used to delete an item and if get returns null then this means that an item doesn't exist. This is bad for two reasons. Firstly, is it not good to mix return types and statuses, and secondly, not all languages have the concept of null. See:
Do all programming languages have a clear concept of NIL, null, or undefined?
I do want to be able to perform many types of operation on the data, but as I understand it everything can be built up on top of a key value store. Is this correct? And should I provide these value added functions too? e.g: like mapreduce, or indexes
Internally we already have a basic version of this in Erlang and Ruby and it has saved us alot of time, and also enabled us to test performance for specific use cases of different key value stores
Do only what is absolute necessary, instead of asking if it is too simple, ask if it is too much, even if it only has one method.
Your API lacks some useful functions like "hasKey" and "clear". You might want to look at, say, Python's hack at it, http://docs.python.org/tutorial/datastructures.html#dictionaries, and pick and choose additional functions.
Everyone is saying, "simple is good" and that's true until "simple is too simple."
If all you are doing is getting, setting, and deleting keys, this is fine.
There is no such thing as "too simple" for an API. The simpler the better! If it solves the need the way it is, then leave it.
The delete method is unnecessary. You can just pass null to set.
Edited to add:
I'm only kidding! I would keep delete, and probably add Count, Contains, and maybe an enumerator (or two).
When creating an API, you need to ask yourself, what does my API provide the user. If your API is so simplistic that it is faster and easier for your client to write their own app, then your API has failed. Ask yourself, does my functionality give them specific benefits. If the answer is no, it is too simplistic and generic.
I am all for simplifying an interface to its bare minimum but without having more details about the requirements of the system, it is tough to tell if this interface is sufficient. Sure looks concise enough though.
Don't forget to document the semantics for "key non-existent" as it isn't clear from reading your API definition above. updated: I see you have added the exists method: is this necessary? you could use the get method and define a NIL of some sort, no?
Maybe worth thinking about: how about considering "freshness" of a value? i.e. an associated "last-modified" timestamp? Of course, it depends on your system requirements.
What about access control? Is it within scope of the API definition?
What about iterating through the keys? If there is a possibility of a large set, you might want to include some pagination semantics.
As mentioned, the simpler the better, but a simple iterator or key-listing method could be of use. I always end up needing to iterate through the set. A "size()" method too, if not taken care of by the iterator. It obviously depends on your usage, though.
It's not too simple, it's beautiful. If "exists(key)" is just a convenient shorthand for "get(Key) != null", you should consider removing it. I guess that depends on how large or complex the value you get() is.
I have looked for several hours for a good tutorial on how to store data for my command line program that I am writing in Objective-C. It seems like my options are NSUserDefaults, Plists, sqlite, or XML.
Now, I think at most I'd have 50kb of data to store, retrieve, and modify, so it seems like from what I read Plists would work just fine, but I'm having difficulty finding a good tutorial online. (I'm completely new to Objective C). Everything I find is for the iPhone, or NSUserDefaults - neither of which I'm looking for.
Can anyone point me in the right direction? I'm hoping just to replicate the very basic functionality of "defaults write com.yourcompanyname.yourappanme key data"
I would greatly appreciate a nudge in the right direction, but again, I'm completely new so the most basic tutorial is best.
The Property List Programming Guide is a good place to start.
The easiest way do do what you want is to put everything you want to save into an NSDictionary or NSMutableDictionary, and then use writeToFile:atomically: to save the data. You can read it back with initWithContentsOfFile:.
The property list guide linked above would rather you use NSPropertyListSerialization to generate an NSData object from the dictionary, and save that instead. That's a (little) bit more involved, but arguably a better approach.
You actually might want to look into using Core Data: http://developer.apple.com/mac/library/documentation/cocoa/conceptual/CoreData/cdProgrammingGuide.html
It will let you save data in XML format.