Xcode 3.2 Debug: Seeing whats in an array? - xcode

Whilst debugging in Xcode_3.1.2 I am pretty sure I could see the contents of my NSString arrays. However after upgrading to 3.2 I only see the following ...
I know I can print the object in (gdb) using "po planetArray" or simply click in the debugger and "print description to console" I am just curious, as I am sure it worked prior to upgrading. Anyone know anything about this?
cheers gary
edit: data formatters is on and it shows what you see above ...

This is because GDB acts as if the variable you are viewing is out of scope while it really just is confused about what each part function or method call of the data formatter is returning (the data formatter is the "{(unichar *)Xcode_CFStringSummary($VAR, $ID)}:s" part you are seeing.
When you are debugging and you are in a method where you know a local variable must be in scope right now, open the debugger window and the area where you can see "Variable", "Value" and "Summary" column titles double click the "Summary" row entry for the variable you are interested in and enter the following (for array types like NSArray or NSCFArray):
"{(int)[$VAR count]} objects {(NSString *)[(NSArray *)$VAR description]}:s"
then press return. You have now overwritten the default data formatter provided by Xcode's GDB extension (to be found in various plists at "/Developer/Library/Xcode/CustomDataViews/") with your own data formatter string.
Your own overrides are saved at "~/Library/Application Support/Developer/Shared/Xcode/CustomDataViews/CustomDataViews.plist" and if you want to have the Apple default data formatter back just double click the row for a variable of the same type and delete whatever is there.
The nitty-gritty details: In the custom expression above the "{}" construct tells GDB to execute a command (as if you where executing it from GDB's debugger command line, which means the same restrictions apply: you need to specify the return type in cast parens in front of every function or method which returns something). The ":s" behind the closing curly brace tells Xcode and GDB to reference the "Summary" column. Also valid would be ":v" which references the "Value" column which most of the time is just the pointer value. Everything that is outside of the curly braces is shown verbatim.
Unfortuntely curly braces can't be nested which invalidates ternary operator conditionals.
So with the above data formatter you should see the following for an empty NSArray:
"0 objects (\n)"
If you want to write your own data formatters as GDB extensions (equivalent to specifying a function akin to Xcode_CFStringSummary above) you can do so. Take a look at the following header: "/Developer/Applications/Xcode.app/Contents/PlugIns/GDBMIDebugging.xcplugin/Contents/Headers/DataFormatterPlugin.h"
it will tell you all you need to know. But it can be hard to get it right. It might be easier and less error prone to just define another method on your class and call that from the data formatter string instead of "description".

In the Run > Variables View menu in Xcode, is "Use Data Formatters" enabled?

I am not sure if this helps but if you select the array value to wish to see in the debugger window and the go to the Menu : Run > Variables View > View Variable As
you can change it from "NSCFString *" to "NSString *". You then see the value so "Planet_1" for example.
Cheers,
Kevin

Related

Xcode Breakpoint and LLDB - How do I open a file (e.g. in Preview) from a given fileURL stored in a variable?

I have a variable in Swift code that runs in iOS simulator and contains an existing fileURL. I want to have the file opened in macOS (not the iOS Simulator) when I hit a breakpoint.
I added an action "Shell Command" to the breakpoint to open the file. The file exists because if I copy-paste the file's path to Terminal, it opens in Preview.
However, the Xcode console says the contrary:
The file /"/Users/tomkraina/Library/Developer/CoreSimulator/Devices/FBA16E00-9450-40E8-9650-1489A67E344C/data/Containers/Data/Application/BB97DB72-FF2A-4087-BD42-2934C63D3323/tmp/7E2303B8-0629-475A-862A-2550351FB448/OutlineExport.pdf" does not exist.
First Question: How do I tell Xcode to open a file with provided fileURL in a variable on breakpoint?
Next thing I tried was to open the file using LLDB, but I cannot find out how to evaluate a command parameter in LLDB, because backticks is only for scalars:
(lldb) shell open `temporaryFile.fileURL.path`
The file /105553157711856 does not exist.
Second Question: How to I evaluate argument parameter to get a string in LLDB?
I don't have a good answer for the first question. It would be interesting to check whether the path that is in the Xcode error message is correct - maybe it's getting it from the value incorrectly. If you copy the path from the error message, go to Terminal and try to open it, does that work? Anyway, this sounds to me like a bug in Xcode. It got some kind of path out of your variable and tried to open it, which should have worked. If you want to follow up, it's probably best to file a bug report with the Apple Feedback.
For the second question, you have to know a little about how variables work in lldb. Some variables have obvious values, for instance, in C a pointer has the pointer value, an integer the integer value, etc. Other variables (any kind of Struct being the obvious example) are actually containers of other values and don't really have a "value" themselves.
lldb can show you what a swift string really is using the --raw option:
(lldb) v --raw str1
(Swift.String) str1 = {
_guts = {
_object = {
_countAndFlagsBits = {
_value = -3458764513820540912
}
_object = 0x8000000100003f50 (0x0000000100003f50) strings`symbol stub for: Swift.print(_: Any..., separator: Swift.String, terminator: Swift.String) -> () + 4
}
}
}
That's probably really interesting to people working on the Swift Standard Library and has the virtue of being the truth. But for most purposes, it's not a terribly useful representation.
lldb handles that problem by adding a notion of "Summary Formatters" that generate a string representation for objects based on their type. There's one for "Swift.string" that digs around in the object, finds where the actual string is, and returns that text. If you don't pass --raw and there's a summary formatter, then lldb will show you the summary:
(lldb) v str1
(String) str1 = "some string here"
That is also the value that you want to try and open.
The backtick syntax in lldb gets the value of the entity, not its summary, which is why that didn't work for a swift string. However, you can fetch and act on the summaries for local variables using lldb's Python interpreter and the SB API. So for instance:
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> var = lldb.frame.FindVariable("str1")
>>> var.GetSummary()
'"some string here"'
So then if that was a file path you wanted to open, you can use Python to do that, like:
>>> os.system("open {0}".format(var.GetSummary()))
The file /private/tmp/some string here does not exist.
256
except of course your var has to hold the path to a real file...
If you want to learn more about the lldb Python API's the API docs are here:
https://lldb.llvm.org/python_api.html
and a general tutorial for using Python in lldb is here:
https://lldb.llvm.org/use/python-reference.html
And more information on variable formatting is here:
https://lldb.llvm.org/use/variable.html

Why do we need the question mark in Immediate Window of VS?

So, reading this documentation:
https://learn.microsoft.com/en-us/visualstudio/ide/reference/immediate-window?view=vs-2022
It looks like the question mark (?) is an alias for the command >Debug.Print, which basically, will evaluate the expression and show the result.
So, in debug mode, instead of running this:
>Debug.Print DoSomething()
I can run this:
? DoSomething()
This is even better because I'm getting the autocomplete suggestions.
Now, the issue is that I can run the same line without a command at all, and it does exactly the same:
DoSomething()
So far looks like there is no need for the command >Debug.Print or the alias ?.
At first, I suspected that using ? will only print the result without changing the values, but this is not the case (When I assign a value to a variable using ? it is assigned and the new value is printed)
So, am I missing something here? Are there any other differences between these 3 options?
According to the documentation, if you want to use Visual Studio command, you need to add greater than sign before the command. If you run 'Debug.Print' without adding greater than sign, you will get an error.
My point is that the question mark ('?') is unnecessary if you in the Immediate Window, it is used to distinguish the typed expression from the result.

ODI KM Option - value from FLEX FIELD

Do you think that it's possible to take a value into an ODI IKM Option (for example) from a flexfield?
Example:
You define a flex field on the target table and then pass the value in the IKM.
Then, reading the variable, it's possible to pass it to an option from the IKM?
Thanks,
After searching I found that it's not possible to do it. Conditional Expression can take predefined values. You can find in the next all the combinations:
Condition Expression – It allows you to set the required condition for
the selected option. Double-click the field for editing the condition
expression for the selected option. Click the browse icon Browse icon,
to launch the Edit Expression Editor, which enables you to create or
edit the existing groovy script that determines whether a knowledge
module should be enabled, disabled, displayed or hidden.
Examples are:
return
options.getValue("Cache").equals("true")?"show=true,enable=true":"show=false,enable=false";
This looks at the value of another KM Option called "Cache". If its
value is "false," then the KM Option is hidden, because it's not
relevant.
return
(isStreaming)?"show=false,enable=false":"show=true,enable=true";
This looks at the Mapping isStreaming property. If it's true, then
this option is hidden.
source
It is very easy to do.
You may use odiRef.getTable(java.lang.String pProperty) in the code of your IKM. One of possible values for pProperty is the code of your FlexField.
If you like to pass if through the option just pas <?…?>-substitution as a value of the option. (Probable you should play with %- or ?-substitutions, which is working.)
Refer to «Substitution API Reference» on Oracle site. Many functions like getTable, getIndex, getAK, getContext and others can obtain flexField value of an object of the corresponding type.
Additionally there is the odiRef.getFlexFieldValue() method. It gets the value of any object of any type, but it is required to pass internal IDs as an argument. So it is not convenient.

What are all of the possible Class Names in QTP or where can I find them?

I'm using QTP 11 and I could use a handy reference for all of the possible values for "Class Name". I'm not trying to manipulate this information. I just need a reference.
For example I know that I can access any input element using "WebEdit()" but what do I use for, say, a table cell.
I want a list I can refer to, not steps for finding the type of an object.
Three options come to mind immediately:
Option A. The handiest way to find the names probably is to look into the dialog Tools/Object Identification.
There, in the "Test Object classes" listview, you see all test object class names for the environment selected under "Environment" that QTP knows of.
Option B. If in the dialog from A. you push the "Generate script" button, creating a script. Use a grep facility (or TextPad, for that matter) to extract all lines containing the text "Object identification configuration for" from that script. This results in a text which after some cleanup is these lists:
User-defined (?):
"abtobjectgraphicswidget"
"cwarrowbutton"
"cwcheckbutton"
"cwlabel"
"cwpushbutton"
"cwradiobutton"
"cwtext"
"cwtext_multi"
"ewflowediconlist"
"ewiconarea"
"ewiconlist"
"ewicontree"
"ewpmnotebook"
"ewspinbutton"
"ewtablelist"
"ewtabletree"
"ewwinnotebook"
"gxcombobox"
"gxedit"
"gxlistbox"
"listview20wndclass"
"listviewwndclass"
"msvb_lib_toolbar"
"richedit"
"seccustomtoolbar"
"secmenubar"
"sectabctrl"
"sectabwnd"
"sectreectrl"
"sectreeview"
"stgrid"
"sysdatetimepick32"
"sysmonthcal32"
"textedit"
"treeview20wndclass"
"treeviewwndclass"
Standard (?):
"activex"
"acxbutton"
"acxcalendar"
"acxcheckbox"
"acxcombobox"
"acxedit"
"acxradiobutton"
"acxtable"
"javaapplet"
"javabutton"
"javacalendar"
"javacheckbox"
"javadialog"
"javaedit"
"javaexpandbar"
"javainternalframe"
"javalink"
"javalist"
"javamenu"
"javaobject"
"javaradiobutton"
"javaslider"
"javaspin"
"javastatictext"
"javatab"
"javatable"
"javatoolbar"
"javatree"
"javawindow"
"dialog"
"static"
"winbutton"
"wincalendar"
"wincheckbox"
"wincombobox"
"window"
"winedit"
"wineditor"
"winlist"
"winlistview"
"winmenu"
"winobject"
"winradiobutton"
"winradiogroup"
"winscrollbar"
"winspin"
"winstatusbar"
"wintab"
"wintable"
"wintoolbar"
"wintreeview"
"browser"
"frame"
"image"
"link"
"page"
"viewlink"
"webarea"
"webbutton"
"webcheckbox"
"webedit"
"webelement"
"webfile"
"weblist"
"webradiogroup"
"webtable"
Note 1: the user-defined objects are probably add-on specific, or otherwise registered in a special way in QTP.
Note 2: this is just a sample of what you might get on your machine. For example, I don´t have the Delphi add-on active, so all the Delphi control´s test object class names are missing. If you want me to activate all add-ons, and re-create this list, I´ll give you my bank account first ;)
Option C. In the online help, from the contents, try navigating to the "HP QuickTest Professional Object Model Reference". It contains chapters per environment, and most of them consist of "X Object" chapters, i.e. there is a "WebButton Object" chapter under "Web".
Option D. See Rich's answer :-O
Since micclass is the same thing as the Class Name property (other than programming placement), the class names of the objects that you are trying to apply to micclass can be utilized. To find the class names of all objects used in the QTP environment, you can use the Mercury.ObjectRepositoryUtil to iterate through the objects and collect what's necessary for the micclass.
More details on that -> Here and Here

VS2010 save array/collection data to a file while debugging

Is there some way to save array/list/collection data to a file while debugging in VS2010?
For example, in this code:
var addressGraphs = from a in context.Addresses
where a.CountryRegion == "Canada"
select new { a, a.Contact };
foreach(var ag in addressGraphs) {
Console.WriteLine("LastName: {0}, Addresses: {1}", ag.Contact.LastName.Trim(),
ag.Contact.Addresses.Count());
foreach(var Address in ag.Contact.Addresses) {
Console.WriteLine("...{0} {1}", Address.Street1, Address.City);
}
}
I'd like to set a breakpoint on the first 'foreach' line and then save the data in 'addressGraph' to a file.
where 'a' contains fields such as:
int addressID
string Street1
string City
<Ect.>
and 'Contact' contains fields such as:
string FirstName
string LastName
int contactID
<Ect.>
I'd like the file to contain the values of each of the fields for each item in the collection.
I don't see an obvious way to do this. Is it possible?
When your breakpoint is hit, open up the Immediate window and use Tools.LogCommandWindowOutput to dump the output to a file:
>Tools.LogCommandWindowOutput c:\temp\temp.log
?addressGraphs
>Tools.LogCommandWindowOutput /off
Note: You can use Log which is an alias for Tools.LogCommandWindowOutput
Update:
The > character is important. Also, the log alias is case sensitive.
See screenshot:
I also encoutered such a question, but in VS2013. I have to save a content of array while debugging.
For example, I need to save a content of double array named "trimmedInput". I do so:
Open QuickWatch Window from Debug menu (Ctrl+D, Q).
Put your variable in Expression and push Recalculate Button
You'll see all the values. Now you could select them all (Ctrl+A) and copy (Ctrl+C).
Paste (Ctrl+V) them in your favorite editor. Notepad, for example. And use them.
That's the simples way that I know. Without additional efforts. Hope that my description helps you!
P.S. Sorry for non English interface on screenshots. All necessary information are written in the text.
Something similar is possible with this method:
I built an extension method that I use in all of my projects that is a general and more powerful ToString() method that shows the content of any object.
I included the source code in this link:
https://rapidshare.com/files/1791655092/FormatExtensions.cs
UPDATE:
You just have to put FormatExtensions.cs in your project and change the Namespace of FormatExtensions to coincide to the base Namespace of your project. So when you are in your breakpoint you can type in your watch window:
myCustomCollection.ToStringExtended()
And copy the output wherever you want
On Visual studio Gallery search for: Object Exporter Extension.
be aware: as far as I worked with, it has a bug that block you from exporting object once in a while.
You can also call methods in the Immediate Window, and so I think your best bet would be to use an ObjectDumper object, like the one in the LINQ samples or this one, and then write something like this in the Immediate Window:
File.WriteAllText("myFileName.txt", ObjectDumper.Dump(addressGraph));
Depending on which ObjectDumper you decide to use, you may be able to customize it to suit your needs, and to be able to tell it how many levels deep you want it to dig into your object when it's dumping it.
Here's a solution that takes care of collections. It's a VS visualizer that will display the collection values in a grid while debugging as well as save to the clipboard and csv, xml and text files. I'm using it in VS2010 Ultimate. While I haven't tested it extensively, I have tried it on List and Dictionary.
http://tinyurl.com/87sf6l7
It handles the following collections:
•System.Collections classes
◦System.Collections.ArrayList
◦System.Collections.BitArray
◦System.Collections.HashTable
◦System.Collections.Queue
◦System.Collections.SortedList
◦System.Collections.Stack
◦All classes derived from System.Collections.CollectionBase
•System.Collections.Specialized classes
◦System.Collections.Specialized.HybridDictionary
◦System.Collections.Specialized.ListDictionary
◦System.Collections.Specialized.NameValueCollection
◦System.Collections.Specialized.OrderedDictionary
◦System.Collections.Specialized.StringCollection
◦System.Collections.Specialized.StringDictionary
◦All classes derived from System.Collections.Specialized.NameObjectCollectionBase
•System.Collections.Generic classes
◦System.Collections.Generic.Dictionary
◦System.Collections.Generic.List
◦System.Collections.Generic.LinkedList
◦System.Collections.Generic.Queue
◦System.Collections.Generic.SortedDictionary
◦System.Collections.Generic.SortedList
◦System.Collections.Generic.Stack
•IIS classes, as used by
◦System.Web.HttpRequest.Cookies
◦System.Web.HttpRequest.Files
◦System.Web.HttpRequest.Form
◦System.Web.HttpRequest.Headers
◦System.Web.HttpRequest.Params
◦System.Web.HttpRequest.QueryString
◦System.Web.HttpRequest.ServerVariables
◦System.Web.HttpResponse.Cookies
As well as a couple of VB6-compatible collections
In "Immediate Window" print following to get the binary dump:
byte[] myArray = { 02,01,81,00,05,F6,05,02,01,01,00,BA };
myArray
.Select(b => string.Format("{0:X2}", b))
.Aggregate((s1, s2) => s1 + s2)
This will print something like:
0201810005F60502010100BA
Change the '.Aggregate(...)' call to add blanks between bytes, or what ever you like.

Resources