Xcode debugging: View value of NSNumber? - cocoa

Is it possible to see the numeric value of an NSNumber in the debugger datatip on in the variable watch window?
I store an Integer value in NSNumber and want to see this value during debugging.
I tried some of the data formatters in the debugger already, but it wasn't much help.

Open the Debugger view and in the Summary column enter
{(int)[$VAR intValue]}
or whatever interpretation is most appropriate for what you want to see in the Debugger.

Related

How can I determine what part of text in a scroll view is visible on screen from an Xcode UI test?

I'm new to the Xcode User Interface testing framework. I can successfully manipulate the screen elements, but cannot work out how to produce a meaningful assertion about what text is visible in a scrolling view.
The test I would like to write would go as follows: launch the app, type lots of text into a text view (enough that the first line scrolls out of view), assert that the first line of text is not visible, scroll the view back up to the top, then assert that the first line is now visible. Note that the purpose of this test is to ensure my app has wired things up correctly, not to test Apple's code.
XCUIApplication allows me to type into my NSTextView instance, and also allows me to scroll the associated NSScrollView. But how do I assert whether the first line of text is currently visible? The value attribute on XCUIElement provides the entire text content of the view, whether or not it is currently displayed.
The accessibilityRange(forLine:) and accessibilityString(for:) methods on NSTextView would be ideal, but I can't see how to access them as the UI test only has access to an XCUIElement, not the underlying NSTextView.
Have I missed something, or is there a better way to approach this?
If you set the accessibility identifier in the storyboard or in code for the text view you can get the text view via (assuming you gave it the id "textview1" and the window it's in has the default accessibility identifier of "Window"):
let textview1TextView = app.windows["Window"].textViews["textview1"]
but that won't actually get you what you need.
Instead, set the accessibility identifier of the scrollview and get that:
let scrollview = app.windows["Window"].scrollViews["scrollview1"]
Then use that to get the scrollbars (you should only have one in this case; you can use scrollbars.count to check.
let scrollbars = scrollview.scrollBars
print("scrollbars count: \(scrollbars.count)")
Then you can use the value attribute of the scrollbar to get it's value:
(you're converting a XCUIElemenTypeQueryProvider into an XCUIElement so you can get it's value):
let val = scrollbars.element.value
it will be 0 at the top and a floating point value when scrolled (one line of text in my test code showed a value of {{0.02409638554216868}}.
Documentation that will help you explore further:
XCUIElementTypeQueryProvider
XCUIElementAttributes
Note that you can put a breakpoint in the middle of your test, run it and then use the debugger console to examine things:
(lldb) po scrollbars.element.value
t = 749.66s Find the ScrollBar ▿ Optional<Any>
- some : 0
(lldb) po scrollbars.element.value
t = 758.17s Find the ScrollBar ▿ Optional<Any>
- some : 0.05421686746987952
and while in the debugger you can even interact with your app's window to scroll it manually (which is what I did between typing in those two po calls), or perhaps add text and so on.
OK OP now noted that they're interested in the specific text showing or not rather than the first line in view or not (which is what I previously answered above).
Here's a bit of a hack, but I think it'll work:
Use XCUICoordinate's click(forDuration:, thenDragTo:) method to select the first line of text (use the view frame to calculate coordinates) and then use the typeKey( modifierFlags:) to invoke the edit menu "copy" command. Then use NSPasteboard methods to get the pasteboard contents and check the text.
Here's a quick test I did to validate the approach (selecting the first line of text using XCUICoordinate as noted above is left as an exercise for the reader):
NSPasteboard.general.clearContents()
// stopped at break point on next line and I manually selected the text of the first line of text in my test app and then hit continue in the debugger
textview1TextView.typeKey("c", modifierFlags:.command)
print( NSPasteboard.general.pasteboardItems?.first?.string(forType: NSPasteboard.PasteboardType.string) ?? "none" );
-> "the text of the first line" was printed to the console.
Note that you can scroll the selection off screen so you have to not scroll after doing the select or you won't be getting the answer you want.

Xcode debugger displays NO for BOOL value that is 0x01

Argh, I hit a really weird problem.
I have a breakpoint set, and I'm trying to inspect a BOOL value. The summary in the locals section says clearly that it is NO. However, I'm pretty sure that the paramater passed in should have evaluated to YES.
So, I hovered my mouse over the variable in question and get the following screen, where the value is 0x01, and the summary says it is NO. (screen attached for your amusement).
What is going on here?
I have reported this bug to Apple and this is the work-around (solution) that works by me:
Right click on the variable in the Variables View and select "Edit
Summary Format…". Do you see the string "NO" in there? If so, delete
that.

understanding Xcode debugger var display

newbie question: can anyone tip me to how to understand/interpret what is displayed in the debugger var pane?
Ex: I am passing an NSDictionary as a method param. I set a breakpoint so I can examine the values in the dictionary. The image below (if it comes through..) shows the expanded view of this var in the debugger. It correctly reports that it contains 3 name/value pairs but as I expand all the sections, I simply can not find where these are stored.
Do I have to create local vars of these name/value pairs in order to view them when I want to check? I know I can use NSLog or printf but sometimes I just want a quick peek.
Right click the variable, click "Edit Summary Format" and type the following:
{(NSString*)[$VAR description]}:s
This replaces the GDB formatter for NSDictionary with a call to the more expensive description method.
That is, instead "x key/value pairs", you'll see the contents of the dictionary as produced by -[NSDictionary description].
This is the same as typing po dictionary in the console window. Or right clicking the variable and choosing "Print Description". Both of them call the description method of the object.
If you are curious, you can find this formatter at /Developer/Library/Xcode/CustomDataViews/Foundation.plist under the key NSDictionary. What you type as replacement is saved in /Users/USERNAME/Library/Developer/Xcode/UserData/Debugger/CustomDataFormatters and will persist across runs until you delete that file.
A NSDictionary is really a class cluster and few people know the inside structure. At this point you ain't going to find much use for that debugger tree.
This is what you are looking for :
Click on your dict, then click on the little "i" icon :-)

Xcode debugging - displaying images

I love using the Xcode debugger. You can take a look at a variable's value and even change it.
But can I somehow DISPLAY the image that is referenced by an image variable? I know I can see its raw bytes, but it would be much more human-friendly to display a window with its contents.
Xcode might not support this. Maybe there is an external tool that would help display images?
Use Quick Look to inspect images in the Xcode debugger.
Select an NSImage or UIImage in the debugger, then click the Quick Look "eye" icon.
Like other areas of OS X, you can also use spacebar to Quick Look!
Quick Look in the debugger can also be implemented for your own classes:
Enabling Quick Look for Custom Types
The variables Quick Look feature in the Xcode debugger allows you to obtain a quick visual assessment of the state of an object variable through a graphical rendering, displayed in a popover window either in the debugger variables view or in place in your source code.
This chapter describes how you implement a Quick Look method for your custom class types so that object variables of those types can also be rendered visually in the Quick Look popover window.
If you like to work with the lldb console, use chisel command "visualize"
tip:
after the installation, you can set a conditional breakpoint after setting the UIImage with the action:
"visualize myUIImageToShowWithQuickLook"
this will show you the image automatically when the debugger stops.
EDIT:
As of Xcode 5, the debugger can show you the visual representation of UIImage/CGImageRef variables!
Xcode itself can't do it. I don't know about external tools.
What i'm doing to test images while debugging is to convert that raw data into an image-file format, like .png, and then saving it somewhere, and then i'm opening the image with any image viewing tool.
I have a piece of code for that purpose, which look basically like that:
NSData *imageData = UIImagePNGRepresentation(self.myUIImage);
[imageData writeToURL:desktopURL atomically:YES];
And i'm just copy-pasting this code where i want to see content of an image on the run.
Make sure to get rid of this code as soon as possible due to the high-cost of the conversion of UIImage to NSData
Edit for Xcode 5: Now when you hover over an image variable name, there is an "eye" icon on the right. Just click it to see the current image!
NOTE: sometimes this fails in Xcode, even if the image is correct. If this happens, OR if you don't have a UIImage variable (e.g. it's a property of another object, you can still use the older answer:
Older answer: Starting with Avraham's answer, I tried a few experiments for displaying an iOS image from lldb without having to recompile or add it to a view. I finally came up with:
e [UIImagePNGRepresentation(myImage) writeToFile:#"/Users/<userName>/Desktop/myImage.png" atomically:NO];
I keep this string in a text editor and paste it when I need it. This stores the current image I'm interested in (in this case, "myImage") to a PNG file on the Desktop. Then I can just open this file with Preview.
If you're working on an iOS device, then you can use
e [UIImagePNGRepresentation(myImage) writeToFile:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingString:#"/myImage.png"] atomically:NO];
Then you can use the Finder; select your device; "Files"; then your dev app, and copy the image to your Desktop to view it.
What if you can't get to the image via the variables view?
Echoing what #pkamb said - you can use the variables view to quick look at an image. But what if you can't get to the image?
for example I have an image at (contentViewController.view.subviews[0].subviews[1] as? UIImageView).image
but if I try to expand contentViewController in the variable view it doesn't expose my subviews
what you can do is right click, add an expression, and then you can see it!
Click the eye icon when hovering over a variable in Xcode:
You can put a breakpoint in the line of your image, and then in the debugger, just write:
po your_UIImage_object
po stands for print object, it's a GDB command which will display several useful informations about the object passed, in your case the image.

Trouble with data not saving with bindings and shared NSUserDefaults in IB

I'm having a bit of a strange issue that I can't quite figure out. I'm somewhat of a n00b to Interface Builder. What I am trying to do seems like it should be simple, but it's not working for some reason.
In interface builder I have a preferences window with a simple NSTextField. I have set the value binding to the Shared User Defaults Controller with the controller key "values" and model key "test". I build/run my app and open the preferences window, type some random value into said text field, close the window. Command-Q the app. Then in a shell i do a "defaults read com.xxx.yyy" for my app and the key and value are nowhere to be found. That being said, it seems like the next time I fire up the app and change the value it works but only if I switch focus off of the NSTextField before closing the window.
In the documentation for NSUserDefaults it says that the shared controller saves values immediately, am I missing something stupid here?
Thanks for any help.
I'm answering this a long time after it was asked in case others find it useful.
It sounds like you need to set "Continuously Updates Values" for the text field you've bound. Otherwise, the value is only sent and, accordingly, the preferences only updated when something happens to 'finalise' the edit. That's usually triggered by pressing Return and probably also happens when you switch focus away from the window (though I just tested this in one of my own applications and it didn't seem to commit the edit).

Resources