I'm trying to make an NSArray from a key in save data and make it mutable. Here's what I have so far:
NSMutableArray *availableThemes = [[[saveData valueForKey:#"availableThemes"] array] mutableCopy];
If I'm correct, sending array makes this object returned by availableThemes an array with the contents of the object, and then mutableCopy makes this array a NSMutableArray. Sadly, and obviously, I'm not. I get this error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray array]: unrecognized selector sent to instance 0x786c7430'
Here, I thought, sending array would turn this data into a NSArray. Instead, it causes a complier error. I know I did something stupidly wrong. Question is, what did I do?
You are calling the class method array on an instance of NSArray.
NSMutableArray *availableThemes = [[[saveData valueForKey:#"availableThemes"] array] mutableCopy];
From your crash log it is clear that the availableThemes key returns an NSArray object, so change your code to:
NSMutableArray *availableThemes = [[saveData valueForKey:#"availableThemes"] mutableCopy];
Related
I want to remove objects from NSmutableArray can one tell me the Best way to remove from NSMutableArray
.h
#property(nonatomic,retain)NSMutableArray *arr_property;
.m
_arr_property=[[NSMutableArray alloc]init];
MTPop *lplv = [[MTPop alloc] initWithTitle:SelectProperty(APP_SHARE.language)
options:[_arr_property valueForKeyPath:#"property_list.property_type_name"]
handler:^(NSInteger anIndex) {
txt_Property.text=[[_arr_property valueForKeyPath:#"property_list.property_type_name"] objectAtIndex:anIndex];
NSLog(#"index number %ld",(long)anIndex);
remove object--->>>
NSLog(#"index number %#",[_arr_property valueForKey:#"property_list"]);
[[_arr_property valueForKeyPath:#"property_list.property_type_name"] removeObjectAtIndex:anIndex]; ////hear the app is crashing
app is crashing error iam getting is
2015-06-09 13:21:31.104 Estater[2170:62264] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'
Think about your code:
_arr_property=[[NSMutableArray alloc]init];
You now have an empty NSMutableArray. It has no elements.
[... removeObjectAtIndex:0];
What did we just say? The array has no elements. It has no element 0 - to have an element 0 it would need to have one element at least, but it doesn't. There is nothing to remove.
[_arr_property valueForKeyPath:#"property_list.property_type_name"]
That part is the weirdest, but let's carry on. When called on an array, valueForKeyPath: results in an NSArray - not an NSMutableArray. So this gives you an empty NSArray. But you cannot say removeObjectAtIndex: to an NSArray, even if it empty - it is not mutable. That's the crash you are experiencing.
The real error is that you are calling removeObject on an element of your NSMutableArray:
[-->[_arr_property valueForKeyPath:#"property_list.property_type_name"]<-- removeObjectAtIndex:0];
The array looks empty, but if filled with something, to remove the first element you should do instead:
[_arr_property removeObjectAtIndex:0];
Firstly, you cannot work with NSMutableArray for key value coding it does not support. You must better use NSMutableDictionary for it.
As dictionaries store objects based on a key, whereas arrays store objects based on an index.
You can use NSMutableDictionary like this:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:something forKey:#"Some Key"];
// ... and later ...
id something = [dict objectForKey:#"Some Key"];
Secondly, valueForKeyPath: returns a value not array and valueForKey: returns array of value for the key and also that array is not mutable.
Edit:
Thirdly, after researching more on valueForKeyPath:, found its use in collection operation and syntax for using is. So, do it by changing
[_arr_property valueForKeyPath:#"property_list.property_type_name"]
To
[_arr_property valueForKeyPath:#"#property_list.property_type_name"]
I have the following statements
[[myListSet objectAtIndex:sender.tag] setValue:#"1" forKey:#"STATUS"];
where myListSet is defined as
NSMutableOrderedSet *myListSet;
myListSet is a list of dictionary entries, each with 6 key-value pairs, with one of the Keys being STATUS.
I thought I could update the values in one of the dictionaries using the above line. It worked in simulator, but not on my iPhone.
The error I am getting is
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
I guess my thought on updating the entry is incorrect. Any ideas on how to update a value for one of the keys for one of the dictionary entries in this set?
NSMutableOrderedSet allows you to modify its direct children. The error you are seeing arises because your NSMutableOrderedSet contains NSDictionary objects and not NSMutableDictionary objects.
In order to modify the sub-dictionaries, you will need them to be NSMutableDictionary objects. You could do this by:
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[myListSet objectAtIndex:sender.tag]];
dict[#"STATUS"] = #"1";
[myListSet replaceObjectAtIndex:sender.tag withObject:dict];
You should be aware that anything that was holding a reference to the original immutable dictionary will still be holding that dictionary and not your modified dictionary.
setValue:forKey makes use of key-value coding which lets you set an object's properties. NSMutableOrderedSet doesn't come with a "STATUS" property out of the box.
You want to use setObject:forKey instead
I believe your data structure is a set of NSDictionary. Your set is mutable but the dictionary within it is immutable.
If you have access to that dictionary then change NSDictionary to NSMutableDictionary and this will work. If not then
NSDictionary *myDictionary = [myListSet objectAtIndex:sender.tag];
NSDictionary *myMutableDictionary = [myDictionary mutableCopy];
[myMutableDictionary setValue:#"1" forKey:#"STATUS"];
[myListSet setObject:myMutableDictionary atIndex:sender.tag]
A user got this crash [__NSArrayM allKeys]: unrecognized selector sent to instance 0x178754d0
This is where the crash occurred.
NSArray *sortedArray = [[array allKeys] sortedArrayUsingFunction:sort context:nil];
I am not sure how this can occur. Any tips or suggestions on how to prevent this will be appreciated.
Edit:
This is my array, I should change the variable name.
id array = [parse objectWithString:answer];
What instance type is array? NSArray has no allKeys message that it can send, thus the unrecognized selector. You are treating array most likely as an NSDictionary.
allKeys function is of NSDictionary not NSArray or NSMutableArray.
You should call this on NSDictionary instances.
I have a loop that works fine the first time through but the second time through the loop I get:
-[NSNull count]: unrecognized selector sent to instance 0x3a094a70
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull count]: unrecognized selector sent to instance 0x3a094a70'
Here is the part in my code where I know it is crashing (the last line):
...
NSLog(#"dict::%#",dictForPost);
// collect the photo urls in an array
photosInDict = [NSArray array];
// photos is an array of dictionaries in the dictionary
photosInDict = dictForPost[#"photos"];
if (photosInDict.count) {
....
I know that when photosInDict doesnt have pictures in the dic it crashes but I dont get why since I initiated the array above it.
photosInDict = dictForPost[#"photos"]
replaces the object previously allocated and stored in photosInDict.
Therefore it does not make sense to allocate the array before. Just
NSArray * photosInDict = dictForPost[#"photos"];
and then check
if ([photosInDict isKindOfClass:[NSArray class]]) {
// Yes, it is an array. Do something with it.
if ([photosInDict count]) {
...
}
}
The result of dictForPost[#"photos"]; is giving you an NSNull object, not an array.
One option would be this:
NSLog(#"dict::%#",dictForPost);
// collect the photo urls in an array
// photos is an array of dictionaries in the dictionary
photosInDict = dictForPost[#"photos"];
if ([photosInDict isKindOfClass:[NSArray class]] && photosInDict.count) {
The line:
photosInDict = [NSArray array];
is pointless and should be removed.
You initialize photosInDict with an empty array, but then you overwrite it with the dictionary's value for "photos", which just happen to be NSNull. You need to check why your dictionary does not have an array for that key.
If the value can be NSNull depending on the situation, you must check whether it is an array or not before trying to count or taking some other action.
Looking this [__NSArrayI allKeys]: unrecognized selector sent to instance error up, it seemingly occurs when you send an NSArray the allKeys message which is meant for NSDictionary, but in this case I'm very clearly sending it to an NSDictionary.
Here's the code I use when interfacing with the Pocket API:
NSDictionary *articles = [response objectForKey:#"list"];
// Create an array we can use to sort the keys (and thus the articles) in order of when they were added
NSMutableArray *allKeys = [[articles allKeys] mutableCopy];
The last line there causes the error. But articles is very clearly declared as an NSDictionary? Why is it not liking it?
Oddly enough, if I inspect it at runtime it says it's an NSArray! Why did it change?
(lldb) po articles
$5 = 0x082103e0 <__NSArrayI 0x82103e0>(
)
(lldb) po [articles class]
$6 = 0x01b83b8c __NSArrayI
(lldb)
It may be declared in your code as a dictionary, but that doesn't make it a dictionary. It is truly an array and that is why you get the exception. Check your response so you know what you should expect.
Your code compiles because the compiler doesn't know that it's going to be an array and it trusts you that it will be a dictionary. It does this because objectForKey: returns id.