I am trying to come up with a structure for my data. Let's imagine that I have a library. In this library, there are different books - I can add books to the library and delete them. So I guess I would need to start with an NSMututableArray:
NSMutableArray *entireLibrary;
Each book in this library has a certain set of features. Some require an array (such as different strings for the headings in each book) and other features, such as page length, require only an integer. The set of characteristics stays the same for each book, like so:
NSString *bookTitle;
NSMutableArray *chapterHeadings;
NSInteger *pageCount;
My question is what the best way would be to store all of this information in my library. Right now, I only have different arrays, strings or integers and I can't see how I can assign them to an individual book which is then placed in my library -- and how to access the data when I need it.
Create your own custom class called BookClass. Keep the bookTitle, chapterHeadings and pageCount as properties of that class and then add BookClass objects into the entireLibrary NSArray.
Related
I am developing an iPhone application in it I am having around 15 arrays and 15 more array which has value in it corresponding to the value in array e.g. NSArray *XYZ = {a,b,c,d} and array NSArray *ABC = {w,x,y,z} such that value 'a' corresponds to 'x' .Can comebody tell me what is the best way to follow MVC in this scenario like I have to make function (returning array) for each array in another class or should I make class for every array.
I would write all your business logic as classes with those arrays in a MODEL file, access those classes from the CONTROLLER file. And then once you have all your data, access from the CONTROLLER the VIEW file to output. Inside the MODEL write functions for those arrays so that you can reuse them, if they vary they may need own functions. This is a helpful link: http://php-html.net/tutorials/model-view-controller-in-php/ and those videos give you a taste of the logic behind MVC: http://www.youtube.com/watch?v=HFQk8WGK1-Q&feature=bf_prev&list=UU9-GXsmQQ-N4h8ZsKI8CSkw
I'm a new developer creating a simple "dictionary" app for personal use and my question is about how to properly implement the Model-View-Controller design in my particular situation. Please bear with me for the necessary background:
I want to be able to hit a button and have a label display a word on one side of the screen, and to have another label display a list of associated words on the other side.
For instance: when I hit the button I want the main label to display "cats" and for the list to display "tiger", "snow leopard", "lion", etc. The output would be random: the label displayed would be random and the list would be scrambled.
I've achieved this output in the Xcode 4.3 console through storing each list in an NSMutableArray, and using an NSDictionary to hold all of the NSArrays. Here is the code:
//creates lists
NSArray *catList = [NSArray arrayWithObjects:#"Lion", #"Snow Leopard", #"Cheetah", nil];
NSArray *dogList = [NSArray arrayWithObjects:#"Dachshund", #"Pitt Bull", #"Pug", nil];
...
//creates dictionary and stores lists values with dictionary keys
NSMutableDictionary *wordDictionary = [[NSMutableDictionary alloc] init];
[wordDictionary setObject: catList forKey:#"Cats"];
[wordDictionary setObject: dogList forKey:#"Dogs"];
...
//randomizes selection of dictionary key
NSInteger keyCount = [[wordDictionary allKeys] count];
NSInteger randomKeyIndex = arc4random() % keyCount;
//displays selected key, which is the main word
NSLog(#"%#", randomKey);
//selects array list corresponding to key
NSMutableArray *randomlySelectedArray = [wordDictionary objectForKey:randomKey];
//shuffles the output of the selected word list array
for( int index = 0; index < keyCount; index++ )
{
int randomIndex = arc4random() % keyCount;
[randomlySelectedArray exchangeObjectAtIndex:index withObjectAtIndex:randomIndex];
}
//prints word list and removes displayed dictionary selection
NSLog(#"%#", randomlySelectedArray);
[wordDictionary removeObjectForKey:randomKey];
(I need to add code that does displays a main word and list one at a time, maybe using NSTimer, but this is what I've got so far.)
Using a single-view template in Xcode, I've been able to get the simulator to show a main word and a corresponding list by adding some of this code to the IBAction method of the button in my view controller implementation file. (Of course I changed NSLog to initWithFormat.) However, none of my randomization code works.
My question, finally, is how do I separate things so that they conform best to the MVC design? I'm thinking that: My button and my two labels constitute the view. My view controller is the controller, and my NSArrays and NSDictionary data are the Model.
However, I've been keeping all of my model data inside the view controller, which I'm pretty sure is wrong. I think that I need to figure out how to create a class for my NSArrays and NSDictionary to store my model data. Then I must manage to get my button & labels to display the desired text of my model data via my view controller. At least I think that's how MVC works.
I'm wondering if that understanding is correct and if anyone has any pointers on how to organize my model data most effectively to get my desired output.
Thanks very much for any help! I'm stuck!
Before starting to design an application based on MVC. We first need to know what these different components are and what MVC help us to achieve?
Why we use MVC?(Model-View-Controller)
Because it helps us in:
Separating responsibilites also leads to reusability
By minimizing dependencies, you can take a model or view class you’ve already written and use it elsewhere
Think of ways to write less code
While designing an application based on MVC, we should focus on above points.
Lets relate this 'Dictionary' application with real world dictionary.
A dictionary is composed of words, their meaning, pronunciation, examples, usage, antonyms, synonyms, indexes and other similar information.
When a user wants to look for a particular word he will use top-margin word for fast look-up. Once he found the right page he will go to that word and see its meaning, usage or other needed information.
Model Part:
Lets draw analogy between your application and what I described above.
In your application you will be having a class : 'Dictionary' which
will represent the real world dictionary. This dictionary is composed
of words, their meaning, pronunciation, usage and other information.
So we will need an array of words which will contain 'Word' object.
The 'Word' class will have all the information that we wish to provide
for particular word. You can also provide other attributes that you
can think of that belongs to Dictionary and add them to it.(Here we are talking about content only)
Now we need to think of different operations to be performed on this dictionary. The most basic operation are creating a dictionary and accessing it.
We will have a DictionaryCreator class which will add all the words that our dictionary will have. So this is another class
'DictionaryCreator'. Or we can put this creating logic in 'Dictionary'
init methods. But it will be helpful to have this class this will
enable the dictionary add-word features.
Once DictionaryCreator creates a dictionary, User will be ready to use it. So we will need to provide different operations that a user
can perform on 'Dictionary' as its methods. In our case we can
consider user is over controller, which in fact is controlled by real
user.
The above techique will help you to create a component that performs only its responsiblity and can be reused in other application or extended for future use.
*Always remember Model is the most reusable component of MVC design. So whenever you are in doubt about Model just go remind the words 'Model must be reusable'.
(Not aware of views or controllers)
So we have just finished Model part of the application.
View Part:
This depends on you, what interface you wish to provide to user. But lets again consider the real world Dictionary. A real world dictionary's content(information) is spread across several pages. This view helps us to view/access/mark/bookmark in dictionary.(Remember that here user performs all the operation and not the pages neither the dictionary). The pages have easy look-up word on top or bottom and some pronunciation guidance at bottom.
In your application you said "I want to be able to hit a button and have a label display a word on one side of the screen, and to have another label display a list of associated words on the other side."
Here we have again have multiple options to implement this, you can create view using Interface Builder and connection them with your controller. But then again this controller and View will be tightly coupled and when we wish to use similar interface somewhere else we will be unable to do so. So for reusability we will create another UIView class and create it with a new View XIB and load this nib. So in future if you need similar kind of view you can easily reuse(like cocoa-touch provides us UIView, UIButton etc.).
*View also tends to be a reusable component in MVC.
(Not aware of controllers, may be aware of relevant model objects)
Controller Part:
Now we have created view and model but how will they communicate? Controller will help them in this. A controller :
Knows about model and view objects
The brains of the operation
Manages relationships and data flow
Typically app-specific, so rarely reusable
*The points and definition I have taken from Stanford University Lectures[CS193P - Lecture 6
iPhone Application Development
Designing iPhone Applications Model-View-Controller (Why and How?) View Controllers]
Update:
Recently, I have come across another good lecture on MVC. It explains this design concept in much better way with very nice examples. It is available at iTunes U or you can directly go to first lecture by iPad and iPhone Application Development (SD) by Paul Hegarty.
I have a Class for handling my data in my project, and now I need to store the data.
I'd like to use a Plist but I'm a bit unsure of how to start.
My class is pretty simple - 6 pieces of data, flat (no hierarchy).
I want my app to start with no data, so can I assume that I should create the PList programmatically once the User creates their first piece of data? (That is, don't create a .plist file in 'Supporting Files' prior to distribution?)
Then, when the app starts the next time, read the data and create an NSMUtableArray array of Class instances?
To create a property list, all you need to do is use appropriate types (i.e. those that support the property list format: NSData, NSString, NSDictionary, NSNumber, NSDate, NSArray), store them in a single container, and tell the containing object to write itself to a file. To read the data, you can initialize that same type using a path. For example:
// writing some data to a property list
NSString *somePath = ... // replace ... with the path where you want to store the plist file
NSMutableDictionary myDict = [NSMutableDictionary dictionary];
[myDict setObject:#"Caleb" forKey:#"name"];
[myDict setObject:[NSNumber numberWithInt:240] forKey:#"cholesterolOrIQ"];
[myDict writeToFile:somePath atomically:YES];
// reading the file again
NSDictionary *readDict = [NSDictionary dictionaryWithContentsOfFile:somePath];
The simplest way is to simple save an NSArray or NSDictionary to disk. Caleb's answer goes into detail there so I won't repeat it, other than to say you might have to convert a non-compatible object like NSColor to an property list object like NSData. It's up to you to do this each time you save or load your data.
NSKeyedArchiver and NSKeyedUnarchiver give you a little more control over the process, but work pretty much the same way. You provide (or get back) a plist compatible root object (usually an NSDictionary) that contains your data. I recommend creating a dictionary that includes your data structure as well as an arbitrary number (your app's build number is a good choice) to use as a version indicator. This way if you ever update your data model you can easily determine if you need to do anything to convert it to the new version.
If you're putting your own objects into the data file, look into NSCoding. The protocol gives you two methods using NSKeyedArchiver and NSKeyedUnarchiver to save and restore your data. This is by far the most straightforward approach if your data model consists of anything more than a few simple strings and numbers, since you're dealing with your own native objects. In your case, you would have your data class implement NSCoding and use the NSKeyedArchiver and NSKeyedUnarchiver methods to encode your six instance variables. When it's time to save or load, pack the instance of your class into an NSDictionary (along with a versioning number as I mentioned above) and call NSKeyedArchiver's archiveRootObject:toFile:. Your save an load methods deal only with your own data object, which makes things easy for you. The common pitfall to watch out for here is if your custom data object contains other custom object. This is fine, but you have to make sure every object that's going to be saved has its own NSCoding implementation.
Two things you can do:
Use NSUserDefaults:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html
The objectForKey method is the one you want to use to store your class. But, as pointed out in the comments, this shouldn't really be used for storing lots of user data; it's best for saving preferences.
For storing more data, you might want to look at Core Data. It's more complex, but should be better suited to your needs. Here's a tutorial on it:
http://mobile.tutsplus.com/tutorials/iphone/iphone-core-data/
Neither of these seems best for your simple application, but I leave this answer up since it gives alternatives for saving data to the iPhone.
The question is quite simple: When I create a new API or Service Class should I create a custom class for the objects that are being passed around or should I just stick to an NSDictionary which simply holds the data in a key-value-style format.
Obviously there are pros and cons but where do you guys think is the threshold of using one over the other?
NSDictionary:
+ No dependencies
+ Very Flexible
+ Commonly used
+ Build-in support for NSCoding
- Structure not defined -> Runtime errors
A custom Object:
+ Structure defined
+ Property-style accessors: myObject.someProperty
- Can result in a rel. big number of classes for nested objects
Update: Included remarks from jbat100
I usually have a set of domain models, which fit better with the MVC approach of iPhone development. Having specific objects also enables you to enforce type-safety a lot easier and also reduces complexity in the long run. If you have NSDictionaries containing NSArrays and more NSDictionaries etc etc to represent your object graph, it can very quickly become unmanageable.
It really depends how much you expect your data model to change. Dealing with changes once you have a custom class based data model can be tricky especially when you have archives (NSCoding stuff) with different versions of the model (in already shipped versions of your app), you must be very careful to ensure backwards compatibility and avoid nasty run time surprises. In that respect NSDictionary based models are, as you say more flexible. However they do not allow all the customized checks and behaviour that custom classes do. Also custom classes make the data model more explicit for coders unfamiliar with the code, from my experience, developers often get sloppy (especially when inexperienced) when dealing with NSDictionary based models which can quickly result in an incomprehensible mess, so if you go down that route, document well and be disciplined!
If you need readonly access and do not need methods, you can do following:
#interface NSDictionary (MyClassCategory)
-(NSString*) someField;
#end
#implementation NSDictionary (MyClassCategory)
-(NSString*) someField {
return [self objectForKey:#"someField"];
}
#end
typedef NSDictionary MyClass;
And use it:
MyClass* myClass = ...;
NSString* value = [myClass someField];
So I want to know if this is a good idea or a bad idea.
I'm building a simple iOS game (using standard UI Controls) which allows a user to create Characters, and Monster "Templates", then build Encounters which references Characters and Monsters and interact with them.
When the user creates an encouner, there is a simple Modal View which allows them to name the encounter, then push to another VC to select the characters participating, go back, push to a second view controller to select the Monster Templates involved, as well as how many of those monsters will be participating.
The goal, in the end, is to have the Monster Templates be used to construct "real" monsters that will be references in the Encounter.
Sample Encounter
Player Characters
Ramza Beoulve
Delita Hiral
Monsters
Orc 1
Orc 2
Orc 3
For the character selection piece, I used an NSSet to store the Character Entities selected and pass it between view controllers. (This way I avoid having to mess with the managed object context very much prior to actually saving the new encounter)
For the monsters, since I need to store a quanitity as well as the entity, it's a little more complicated.
So my original thought was to store them in an NSArray of NSDictionaries which in turn contain the Monster Template and the Quantity.
The problem with that approach is I have to loop through the NSArray and open each individual dictionary to check if a particular monster template exists or not.
It might not matter much at this scale of application, but it seems inefficient.
So I thought instead it might be better to simply maintain two NSMutable Arrays
NSMutableArray *selectedMonsterTemplates;
NSMutableArray *selectedMonsterTemplateQuantities;
This way I can simply call
[selectedMonsterTemplates containsObject:monsterTemplate];
when I need to check if something is already in there, and when I add or subtract the quantity for a particular monster, I can simply update both Arrays.
Then when the Encounter is saved I can simply iterate over the Array once to create my individual monster instances in the quantity desired, and associate them with the Encounter.
I'm concerned that this approach, while simple and efficient, might lead to concurrency problems if there is a small mistake in the code. Is there a better way to go about this?
Maybe its a better design to add a class, lets say TemplateStore. (Or whatever you like)
#interface TemplateStore : NSObject {
MonsterTemplate *template; //Super class of a monster entity.
NSInteger quantity;
}
- (id) initWIthMosterTemplate:(MonsterTemplate *)temp;
- (void) increaseQuantity;
- (BOOL) isKindOfTemplate:(MonsterTemplate *)otherTemp;
#property (readonly, retain) MonsterTemplate *template;
#property NSInteger quantity;
#end
WHen you store this kind of object in an array, you can iterate over it and use the isKindOfTemplate method to know if the MonsterTemplate exists. Then just increase the quantity.
Generally speaking, you wouldn't make an array of dictionaries just to hold structured data, you'd use a single dictionary with the item (template) as the key and the quantity as the value. Pseudocodey it would be like:
quantity=dict[template];
Of course that's assuming you have templates stored as pointers somewhere. A better alternative is to use structures:
struct monster_t { template_t t; int quantity; }
And then you hold an array of these things:
monster_t[] bestiary;
Or even better, figure out an ID of sorts (unique monster name file?) and hold it in a dictionary:
dictionary<string, monster_t> dict;
dict["big_monster_01"].quantity=5;
Of course this system is pretty useless, you don't care about quantity at all. What you do care about is about actual monster instances in the world, basically templates with customized values for hit stats, loot etc and a position:
struct monster_instance_t { monster_t template; vector position; }
monster_instance_t[] monsters; // who cares what they are?
// that's what polymorphism is for!