Which is the quickest way to view the value of a NSCFString variable in debugger window?
As for NSString, the string value is automatically displayed in the window or you move your mouse over it. But for a NSCFString, I tried same but cannot find the internal string.
When the program stops in your breakpoint, did you try typing the following into xcode's output console
po myNSCFString
being myNSCFString your NSCFString variable.
Related
With ARC turned off:
I create an instance of my custom class using alloc, so it has retain count of 1.
On the next line, I NSLog() the instance (I implemented a description method in my custom class).
On the next line, I release the object.
On the next line, I NSLog() the instance again, i.e. I send it a description message, and I see the same output in the console. I expected some kind of error output.
Here is the relevant code:
AppDelegate.m:
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
Greeter* host = [[Greeter alloc] initWithName:#"Maggie"]; //My custom class
NSLog(#"Greeter %#", host);
[host release];
NSLog(#"Greeter %#", host); //Create error: send a `description` message to an object whose retain count is 0.
return YES;
}
...
...
Greeter.m:
...
- (NSString*)description {
return [
[[NSString alloc] initWithFormat:#"\n\tname: %# \n\tCreated on %#", [self name], [self today]]
autorelease
];
}
--output in Console:--
2015-04-26 21:18:58.914 Flashlight[2380:62826] Greeter
name: Maggie
Created on 2015-04-27 03:18:58 +0000
2015-04-26 21:18:58.915 Flashlight[2380:62826] Greeter
name: Maggie
Created on 2015-04-27 03:18:58 +0000
Similar code in cocoa, causes weird stuff to happen, and Xcode flags the second NSLog() with EXC_BAD_ACCESS.
Response to comments:
I decided to start a new app to try some things, and here is what I discovered:
In Xcode 6.2, even though there is no error in the console, i.e. both NSLog()'s print the same thing, Product>Analyze will point out the line with the error saying: Reference-counted object is used after it is released. And if I click on that message, Xcode shows a nice graphical explanation of how that happened in the code.
If I edit the scheme to enable Zombie objects, then instead of the second NSLog() message, I get an error message:
Flashlight3[606:11093] *** -[Greeter respondsToSelector:]: message
sent to deallocated instance 0x7fb5e1caa8c0
After poking around in Xcode for much too long, I figured out how to edit the scheme. To the right of the Run and Stop buttons, there is a jump bar showing: ProjectName>Platform, which in my case is Flashlight>iPhone6. I clicked on Flashlight, and a drop down list displayed Edit scheme. I clicked on Edit scheme, then under Run/Debug, there is a checkbox for Enable Zombie Objects, which I checked.
Did you compile with debug symbols?
I guess not. I read some Apple docs to figure out how to do that: I clicked on the top line in the Project Navigator, chose Build Settings, then I scrolled down to Build Options, then I selected Build Variants, then I clicked the arrow to reveal Debug and Release. To the right of Debug, I clicked on normal, and I typed in debug.
I'm not sure what that does. I see no difference after doing that.
Do you find your code in the stack trace?
In the Stack Trace area:
Product>Profile
Scroll down the window and choose Zombies.
Then click the red Record button.
A Zombie Messaged popup will appear.
Inside the popup, click the arrow with the gray circle around it.
In the bottom pane, click on the Zombie line.
In the bottom right pane, at the top of pane, select the icon on the far right.
...there are a bunch of names in a list preceded by an icon:
Some of the icons are black. If I click on enough of the black icons, I eventually jump to my code. Doing that is problematic, though, because when I click on one of the black icons, it is hard to get back to the Stack Trace list to try another black icon. Edit: Okay, I found a way to get around that problem: when I click on one of the icons in the Stack Trace pane, it takes me to some code where one of the lines will have a red arrow pointing at it. If I click on the red arrow, it will show me a popup containing the Stack Trace list, and then I can click on one of the other black icons.
Just because an object's retain count goes to 0 and its dealloc method is called, doesn't mean the memory used by the object is instantly turned to garbage. The deallocated object could possibly sit in memory, intact, for a while before the memory space is reused for something else.
That seems to be the case here. The call to log host after it's been deallocated finds that the memory for the deallocated object is still intact so accessing its data works.
But it seems in your test on a Mac results in the memory being handled differently causing the exception.
rmaddy's answer is completely correct. But likely you want to know, how to get an error message in such a case.
There are two options:
Run the static analyzer. It can detect some of these errors.
Enable the zombie option in the scheme. This will keep the instance objects alive and report an error message, if they are used.
So I'm new to objective c, practically new to programming in general.
Anyway, in my simple program, I control-dragged my UITextField from the storyboard into my ViewController.m thinking it was a way to create a method to be invoked when the field was entered/tapped on. It wasn't long until I deleted the method.
When running the simulator, the keyboard would come up and the text field would already be focused on. If I tapped anywhere else on the screen, it resulted in a crash giving me the unrecognized selector error for the selector I already deleted.
There's nothing in my ViewController.h and the rest of the code seems fine. If I re-add the selector with no instructions, it behaves as intended and the keyboard resigns. My question is, why am I getting this error?
It would be more helpful to have the output of the crash. With that said I suspect your storyboard still has an outlet hooked up, referencing the function or outlet you created. From your storyboard click on your textfield and then navigate to the connections inspector (view -> utilities -> connections inspector). From there you should be able to see any connections you have made. Click the x to get rid of it.
The connection inspector is the icon in the upper right with the right facing arrow inside of a circle.
Edit:
I realized you asked why this is happening and not how to fix it. Unrecognized selector means just what it sounds like. Your code, in this case the storyboard is trying to call a method or access a variable on an object that doesn't implement that method. Normally the compiler catches these types of errors in your code but there are cases it can't catch, like the one your experiencing. For example it is ok to assign an NSArray object to a variable declared as something else, say an NSString as follows
id object = #[#"hello", #"world"];
NSString *notAString = object;
[notAString length];
Try running this and it will crash with a similar error because NSArray implement the length method, or in Objective-c speak, it doesn't respond to the selector "length".
Most typically it's this:
Select your UITextField in IB, go to the Connections inspector and remove the ghost connection to the removed method.
I'm getting an EXC_BAD_ACCESS with my iPhone app on 0x01ad809b <+0015> mov 0x8(%edx),%edi
I have NSZombieEnabled set to YES but I'm not seeing any class printed out in the debugger like I normally do.
Is there another way to debug this problem?
You have a crash caused, most likely, by corruption of memory, using a variable that isn't initialized, and/or casting a non-object type to an object.
First, post the backtrace of the crash. That will provide more context.
Second, try Build and Analyze. Fix any of the problems that it identifies.
Finally, if this is a new crash, go back to a revision right before the crash and then roll forward until you hit the crash. What are the changes made over that span of time?
With more context -- the crash log, in particular (or backtrace, at the least) -- more specific debugging techniques can be offered.
You can select Breakpoint navigator and add breakpoint on all exceptions. Maybe it will help.
Try with malloc info as well.
Use Instruments to Profile and detect zombies instead.
Change the build target to the Simulator
In the Build menu, select Profile
Instruments will open, then select the Zombies instrument
This automatically sets up the NSZombieEnabled flag and will popup a message whenever a dealloced object is messaged. Clicking the disclosure will show the memory management events of the object.
I understand that when you reach a breakpoint while debugging in Xcode you can hover the mouse pointer over objects and see their properties. But with most objects you only get a few of the properties. The rest are hidden. Trying this with a CLLocation object is next to useless.
Is there another way to peer inside this object while debugging?
Do I just have to resort to using NSLog to get what I want?
use the command: po VARNAME This will print out the value for you
As box pointed out, the gdb po command will print out whatever a varname points to. Xcode's debugger panel (the bottom pane in Xcode4) will also list out all objects in the current scope and allow you to view their ivars by clicking the disclosure buttons next to the objects. For Apple classes, though, this doesn't work so great, so I'd rely more on po, NSLog, and Apple's docs.
Create a -(NSString *)description method for whatever object you're trying to view.
At a breakpoint, right click on the variable in the local/global variable list (next to Console output) and click Print Description of "...". This will print out whatever details you want.
I am trying to find out how a UIViews transformation matrix is being modified. Thus (using the gdb console) I'd like to watch for any/all changes of the UIView's transform property. How would I go about doing so?
Add a symbolic breakpoint in Xcode. Use -[UIView setTransform:] as the Symbol.
Use a more narrow subclass class if you want less or more specific output.
Use a symbolic breakpoint -[UIView setTransform:]. Note that you can also use a condition with $arg1 (works only on 64bit simulator like iphone 5s) compared to some pointer to catch breakpoints on property change only for a specific instance $arg1 == 0x7f9cbba75e60. Screenshot below shows a breakpoint that catches changes on transform property only for UIView instance that has a pointer 0x7f9cbba75e60
If you're like me, and don't write in Obj-C, here's a quick Swift way to do it for beginners.
Just add a didSet to the property, and a breakpoint inside the block.