Is there a way to view the key/value pairs of a NSDictionary variable through the Xcode debugger? Here's the extent of information when it is fully expanded in the variable window:
Variable Value Summary
jsonDict 0x45c540 4 key/value pairs
NSObject {...}
isa 0xa06e0720
I was expecting it to show me each element of the dictionary (similar to an array variable).
In the gdb window you can use po to inspect the object.
given:
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
[dict setObject:#"foo" forKey:#"bar"];
[dict setObject:#"fiz" forKey:#"buz"];
setting a breakpoint after the objects are added you can inspect what is in the dictionary
(gdb) po dict
{
bar = foo;
buz = fiz;
}
Of course these are NSString objects that print nicely. YMMV with other complex objects.
You can right-click any object (ObjC or Core Foundation) variable and select “Print Description to Console” (also in Run->Variables View). This prints the result the obejct’s -debugDescription method, which by default calls -description. Unfortunately, NSDictionary overrides this to produce a bunch of internal data the you generally don’t care about, so in this specific case craigb’s solution is better.
The displayed keys and values also use -description, so if you want useful information about your objects in collections and elsewhere, overriding -description is a must. I generally implement it along these lines, to match the format of the default NSObject implementation:
-(NSString *) description
{
return [NSString stringWithFormat:#"<%# %p>{foo: %#}", [self class], self, [self foo]];
}
You can use CFShow()
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
[dict setObject:#"foo" forKey:#"bar"];
[dict setObject:#"fiz" forKey:#"buz"];
CFShow(dict);
In output you will see
{
bar = foo;
buz = fiz;
}
XCode 4.6 has added the following functionality which may be helpful to you
The elements of NSArray and NSDictionary objects can now be inspected in the Xcode debugger
Now you can inspect these object types without having to print the entire object in the console. Enjoy!
Source: http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/WhatsNewXcode/Articles/xcode_4_6.html
Click on your dict, then click on the little "i" icon, it should do the job :-)
If you would like to print these in a breakpoint action in modern XCode (yes, I am 10 years after the original post!) use the following breakpoint expression in a "Log Message" action:
#myDictionary.description#
Below is a screenshot of my breakpoint action where the variable event is an NSString and the variable contextData is the NSDictionary that I am logging the contents of:
:
You can also use NSLog.
Also you can go in Debug area or xcode, then find out All Variables, Registers, Globals and Statics then select your variable. Right click on it. Then select Print description of "...."
Hope it helps!
Related
This question already has an answer here:
NSMutableDictionary setObject:forKey: fails to add key
(1 answer)
Closed 8 years ago.
I'm trying to do some complex stuff, but when I add to an nsmutabledictionary and try to get values from it, it's simply returning nothing and not printing anything when I try to print what it returns. I can't even get the following to print anything in an ibaction, even though the action is being triggered. Could you like me know if I'm doing anything wrong and what it is? Thanks!
Sample code of super simplified version of what I'm doing:
NSMutableDictionary *test;
[test setObject:#"ValueIWantToGet" forKey:#"KeyIAmSetting"];
NSLog([test objectForKey:#"KeyIAmSetting"]); //Should print "ValueIWantToGet", right?
Your test variable is not initialized. Do this instead:
NSMutableDictionary *test = [NSMutableDictionary dictionary];
or
NSMutableDictionary *test = [[NSMutableDictionary alloc] init];
In Objective-C all objects are manipulated through pointers. Hence the asterisks in declarations in front of variable names. When you do not assign anything to a pointer, its value remains uninitialized, so any reference to it is undefined behavior. In situations when the value happens to be nil, however, you would not see a crash, because Objective-C allows sending messages to nil (they have no effect).
I'm making a property of an NSMutableDictionary, so how should I initialized it if it's a property?
Properties should be initialized in the initializer of your class, for example
-(instancetype)init {
if (self = [super init]) {
_test = [NSMutableDictionary dictionary];
}
return self;
}
There is a literal syntax to add object and change object in an NSMutableDictionary, is there a literal syntax to remove object?
Yes, but... :-)
This is not supported by default, however the new syntax for setting dictionary elements uses the method setObject:forKeyedSubscript: rather than setObject:forKey:. So you can write a category which replaces the former and either sets or removes the element:
#implementation NSMutableDictionary (RemoveWithNil)
- (void) setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key
{
if (obj)
[self setObject:obj forKey:key];
else
[self removeObjectForKey:key];
}
#end
Add that to your application and then:
dict[aKey] = nil;
will remove an element.
No. There is not. I have tried to find proof link but did not succeed :)
As of iOS 9 and macOS 10.11, these two are equivalent:
[dictionary removeObjectForKey:#"key"];
dictionary[#"key"] = nil;
See the Foundation release notes (search for the heading NSMutableDictionary subscript syntax change).
I am write a Objective-C Code on XCode 4.4.
I have a NSMutableArray as a instance variable of my class k_info
I have defined and synthesized (nonatomic,retain) property by the name of onesplaces too.
I am unable to add a NSMUtableString object in the NSMutableArray onesplaces.
When I try to add it.The size of onesplaces remains 0 and object at zero index obviously remains null.
I tried doing this with and without using "self" key-word but it didnt worked in either case.
My syntax of adding object and printing it is right because when I create a new NSMutableArray test
and try to do the same thing it works for it but not for the instance variable onesplaces.
I cannot proceed any further in my project without solving this issue.please tell me why is it
happening and how should I solve this problem.
-(void)createinfo:(NSMutableArray )al varsis:(int)vars
{
NSMutableString stes=[[NSMutableString alloc]init];
stes=(NSMutableString*)#"string0";
[ onesplaces addObject:stes];
NSLog(#"%u",[onesplaces count]);
NSLog(#"value is: %# ",[ onesplaces objectAtIndex:0]);
[ self.onesplaces addObject:stes];
NSLog(#"%u",[onesplaces count]);
NSLog(#"value is: %# ",[self.onesplaces objectAtIndex:0]);
NSMutableArray* test=[[NSMutableArray alloc]init];
[ test addObject:stes];
NSLog(#"%u",[test count]);
NSLog(#"value is: %# ",[test objectAtIndex:0]);
}
You probably forgot to create the array. Somewhere in your code, maybe in your init method, you need to create the array before using it.
self.onesplaces = [[NSMutableArray alloc] init];
You get nil instead of error messages because Objective-C allows you to send messages to nil, which always return nil.
I'm loading a dictionary (list of word, not the class) into a NSSet as NSStrings. I then repeatedly send this set the message -containsObject:someNSString. But it always returns false. I wrote some code to test it:
NSLog(#"Random from dictionary: %#", [dictionary anyObject]);
NSString *test = [NSString stringWithFormat:#"BEMIRED"];
NSLog(#"To match this word: %#", test);
if ([dictionary containsObject:test])
NSLog(#"YES!");
In the log I get the following:
Random from dictionary: BEMIRED
To match this word: BEMIRED
(I'm missing the "YES!")
When I try using CFShow(dictionary) I can see that it actually contains Strings and that everything. An example:
0 : <CFString 0xc3bd810 [0x1386400]>{contents = "BEMIRED"}
3 : <CFString 0xdf96ef0 [0x1386400]>{contents = "SUBJECTIFIED"}
Can anyone please help me here?
Thanks!
NSSet uses isEqual: to test for object equality, which NSString overrides to perform a string comparison as you would expect. The follow unit test passes:
- (void)testSetStrings
{
NSSet *set = [NSSet setWithObject:#"String 1"];
// I've used the UTF8 initializer to avoid any cleverness from reusing objects
NSString *string1 = [[[NSString alloc] initWithUTF8String:"String 1"] autorelease];
// Test the references/pointers are not the same
STAssertTrue([set anyObject] != string1, nil);
STAssertTrue([set containsObject:string1], nil);
}
We can see the two strings have different pointer values, but the set still returns YES for the containsObject: call.
So I would guess your strings are not in fact equal. I would check for hidden whitespace or other similar issues.
The -[NSSet containsObject:] seems to check for the pointer value only (the documentation is very lacking for that method), not for object equality. So you need to use -[NSSet member:] instead, which uses isEqual: to check whether an object that is considered to be equal is in your set.
if ([dictionary member:test])
NSLog(#"YES!");
Edit: Actually it seems that containsObject: does use isEqual: as well. They only seem to differ in what they return (containsObject: returns a BOOL while member: returns id). I'm letting this answer stay for documentation purposes.
Ok so I solved the problem and it had nothing to do with the containsObject method. As I commented i used Dave DeLongs DDFileReader found here: Dave DeLongs DDFileReader
So by using CFShow on the entire dictionary I noticed that every word had a new line at the end of it. So instead of the -readLine method i used the -readTrimmedLine (bot methods in above mentioned file reader). This solved the problem for me.
For future forum visitors I'd like to draw attention to the discussion DarkDust and zoul had about -containsObject and -member (both methods of NSSet) which it turns out both uses the -isEqual method.
I'll use an example from JavaScript to help clarify my question. Let's assume I have the following object:
sports = {
soccer: {...},
basketball: {...},
baseball: {...}
}
If at some point in my script I have a variable, sportString, that simply holds a string, I can dynamically call one of the sports objects in the following way:
sports[sportString];
This frees me from having to use a bunch of nested if statements, testing the value of the string such as:
if(sportString === 'soccer'){
sports.soccer;
}else if(sportString === 'basketball){....
So, my question is how can I accomplish something similar to sports[sportString] in Objective-C, if sportString is an NSString object?
Use an NSDictionary as your sports object. Then you can do lookups like this:
[sports objectForKey: sportsString];
The people saying you should use NSDictionary for general key/value storage are 100 % right. However, I think it’s useful to know that you can call a message specified by a string:
SEL selector = NSSelectorFromString(#"foo"); // Or #selector(foo) if you know it at compile time
id value = [object performSelector:selector];
You can also use selectors with up to two arguments, as long as they take objects:
SEL selector2 = NSSelectorFromString(#"setFoo:");
[object performSelector:selector2 withObject:value];
It’s possible to invoke arbitrary methods using IMPs or casting objc_msgSend(), but now I’m getting way beyond the scope of your actual question. :-)
Your JavaScript object sports would typically be an NSDictionary or NSMutableDictionary.
Example:
NSMutableDictionary *sports = [NSMutableDictionary dictionary];
[sports setObject:#"Foo" forKey:#"soccer"];
[sports setObject:#"Bar" forKey:#"basketball"];
NSString *sportString = #"soccer";
NSString *sportValue = [sports objectForKey:sportString];
NSLog(#"%#", sportValue); //logs "Foo"