I have a UIWebView in which I set content offset at some point:
myWebView.scrollView.contentOffset = CGPointZero;
It turns out afterwards that this view is scrolled to the bottom of its content. How can I figure out which part of code sets that offset? I miss data breakpoints and watchpoints on it. But how can i do it in actual Xcode?
In Xcode 4.5, in the locals window, you can turn out objects to see the member ivars, right-click/control-click on the ivar of interest and hit "Watch " and anything that modifies that ivar in that object will stop execution. Alternatively, you can add a watchpoint from the debugger console like this,
(lldb) watch set variable myWebView.scrollView.contentOffset
or
(lldb) w s v myWebView.scrollView.contentOffset
(shortest unique command name is always valid in command line lldb)
Related
I'm facing big issues when trying to print out Objective C properties in many situations when I'm almost certainly sure it SHOULD work.
Consider the following setup:
The view controller's property has strictly set class (Card *), but still, LLDB outputs an parsing error where subproperty cannot be found on object of type id.
Having an object property defined on a view controller (see points 5 & 6):
stop at breakpoint inside the controller code (f.e. in -viewDidAppear: method)
try to print out the property itself with po _card (points 1 & 2)
try to print out its subproperty with po _card.offlineURL (points 3 & 4)
an LLDB parsing error occurs
Printing out via [_card offlineURL] prints out proper object description as LLDB sends a message to Card object with no class check.
Definition of object property on the controller declares non-id class, though (point 5).
I'm expecting LLDB to print out the property object's subproperty description, NSString containing URL string in this case, but this annoying LLDB error occurs instead.
This is just a single example from many. Sometimes it affects direct property printout, numbers printing etc. These issues are way more frequent since integration of Swift began, being worse with every new version of Xcode since 6.2, including the latest 7.2.
This happens in my Objective C project in many situations, though sometimes it works fine in different cases.
Do you know about any work-arounds or fixes for this issue? I've already filed a report on Apple Bug Reporter, but this will certainly take time for Apple to even notice.
The most likely problem given the info in your question is that we don't actually have debug information for _card.
The lldb command:
(lldb) image lookup -t Card
will tell you whether lldb had debug information for Card available to it. If this doesn't find anything, then maybe some part of your project isn't getting built with debug info. If the command does find some correct definition of Card, then it must be that the debug info for the _card ivar is not getting hooked up to this type correctly.
If there is a definition of Card, then the workaround:
(lldb) po ((Card *) _card).offLineURL
is available.
For future reference, there are two other bits of behavior that are probably complicating your attempt to figure out what is going on here:
1) (w.r.t. picture 3) The Xcode IDE uses its built-in indexer for auto completion in the debug window as well as the Source Code editor. But the debugger runs off debug information, since we need to be able to debug things that aren't built in Xcode. So the fact that auto-completion can find a name in an expression doesn't tell you anything about what lldb will do.
2) (w.r.t. picture 2) po force-casts the expression you are trying to "po" to an ObjC object (i.e. "id") and then calls its description method. The description method of an ObjC object that doesn't override description prints the type name and the address. So lldb didn't need to know the type of the _card ivar to get the output you saw. We only start to need types when the expression is more complex and involves accesses to ivars or properties of an ObjC object in the expression.
Note also, by default if you do:
(lldb) print _card
lldb will evaluate the expression "_card", find it resolves to a pointer of at least type id, then follow that pointer's isa pointer into the ObjC runtime to figure out what the dynamic type is. So it is likely to print Card * in this case.
But the expression parser hasn't yet been taught to resolve the dynamic type of sub-expressions within the expression parser in mid-parse. That would actually be quite a trick... So if it doesn't know the full type of _card, then:
(lldb) print _card.offlineURL
isn't going to work, since id does indeed not have a property of that name.
You can work around this by doing:
(lldb) print _card
$0 = (Card *) 0x12345678
Then:
(lldb) print $0.offlineURL
since the result variable captures the full dynamic type information, that will also be available in subsequent expressions.
I've got something like this:
NSArray* titleColors = #[defaultColorForTitles, defaultColorForTitles, defaultColorForTitles]];
If I NSLog it out, I get:
2015-02-09 15:26:21.984 project[27352:1574376] (
6c6c6c,
red,
blue
)
Yay!
But if I set a breakpoint at the next line and hover over the variable, instead of seeing the array values (like I'd expect), it shows nil. Is this expected? Is my Xcode broken? What's going on?
Are you running a debug build? When hit your break point, does NSLog print out the value? If it does print out, but your inspector shows nil. It can be you are running a released build and compiler made an optimization there (mostly because that line is the last use of titleColors). That's my guess based on current information.
I am trying to debug my iOS app using lldb and I'm getting really weird errors on debug.
A few lines before my breakpoint, I've got:
CGRect frame = view.frame;
Which I can access with no problems with print frame command in lldb. However, when I try to access the frame again in lldb, I type print view.frame and get the following error:
error: property 'frame' not found on object of type 'UIView *'
This doesn't make sense as I can verify the view is a UIView* instance and has a valid property called frame by typing po view and getting correct results:
(UIView *) $4 = 0x1e199bf0 <MyAppCustomView: 0x1e199bf0; frame = (3398 3396; 204 208); layer = <CALayer: 0x1e199ce0>>
This particular lldb error happens to me a lot, and I couldn't find the cause of this error. Someone suggested at Property 'count' not found on object of type 'NSMutableArray *' PO command in lldb that one could use gdb as (gdb) p view.frame but I'm getting error: '(gdb)' is not a valid command. and I highly suspect that a gdb command would "work?" inside another debugger anyway.
Any suggestions or workarounds for this bug which occurs randomly?
Dot notation for message sending is not supported in lldb when using Objective-C. Use bracket notation and cast the result to CGRect:
p (CGRect)[view frame]
Just in case the above doesn't work (which it didn't for me, looking for the frame for a variable cell, class derived from UITableViewCell): forcing the extra parentheses seemed to help lldb's little ditty brain:
p ((CGRect)[cell frame])
presto magico:
(CGRect) $5 = origin=(x=0, y=0) size=(width=320, height=44)
I had to disable (uncheck) Thread Sanitizer in Xcode > Product > Scheme > Edit Scheme > Run > Diagnostics. With Thread Sanitizer enabled I wasn't able to access many NSView properties (e.g. bounds, frame) through LLDB.
How could I view the value of [fetchedResultsController sectionIndexTitles] in the debugger without change the code?
return [fetchedResultsController sectionIndexTitles];
Currently, I use to trick of add an tempory variable s and then use "print the descriptions of 's'" command. But this method requires me change the code so it is not convenient.
NSArray *s= [fetchedResultsController sectionIndexTitles];
return s;
Similar, it would be very helpful to be able to see the value of [a method1] in following statement:
[b [a method1]]
Do use breakpoints ... Add breakpoint to your return line, right click on breakpoint, edit breakpoint and now you have two options ...
Add Action Debugger Command ...
expr (void)NSLog( #"%#", [fetchedResultsController sectionIndexTitles] );
... or Log Message Action in a similar way and turn on Automatically continue after evaluating.
What it does?
Every time you hit your line with breakpoint, your application is paused, breakpoint actions are processed and as you did turn on Automatically continue after evaluating, your program continues when these breakpoint actions are processed. This is the way how to log, inspect, ..., without modifying your code.
I found the trick:
After the breakpoint is hit, Simply type following command in the LLDB would do the job:
po [self.fetchedResultsController sectionIndexTitles]
Where po is an abbreviation for expression -o -- used to print the object description of the value resulting from the expression.
The return value is visible in Xcode debugger, immediately after returning from a function call (i.e. immediately after hitting the the "step out" button). See below screenshot for example:
I've tried creating a breakpoint within a class definition, stopping on the message sent to an object instance, hoping it would then jump to the class code and allow me to walk through line by line and see the values of the local variables.
However, I'm going to venture out and say "no, this should not be possible", as there could be multiple instances of the class in memory. If someone could give a better explanation, that would be grand.
(As a side note, my alternative is excessive NSLogging of the runtime data.)
Yes, it is possible! You can add a condition to a breakpoint:
http://d.pr/yZVB+
http://d.pr/pWOB+
The program will only pause at this breakpoint when the condition is satisfied. You could choose a condition such as self == _myGlobalInstanceOfInterest.
If you don't want to store the instance in a variable, you might, for example, start the breakpoint without a condition — and then when you figure out which instance you want as the program is running, use p myObject to get the address, and then just set the condition to use the that address (such as self == 0x8badf00d).
I take it you want to break upon a message being sent to a particular instance?
Read the Xcode documentation on breakpoints and watchpoints. Basically, you can set a condition on a breakpoint so that it will automatically continue if self isn't the instance you're interested in.
Assuming you're talking about something like this:
- (void)eatAPieceOfFruit: (NSFruit *)fruit {
NSString * fruitType = [fruit species];
BOOL hasSeeds = [fruit hasSeeds];
NSInteger deliciousnessRating = [self enjoymentOfFruitType: fruitType];
NSString * reactionToEating = [self phraseForFruitType: fruitType];
// Breakpoint set here
}
The debugger has access to and knows the name of any variable that's in scope -- any variable that you would be able to use in the actual code at the line where you broke, you can also get to via the debugger. So, at the debugger prompt, type:
po reactionToEating
(that's "po" for "print object"), or the name of any other local variable to see what it is. If you want to call a method on an object that's in scope you can do so:
print (int)[reactionToEating length]
po [reactionToEating capitalizedString]