problem in nsuserdefaults - iphone

hii every one i have stil problem in nsuser defaults i'll tell the scenerio in detail
First i have diclared nsmutable array in appDelegate and set it in NSUserDefaults With For Key#"abc"
In FirstView Controller i first fetch the array from NSUserDefaults and save its values in NSMutable Array
When a Click say abcButton i have create a dictionary and adding values in it like
[abcDictionar setObject:[[abcMutableArray objectAtIndex:indexPath.row] objectForKey:#"abc"] forKey:#"abc"];
When i added all values in NSDictionary Then i add NSDictionary in NSMutable Array
like This
[abcMutableArray addObject:abcDictionary];
Then i save it NSUserDefaults
It Give me Exception in Point 4
When i add nsdictionary in Point One It All work fine but data in array is ambigous and it raise exception when am going to display it in tableview
if any one has some idea then let me know thanks in advance...:)

NSUserDefaults does not store mutable objects, only immutable ones. When you retrieve objects from it you must cast/copy them into mutable objects if you wish to mutate them.
Also be aware that:
The NSUserDefaults class provides convenience methods for accessing common types such as floats, doubles, integers, Booleans, and URLs. A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData.
Which is from the NSUserDefaults documentation.

Related

Accessing array/set of objects with keys

I want to be able to add objects to an NSArray and access them with Keys. Currently the way im doing it is creating a seperate NSDictionary of key-value pairs where the value is an integer number representing the index in my NSArray. This seems like an extra step to me.
If my understanding of NSDictionary is correct, only 'values' can be stored: a pointer to an object cannot.
Surely there must be an equivalent NSDictionary type function that allows objects to be stored and accessed with a key? I have looked through the documentation, but cant seem to find any answers, unless im missing something obvious.
NSDictionary is to store key value pairs. if you are adding key value pair after you created the dictioanry, use NSMutableDictionary class . example,
[dictionaryObject setObject:#"" forKey:#"abc"];
You can store objects in NSDictionary and can be accessed via keys...
In short, no.
An array (NSArray) is an ordered collection of references to objects, so simply said, an ordered collection of objects.
As opposed to dictionaries, which are unordered and values are accessed by keys.
You understanding of collections is probably wrong, you don't store values, but pointers (references).
The extra step is necessary if you need to store the references in an array, but in this case, you should consider using a dictionary. An option is to use keys that take care of the order.
For example :
[myDictionary objectForKey:#"1"];
could be an equivalent of :
[myArray objectAtIndex:1];
Thats wrong, you can store objects in a NSDictionary. Look at the method dictionaryWithObjects:forKeys: or dictionaryWithObjectsAndKeys:
I have no experience in Cocoa but looking at the documentation it seems like NSDictionary (or at least NSMutableDictionary) should handle your request (without you using NSArray).
I think I understand your problem. My suggestion for you is to use NSMutableArray and macros, like:
NSMutableArray *array=[[NSMutableArray alloc]init];
#define SOME_MACRO 0
id someObject;
[array insertObject:someObject atIndex:SOME_MACRO];
id getterObject=[array objectAtIndex:SOME_MACRO];
Of course define the macros in the header file.

Using NSDictionaries

I have a number of NSString objects I want to save into an NSDictionary.
How is an NSDictionary initialized with the keys and do the values need to be set there and then or can the dictionary be setup using just the keys and the objects later set?
To start with here's a link to the NSDictionary documentation, and NSMutableDictionary
You can create a NSMutableDictionary with just keys by passing [NSNull null] as the object for that key. It's important to use a mutable dictionary here otherwise you won't be able to change the dictionary after you've created it, and a dictionary that just has keys instead of objects is of little use.
That is what NSNull is for: to provide null values for collection types that don't allow nils.
A dictionary can be initialized both as empty or as a list of (value,key) pairs.
Initializing the dictionary just with keys and not values is useless/meaningless in Objective-C, since it will be equivalent to a void initialization.
If you want to create a dictionary and want to be able to set objects later, you have to use a NSMutableDictionary, that has not a static initialization of its data, through its setObject:forKey: method.

Application crash problem in iPhone

I have used NSMutable Dictionary and NSMutable Array. The datas are to be stored and retrieved from plist(Documents Directory) using NSArray of NSMutable Dictionary.
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'
Please Guide me why its happened?.
Thanks!
It might help if you post the exact code that causes. My guess would be that while you are using NSMutableDictionary, the call to valueForKey: returns to you a non-mutable NSArray, and you think it is returning you an NSMutableArray instance. Note that mutable arrays and dictionaries allow you to manipulate the collection of items inside them, but do not guarantee you that those items themselves are mutable. For example, if you check the Property List Programming Guide: Reading and Writing Property-List Data, you will notice the following example:
If you load the property list with
this call:
NSMutableArray * ma = [NSMutableArray arrayWithContentsOfFile:xmlFile];
ma is a mutable array with immutable
dictionaries in each element. Each key
and each value in each dictionary are
immutable.
If you need explicit control over the mutability of the objects at each level, use propertyListFromData:mutabilityOption:format:errorDescription:
You can also create an explicit NSMutableArray copy from the NSArray you got from the NSMutableDictionary.
you said you are retrieving the array as a NSArray and not casting it to a NSMutableArray before you attempt to remove an object for it. This causes an error since you can't remove an object from an NSArray
Suppose [something dictionaryValue] returns an immutable dictionary, and you want a mutable version of that dictionary. It is not enough to say:
NSMutableDictionary *d = [something dictionaryValue];
This merely tells the compiler that d is an NSMutableDictionary, but really it's the same immutable dictionary you got from [something dictionaryValue]. Instead, you need to create a new, mutable copy of the dictionary:
NSMutableDictionary *d = [NSMutableDictionary dictionaryWithDictionary:
[something dictionaryValue]];
Similarly, use [NSMutableArray arrayWithArray:...] for arrays.

How to load data from a plist for OpenGL Rendering (iPhone)?

I have an interesting problem.
I have 4 arrays stored in a .plist file, they are called "vertices", "normals", "texCoords" and "polygons" (this file is attached, along with GLViewController.m).
l want to load these arrays into arrays of type Vertex3D, Vector3D, GLfloat and GLubyte respectively, and then render them using OpenGL.
However, I am unsure how load the arrays and was hoping you might be able to help.
Bear in mind that I will want to modify the size of the arrays in the plist, so their size cannot be assumed to be constant (they could have any number of indices).
Links:
Plist: pastie.org/782396
GLViewController.m: pastie.org/782399
Plists are always loaded into arrays or dictionaries of "plist objects": NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary. So the only way to deal with them is to load the plist into an array or dictionary, then iterate through the resulting objects in order to build new arrays or whatever of the appropriate type.
So basically you'll need to write some sort of code to "translate" from plist to the object types needed by OpenGL.
Check out NSArray arrayWithContentsOfFile: and NSDictionary dictionaryWithContentsOfFile:
Also see the Property List Programming Guide.

Saving an NSMutableArray to Core Data

I want to add an NSMutableArray of NSStrings to one of my Entities in my core data model. The problem is that this isn't a supported type in Core Data.
I tried making a tranformable attribute, but the problem is that I see no way of turning a NSMutableArray to NSData, and then going from NSData, back to an NSMutableArray. Does anyone have an idea as to how this issue can be solved?
(I know I can archive the array, but I don't want to do that, I want it to be present in my model).
You could have a binary data attribute in your modeled object, archive the array to data, and hand it off to the object.
But I think the better way would be to have a to-many relationship, instead of using an array directly.
****Edit: Here's how to archive the array into NSData so that it can be used in your managed object***
NSData *arrayData = [NSKeyedArchiver archivedDataWithRootObject:[NSArray arrayWithObjects:#"1",#"2", nil]];
Basically, any class you have which conforms to the NSCoding protocol can be archived in this way. NSArray/NSMutableArray already conform to it. They tell all of their objects to archive themselves, so they must conform too. And all of those objects' members must conform, etc. It's like a tree.
Since your array conforms, and it's an array of NSString (which also conforms), then you're golden.