How can I see values of Object in NSLog? - iphone

Suppose I have an object containing some data.
How can I see that data using NSLog?
If anyone is not clear about my question, then can ask me again.

If you want to see an NSArray and NSDictionary and etc objects then you can directly print like NSLog(#"%#",object);
If it is an user defined object then you need to display by calling with property (attribute).
User defined object with name object and properties like
NSString *property1;
int property2;
NSMutableArray *property3;
Print them in the console as follows:
NSLog(#"%#, %d, %#" object.property1,object.property2,object.property3);

If you implement the -(NSString*)description method in your class then you can use NSLog to output a summary of the data. Of course, you can also directly output any property.
For example:
NSLog (#"%# %d", object, object.integer);
The first part calls the description method and outputs that; the second part gets the value of the integer property of object and outputs that.

Every Objective-c Object (this comes from NSObject) has a property called description. So if you want to print information about your class this is the way to go.
#implementation MyClass
- (NSString*)description
{
return [NSString stringWithFormat:#"MyClass:%#", #"This is my class"];
}
so if you do a call like this.
MyClass *myClass = [[MyClass alloc] init];
NSLog(#"%#", myClass);
NSLog(#"%#", [myClass description]); //Same as the line above
Then it will write "MyClass:This is my class" to the console (in this case it will print it twice).

Implement description of the given class.
-(NSString*)description {
return [NSString
stringWithFormat:#"<%#> name: `%#` size: `%#`",
NSStringFromClass(self), self.name,
NSStringFromCGSize(self.size)];
}
NSLog(#"%#", object); // <Object> name: `Harry` size: `{2, 2}`
extension Object: CustomStringConvertible {
var description: String {
"<\(Self.self)> name: `\(name)` size: `\(size)`"
}
}
print(object) // <Object> name: `Harry` size: `(2.0, 2.0)`

I would suggest these:
Objects:
For objects like Dictionary, Array, Strings do it like:
NSLog(#"%#", object);
For basic data-types like integers
NSLog(#"%i",intVal);
For type encoding you should see http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html

Use this class https://github.com/arundevma/ICHObjectPrinter
NSLog(#"Object description is %#",[ICHObjectPrinter descriptionForObject:person]);

NSLog(#"My object data:%#",[myObj someData]);
NSLog(#"My object Other data:%#",[myObj someOtherData]);
Or directly:
NSLog(#"%#",myObj);
NSLog(#"Description:%#",[myObj description]);

Additionally to Satya's answer, if you want to see basic c data types, use the format specifiers. Such as %d for an integer:
NSLog (#"My integer:%d", myObject.myInteger);
The complete list is here:
http://www.cplusplus.com/reference/clibrary/cstdio/printf/

Related

NSLog pointer syntax

I'm a little bit confused about the syntax of NSLog. For example,
NSString *nameString = #"Name";
NSLog(#"nameString is: %#", nameString);
If my understanding is correct (which it very well may not be), then nameString is defined to be a pointer to a String. I thought then that this would print the memory address that nameString holds, not the value of that address. So, if that is true, then in the NSLog statement, to get the value of the pointer, shouldn't we need to use the asterisk notation to access what nameString points to like this:
NSLog(#"nameString is: %#", *nameString);
?
It has been a little while since programming in C, but since Objective-C is a superset of C I thought they would behave similarly.
An explanation would be greatly appreciated! Thanks!
The command %# is like "shortcut" that calls the method -description on the receiver. For an NSString it simply display the string itself, since is inherited from NSObject you can override it, very usefull if you create for own class. In that case the default behaviur is print the value of the pointer. If you want to print the address of the pointer in the string just replace with :
NSLog(#"nameString is: %p", nameString)
I think that you use an asterisk only to declare a pointer. Then, you only use the name you decided. For example:
NSString *foo = [[NSString alloc] initWithString:#"Hello"];
NSLog(#"%#", foo);
Correct me if I am wrong :)
It's an object and NSLog is a function that uses its format specifiers to determine what to do with the argument. In this case the specifier is %# which tells NSLog to call a method on an object.
Normally this will call the method "description" which returns an NSString but it probably does respondsToMethod first and falls through to some other string methods.

Return type from valueForKeyPath:?

This is probably pilot error on my part, but I am a little confused why this does not return an int (as thats the type of the property identified by the key path). Does valueForKeyPath: return an object instead, can anyone explain.
// Simple Object
#interface Hopper : NSObject
#property(nonatomic, assign) int mass;
#end
// Test
Hopper *hopper = [[Hopper alloc] init];
[hopper setMass:67];
NSLog(#"HOPPER: %d", [hopper valueForKeyPath:#"mass"]);
.
WARNING: Conversion specifies type 'int' but the argument has type 'id'
Yes, it returns an objc object:
- (id)valueForKeyPath:(NSString *)keyPath;
Details for automatic conversions from non-objc objects to objc objects (e.g. NSNumber and NSValue) is covered in Accessor Search Patterns for Simple Attributes.
Therefore, you would use the objc object format specifier %#:
NSLog(#"HOPPER: %#", [hopper valueForKeyPath:#"mass"]);
valueForKeyPath returns an object. int and char types are not objects. Access the property via the . operator or similar.
NSLog(#"HOPPER: %d", [hopper mass]);
NSLog(#"HOPPER: %d", hopper.mass);
Edit: Didn't fully read example code, updated answer

NSUserDefaults: How to display user defaults when valueforKey is an ENUM

In iPhone app, How to display values in console for user defaults when valueforKey is an ENUM?
Currently with the below code if I try to display in console then it crashes with no crash log in console.
NSLog(#"%#",[[NSUserDefaults standardUserDefaults] valueForKey:Enum]);
To fetch:
int someValue = [[NSUserDefaults standardDefaults] integerForKey:#"your key here"];
to save:
[[NSUserDefaults standardDefaults] setInteger:10 forKey:#"your key here"];
EDIT: got it, you crash because in NSLog you are using the wrong format:
NSLog(#"%i",[[NSUserDefaults standardUserDefaults] valueForKey:Enum]);
try %i (to print integers) instead of %# (used to print valid objective-c objects)
Since an enum is really just a fancy way of displaying an int, all you have to do is create an enum variable and set it to the value you get from NSUserDefaults.
You may end up with something like:
PirateEnumType pirateType = [[NSUserDefaults standardUserDefaults] integerForKey:#"PirateType"];
EDIT:
I'm sorry. I guess I didn't fully understand your question. Since an enum is really an int, you will need to use "%i" to display it instead of "%#".
In order to show it properly as a human readable string, you would need to have some sort of enumToString function, perhaps like:
-(NSString*)enumToString:(PirateEnumType)enumValue {
NSString* returnValue = #"";
switch (enumValue) {
case Captain:
returnValue = #"Captain";
break;
case Swashbuckler:
returnValue = #"Swashbuckler";
break;
case PegLeg:
returnValue = #"PegLeg";
break;
}
return returnValue;
}
NSUserDefaults objects are really just NSDictionary objects. NSDictionary only takes an object as a key. Enum is just an integer, so you can't use it as a key directly. One way to do it, though is to use NSNumber, which can represent an integer as an object like the following:
[[NSUserDefaults standardDefults] valueForKey:[NSNumber numberWithInt:yourEnum];
To set the value you would do:
[[NSUserDefaults standardDefaults] setValue:yourValue forKey:[NSNumber numberWithInt:yourEnum]];
There are two issues here. Firstly, an enum cannot be a key in valueForKey. valueForKey can only accept strings, not string values of enums. Therefore, you need to implement a method to get a string value from an enum. In my example below that method is stringFromEnum. Here is one example of how to get a string from an enum.
Sometimes I've seen NSLog choke when I ask it to directly include the return value of a message sent to an object. I've always found that assign the result of that message to an instance variable first and then passing the value of that instance variable into NSLog instead solved the problem, but admit I haven't figured out what the relevant factors are that determine when it does or does not work the original way. Interested in any comments.
NSString *myKey = [self stringFromEnum:Enum];
NSString *myStringToLog = [[NSUserDefaults standardUserDefaults] valueForKey:myKey];
NSLog(#"%#", myStringToLog);
Another reading of your question could be that your instance variable Enum is actually a string, which is the Key for an enum that will be returned from NSUserDefaults. However, that can't be the case, as NSUserDefaults will not store an enum. See the documentation for object types that are supported. If that's what you're trying to do, your problem may be partly in other code where you're trying to store the enum in the first place?

method with many parameters

i have a method with 20 parameters,( NSString, float,....), can i construct a type ( for example Enumerated, typdef) to invoque my method and not pass all my parameters ?
replace:
-(void)myMethodeParam1:...:param2:.... ;
with:
-(void)myMethode:MyNewTypeParam ;
tanks for your answers
You can use NSDictionary (NSMutableDictionary). You'll need to wrap primitive type (like float) to obj-c objects (e.g. NSNumber) for that though.
E.g. you have 10 NSString params named param0,...,param9 then you can place them in NSDictionary:
NSDictionary *paramDict = [NSDictionary dictionaryWithObjectsAndKeys:string0, #"param0", string1, #"param1", ..., string9, #"param9", nil];
[obj myMethod: paramDict];
or if you can enumerate your variables somehow you can use NSMutableDictionary and add them to it in a loop.
Then in your method you can get your parameters from dictionary you have:
-(void)myMethode: (NSDictionary*)dict{
NSString *string0 = [dict objectForKey:#"param0];
//Do something with it
...
}
If your parameters together are some logical entity and they're usually used together you also can also create a custom class that contains them as instance variables

Objective C: Compare Array Element to String

Greetings,
I'm trying to simply compare a NSString to an NSArray.
Here is my code:
NSString *username=uname.text;
NSString *regex=#"^[a-zA-Z0-9-_.]{3,20}$";
NSArray *matchArray=nil;
matchArray=[username componentsMatchedByRegex:regex];
if(matchArray[0] == "asdf"){ //this line causes the problem!
NSLog(#"matchArray %#",matchArray);
}
I get an "invalid operands to binary ==" error.
How can I compare the string?
Many thanks in advance,
You are trying to compare an NSString to a C string (char *), which is wrong. matchArray is an NSArray so you cannot treat it as a C array either, you have to use its objectAtIndex: method and pass in the index.
Use this instead:
if ([[matchArray objectAtIndex:0] isEqualToString:#"asdf"]) {
NSLog(#"matchArray %#", matchArray);
}
Addressing your comments, the reason why isEqualToString: does not show up in autocomplete is because Xcode cannot guess that matchArray contains NSStrings (it only knows it contains ids, that is, arbitrary Objective-C objects). If you really wanted to be sure, you can perform an explicit cast, but it doesn't matter if you don't:
if ([(NSString *)[matchArray objectAtIndex:0] isEqualToString:#"asdf"]) {
NSLog(#"matchArray %#", matchArray);
}
you want to use -objectAtIndex to get the array element. NOT the C array accessor syntax
try to use:
[[matchArray objectAtIndex:0] isEqualToString:#"asdf"];
anyway the string "asdf" should be #"asdf"