XCode - Printing Live Values of objects - objective-c

Hi I am debugging and need to be able to check what the values of my properties within my objects are. They are strings... but I dont see the actual string itself.
I just get this here:
some advice would be nice...
thanks

Add below method to TrackVO class
- (NSString *)description{
return #"put together your instance property values and send out";
}
Note:
You are overriding the method that is inherited from NSObject.
%# and xCode-variable-view will implicitly call this description method.

The debugger sometimes messes up the contents of variables. Try logging your strings.
NSLog(#"String value: %#", myString);

Related

How to properly use makeObjectsPerformSelector: Getting error unrecognized selector

Let me start off by saying I am new to Objective C.
I am getting the error
atusMenuApp[24288:303] -[__NSCFConstantString createListItem]: unrecognized selector sent to instance 0x100002450
Here is my code:
selector = [NSMutableArray arrayWithObjects: #"nvda", #"aapl", #"goog", nil];
[selector makeObjectsPerformSelector:#selector(createListItem:) withObject:self];
- (void)createListItem:(NSString *)title {
//do some stuff
}
Now I have done plenty of looking around and it seems like the biggest reason for this issue is the addition of or lack of the :however I do believe I properly have that in place. Maybe I do not understand the use of makeObjectsPerformSelector very well as after look up the doc on it I found:
Sends to each object in the array the message identified by a given selector, starting with the first object and continuing through the array to the last object.
Any help would be great, Thanks!
[Only if you read the documentation (or thought a bit about why a method is named this way and not that), or even made the effort trying to understand the error message...]
The makeObjectsPerformSelector:withObject: method of NSArray does what it suggests it does: it makes the objects of the array perform the selector, that can have an optional argument. So
[selector makeObjectsPerformSelector:#selector(createListItem:) withObject:self];
will send the createListItem: message to every single NSString object in the selector array and pass in self as its argument. It won't perform the selector on self passing in the object. I. e., what you have is equivalent to
for (NSString *obj in selector) {
[obj createListItem:self];
}
Obviously, instead of this, you want the following:
for (NSString *obj in selector) {
[self createListItem:obj];
}
You don't even need that nasty method for this. A nice fast enumeration for loop will do it.
First you make an array of NSStrings. Then, you send them all the message createListItem. That's all fine and dandy, but NSString doesn't have any method called createListItem; just because you've defined an instance method called createListItem doesn't mean every instance of every class can use it. Only the class who's implementation file has the definition will be able to handle the message. For instance, I can't make a list of Car instances, then define the method fly in another class called Helicopter's implementation and expect to be able to call fly on an instance of Car; only Helicopter can use it. I recommend you read a good book on Objective-C and further familiarize yourself with classes, instances and instance methods.
You misunderstood the method.
It will call the method createListItem: with argument self over every object of the NSArray.
So the resulting call would be something like:
[#"nvda" createListItem:self];
...
Clearly that method doesn't exist for a NSString and there goes your exception.
If you need to apply a method of self to every object inside your array, simply loop through it.

Objective C How to check and see if object was chosen?

I am trying to write an if statement that checks an array of objects to see if a certain object exists (in this case the word, "NBC" in my array, "channel"). I'm new to this and I'm not sure how to do it in objective c. Please take a look at my code below:
if ([[self.channel objectAtIndex:path.row] containsObject: #"NBC"])
{
//Arguments
}
After I run it with this, the simulator crashes and gives this error: 2013-01-02 17:11:44.778 Master Detail Practice App[50056:207] -[__NSCFConstantString containsObject:]: unrecognized selector sent to instance 0xc698
I know my syntax or logic is probably off. Any help will be appreciated. Thank You!
[self.channel objectAtIndex:path.row] is returning you an NSString object. You're then trying to send that NSString instance a containsObject: message, which it doesn't know what to do with. Maybe you meant:
[self.channel objectAtIndex:path.row] isEqualToString:#"NBC"]
or
[self.channel containsObject:#"NBC"]
But without more context, it's hard to say.
It appears you are pulling out the String from an array rather than checking the array for the String. Try rewriting your code like this:
if ([self.channel containsObject: #"NBC"]) {
//Arguments
}

Issue with NSLog when printing BOOL type

(XCode 4.3)
Why does the following crash at the NSLog statement with EXC_BAD_ACCESS?
BOOL autoFlag
#property BOOL autoFlag
#synthesize autoFlag
[object setAutoFlag:YES]
NSLog(#"%#", [object autoFlag]); //crashes here in debugger with EXC_BAD_ACCESS
I managed to get around it with NSLog(#"%d"..., which prints 1, but why doesn't #"%#" work? I thought it just converts the value to a string?
%# is used to print the description of objects that are descendants of the NSObject class, this however can be overwritten to make your objects print whatever you want.
Unless autoFlag is an object it will crash your program. It is very common to get these type of errors in NSLog Statements since the compiler cant tell what kind of "thing" you want to print and most of the time it wont be able to know before hand (there are some exceptions in where it will tell you that you are using the wrong identifier).
If what you want to see is something like "True" or "YES" then you need something like
NSLog(#"Auto Flag: %#",object.autoFlag? #"True":#"False");
Take a look at: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html
%d works because you are telling it to print your boolean value as an integer, so you will get back either 0 (false) or 1 (true) using this method. There is no specific formatter for a boolean.
You encountered a crash because the code is expecting a pointer to a memory address by using %#, and instead you gave it a primitive datatype, in this case a boolean. When the application tried to use this address and there was no object there, you got a EXEC_BAD_ACCESS.

Objective-C - NSLog - "%#" Referencing Character

I'm working through a BNR iOS Programming text and I came across this piece of code:
NSLog(#"%#", [items objectAtIndex:i]);
I am unsure of what "%#" is used for. I've seen other formats for referencing integers or characters, but I've never seen this.
I even checked this reference here and it had nothing.
Thanks!
%# is for printing objective-c objects.
To be a bit more precise. Every object is able to override
-(NSString *)description
This method is called when you use %#. It depends on the object what info of the object it will return in the NSString.
According to Apple:
Objective-C object, printed as the string returned by descriptionWithLocale: if available, or description otherwise. Also works with CFTypeRef objects, returning the result of the CFCopyDescription function.
Reference:
String Format Specifiers
I am working through the same text - and coming from a Java background, the "%#" formatter seems equivalent to the "toString" method that Java would have.
It is used to display custom information about an object.
There is a good example in the response to this StackOverflow question about the "toString()" equivalent.

Arguments by reference in Objective-C

I'm trying to pass an NSString by reference but it doesn't work.
This is the function:
+(void)fileName:(NSString *) file
{
file = #"folder_b";
}
and this is the call:
NSString *file;
[function fileName:file];
nslog(#"%#",file); // and there is nothing in the string....
What I must do to pass my string by reference?
If you want to return a value, then return a value. Pass by reference in Cocoa/iOS is largely limited to NSError**.
Given:
+(void)fileName:(NSString *) file
Then do:
+(NSString *) fileName;
And be done with it.
If you need to return more than one value at a time, that begs for a structure or, more often, a class.
In Objective-C, pass by reference smells like you are doing it wrong.
Pass by reference in Objective-C is reserved largely for returning NSError* information about a recoverable failure, where the return value of the method itself indicates whether or not the requested task succeeded or failed (you can pass NULL as the NSError** argument to allow the method to optimize away creating said error metadata).
Pass by references is also used to retrieve interior state of objects where the return value is effectively a multi-value. I.e. methods from AppKit like the following. In these cases, the pass-by-reference arguments are typically either optional or are acting as secondary return values.
They are used quite sparingly across the API. There is certainly use for pass by reference, but -- as said above -- doing so should be quite rare and rarer still in application code. In many cases -- and in some of the cases below, potentially -- a better pattern would be to create a class that can encapsulate the state and then return an instance of said class instead of pass by reference.
NSWorkspace.h:- (BOOL)getInfoForFile:(NSString *)fullPath application:(NSString **)appName type:(NSString **)type;
NSTextView.h:- (void)smartInsertForString:(NSString *)pasteString replacingRange:(NSRange)charRangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString;
NSAttributedString.h:- (BOOL)readFromURL:(NSURL *)url options:(NSDictionary *)options documentAttributes:(NSDictionary **)dict;
NSNib.h:- (BOOL)instantiateWithOwner:(id)owner topLevelObjects:(NSArray **)topLevelObjects NS_AVAILABLE_MAC(10_8);
NSSpellChecker.h:- (NSRange)checkGrammarOfString:(NSString *)stringToCheck startingAt:(NSInteger)startingOffset language:(NSString *)language wrap:(BOOL)wrapFlag inSpellDocumentWithTag:(NSInteger)tag details:(NSArray **)details NS_AVAILABLE_MAC(10_5);
I believe you're looking for:
+ (void)fileName:(NSString **)file
{
*file = #"folder_b";
}
What's really done here is we're working with a pointer to a pointer to an object. Check C (yup, just plain C) guides for "pointer dereference" for further info.
(...But as has been pointed out repeatedly, in this particular example, there's no reason to pass by reference at all: just return a value.)
Passing a pointer to your object is the Objective C (and C) way of passing by reference.
I agree with 'bbum' that a perceived need to pass by reference is a signal to think about what you are doing; however, it is by no means the case that there are not legitimate reasons to pass by reference.
You should not create classes willy-nilly every time you have a function or method that needs to return more than one value. Consider why you are returning more than one value and if it makes sense to create a class for that then do so. Otherwise, just pass in pointers.
-Just my 2 cents
Try this
+(void)filename:(NSString **)file {
*file=#"folder_b";
}
and send the file as &file like:
NSString *file;
[function fileName:&file];
nslog(#"%#",file);
hope this will work.
I suspect this is because NSString is immutable. Have you tried NSMutableString?