In iOS 6 I can do this:
NSDictionary *d = #{anObject : "key"};
But apparently when the object is a UIImageView or UIWebView (or maybe others too), it crashes with:
'NSInvalidArgumentException', reason: '-[UIWebView copyWithZone:]: unrecognized selector sent
Changing the dictionary declaration to the old way works:
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:anObject,#"key", nil];
Any idea why this happens?
The syntax is
NSDictionary *d = #{<key> : <value>, ...};
In your case:
NSDictionary *d = #{#"key" : anObject};
So your code tried to use anObject as the key. That failed for UIWebView because keys must
conform to the NSCopying protocol .
This is because the new syntax expects keys and values to be ordered in reverse, compared to dictionaryWithObjectsAndKeys:
NSDictionary *d = #{ #"key" : anObject};
Also, do not forget the # sign in front of NSString literal.
Key first, value second.
NSDictionary *d = #{#"key" : nObject};
Related
I am tring to get value from an NSDictionary but getting an Exception that the keys is not defined.
NSDictionary *userNames=[[NSDictionary alloc] init];
NSString * testValue = #"";
testValue = [userNames valueForKey:#"#&"];//crashing here when key is #&
Terminating app due to uncaught exception 'NSUnknownKeyException',
reason: '[<__NSDictionaryM 0x2831eeec0> valueForUndefinedKey:]
Never use valueForKey to get a single value from a dictionary unless you know what KVC is and you really need KVC.
The dictionary is empty, the key does not exist and the leading # has a special meaning in KVC so valueForKey crashes in this case.
The proper API is objectForKey but just use modern key subscripting to get at least nil if the key doesn't exist
testValue = userNames[#"#&"];
Apple doc
If key does not start with “#”, invokes object(forKey:). If key does start with “#”, strips the “#” and invokes [super valueForKey:] with the rest of the key.
you may do
testValue = [userNames objectForKey:#"#&"]
or
testValue = [userNames valueForKey:#"&"]
Probably you are not declaring keys and values. NSDictionary requires you to init with Values and keys. (Whether fetch them from a file or declare them while initializing.
NSDictionary * userNames = [[NSDictionary alloc] initWithObjectsAndKeys:
#"value1", #"key1",
#"value2", #"key2",
nil];
NSString * testValue = [userNames valueForKey:#"key2"];
NSLog(#"%#", testValue);
Also notice that the value is written before and then key is defined. Refer to this document.
If you want to declare the dictionary first (like you did in your question) and then add the values and keys to the dictionary, You have to use NSMutableDictionary.
NSMutableDictionary *userNames1 = [[NSMutableDictionary alloc] init];
[userNames1 setValue:#"firstValue" forKey:#"key1"];
[userNames1 setValue:#"secondValue" forKey:#"key2"];
NSLog(#"%#", [userNames1 valueForKey:#"key2"]);
I have an NSMutableArray called myMutbaleArray that looks like this when I log it
2015-12-08 17:04:21.679 APP[3342:573379] (
{
id = 19;
"num_test" = 100000;
url = "http://fsad.com";
},
{
id = 20;
"num_test" = 100001;
url = "http://teeeet.com";
}
)
And I want to add an object that looks like this
{
id = 21;
"num" = 100002;
url = "http://example.com";
}
So I am trying this
[myMutbaleArray addObject:#{ #"id":#"23",#"num_test":#"100000", #"url":mainDict[#"website_url"],#"website_name":#"website"}];
But when I do this I get
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'
I initialize the array like this
#interface {
NSMutableArray *socailArray;
}
//inside connectionDidFinishLoading
socailArray = [dataDict valueForKey:#"socail"];
Why can I add another dictionary to the MutableArray?
Thanks
If you see this, your array is actually not a mutable array. Here is the hint:
-[__NSCFArray insertObject:atIndex:]
^^^^^^^^^^^
The object is of type __NSCFArray, which is an internal counterpart of NSArray.
Even if you declare your variable as NSMutableArray the pointer can point to an object of any type (event for example NSRegularExpression). Important is, how it is created.
This happens to most people if they serialise an array either using NSUserDefaults, NSJSONSerialization or what ever.
The key is to create a mutable copy when the array gets deserialised using
-[NSArray mutableCopy]
Note that this is not deep-copy. This means an array contained in the root array will not be mutable copied and needs to be replaced separately.
Deep copying can be achieved using this:
// array
NSArray *originalArray = #[#"a", #"b", #[#1, #2]];
NSMutableArray *mutableArray = (NSMutableArray *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFArrayRef)originalArray, kCFPropertyListMutableContainers);
// dictionary
NSDictionary *originalDictionary = #{#"a": #"b", #"c": #[#{#"abc": #123}]};
NSMutableDictionary *mutableDictionary = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)originalDictionary, kCFPropertyListMutableContainers);
You should change init to:
//inside connectionDidFinishLoading
socailArray = [NSMutableArray arrayWithArray:[dataDict valueForKey:#"socail"]];
Because: [dataDict valueForKey:#"socail"] is a NSArray.
With socailArray = [dataDict valueForKey:#"socail"];, the type of [dataDict valueForKey:#"socail"] is NSArray, so it auto cast socailArray into NSArray, that's why you can not insert thing into this.
To avoid this, you must be hold socailArray as NSMutableArray using:
socailArray = [[dataDict valueForKey:#"socail"] mutableCopy];
Hope this could help.
I am getting this error:
'-[ProductionCellData objectForKey:]: unrecognized selector sent to instance 0x14dca5d0'
on this line of code:
NSString *productionItem = [[myArray objectAtIndex:keyCounter] objectForKey:#"baseLineStart"];
keyCounter is equal to 0 and here is what myArray looks like
I am trying to get the value of baseLineStart but I keep getting the error above....how do I fix this?
objectForKey is normally used in dictionaries.
If you want to access the property, just refer to it:
NSString *productionItem = [myArray objectAtIndex:keyCounter].baseLineStart;
Or with even more modern syntax:
NSString *productionItem = myArray[keyCounter].baseLineStart;
The fact is that ProductionCellData does note responds to this selector, you should use
- (nullable id)valueForKey:(NSString *)key;
or get property from object in this way (if it is public )
NSString *productionItem = [[myArray objectAtIndex:keyCounter] baseLineStart];
Try to find error by the following way.
NSDictionary *dic = [myArray objectAtIndex:keyCounter];
NSLog(#"dic:%#",dic);
NSString *productionItem = [dic objectForKey:#"baseLineStart"];
//1. observe the dic object has "baseLineStart" key. if not found write the correct one.
//2. objeserve what type of value returns "[myArray objectAtIndex:keyCounter]". it may not NSDictionary which may resoan of crash
I am working with the following function atm, but I'm banging my head against a wall.
-(double)fetchTimeUntilNextUpdateInSeconds{
NSFetchRequest *fetchReq = [[NSFetchRequest alloc]initWithEntityName:#"DataInfo"];
fetchReq.predicate = [NSPredicate predicateWithFormat:#"data_info_id == 1"];
[fetchReq setPropertiesToFetch:[NSArray arrayWithObject:#"nextupdate"]];
NSArray *array = [self.context executeFetchRequest:fetchReq error:nil];
NSString *string = [[array valueForKey:#"nextupdate"] stringValue];
NSLog(#"string: %# array count:%lu", string, (unsigned long)array.count);
NSArray *hoursAndMins = [string componentsSeparatedByString:#":"];
int hours = [hoursAndMins[0] intValue];
int mins = [hoursAndMins[1] intValue];
return (mins*60)+(hours*60*60);
}
LOG: string: (
"05:42"
) array count:1
I'm getting following error: -[__NSArrayI componentsSeparatedByString:]: unrecognized selector sent to instance 0x174224060'
fair enough, i try to invoke "stringValue" method on string (as showed in code snippet) and get the following instead:
-[__NSArrayI stringValue:]: unrecognized selector sent to instance 0x174224060'
The ladder makes me think I'm already receiving a string as stringValue is not a method of that class.... but why won't the first work then. Better yet, what am I doing wrong here?
I guess, executeFetchRequest returns an array containing always one item.
The mistake is the method valueForKey which is ambiguous. It's a key value coding method as well as a method of NSManagedObject. If you want to get the value of a key of one object, so first get the first object from the array and then call valueForKey.
NSArray *array = [self.context executeFetchRequest:fetchReq error:nil];
// get the value of the key `nextUpdate` of the first item of the array
NSString *string = [array[0] valueForKey:#"nextupdate"];
To make clear what's happening when valueForKey is sent to an array, see this code, it returns an array of the values for the key id of all members of the array.
NSArray *array = #[#{#"name" : #"John", #"id" : #"1"}, #{#"name" : #"Jane", #"id" : #"2"}];
NSLog(#"%#", [array valueForKey:#"id"]); // --> #[#"1", #"2"]
Uhh, could also be the case that ( "05:42" ) has quotation marks that you may need to escape before you write this as a string to an array. OR you just maybe need to typecast the value of string AGAIN, but instead of doing that, why not try this first and tell us what happens.
NSArray *hoursAndMins = [[[array valueForKey:#"nextupdate"] stringValue] componentsSeparatedByString:#":"];
How can i retrieve the key value from the below NSMutableArray array. The below code crashes on isEqualToString. However i can see the value of nsRet in the variable view window as #\x18\xaa\x01\xc8\a before running that statement.
NSMutableArray* nsMyList = [[NSMutableArray alloc] init];
[nsMyList addObject:[NSDictionary dictionaryWithObjectsAndKeys:
#"valueOfKey", #"Key",
nil]];
NSString *nsRet = [nsMyList valueForKey:#"Key"];
if ([nsRet isEqualToString:#"deviceClass"])
{
NSLog(#"Key value:%#", nsRet);
}
Can anyone here please help me get the correct value for the key?
Thanks.
This is because you need objectForKey:, not valueForKey:. The valueForKey: method is for key-value programming. Moreover, the call should be on the [nsMyList objectAtIndex:0], like this:
NSString *nsRet = [[nsMyList objectAtIndex:0] objectForKey:#"Key"]
You've stored the NSDictionary in an array. The correct access based on your code would be:
NSDictionary *dict = [nsMyList objectAtIndex:0];
nsret = [dict valueForKey:#"Key"];
It looks like you are trying to get the valueForKey: on an NSMutableArray rather than on the dictionary.
What you want is:
[[nsMyList objectAtIndex:0] valueForKey:#"Key"];
I am a bit lost.
In order to access the dictionary you just create you need to obtain the first element in the NSMutableArray and then the dictionary.
It will be something like this:
NSString *nsRet = [nsMyList[0] objectForKey:#"Key"]
I think it can solve it.