How can I print to console in Swift Playgrounds on iPad? - swift-playground

I would like to debug a method deep inside my "Sources" folder within a Swift Playground.
public func wannaDebugThis() {
let x = 42
let text = "Debug message with useful information: x = \(x)"
print(text)
}
Within a macOS playground, the print output is shown in the debug area, as described in this question.
On iPad however, the print statement seems to be ignored. Even within Console.app on mac, I cannot find the desired output.
How do I write debug statements on iPad and where do I find them?

While I couldn‘t find a way to modify an Empty/Blank Playground to provide console in-/output. There is the „Answers“ template, that you can use for simple console interactions.
Another way is to use the „Interactions“ template, provided here: https://buildingrainbows.com/2018/03/13/print-to-the-console-in-swift-playgrounds-for-ipad/

This feature has been added to Swift Playgrounds version 3.4 on iPad

In order to write debug messages from the iPad to the console, NSLog() has to be used.
public func wannaDebugThis() {
let x = 42
let text = "Debug message with useful information: x = \(x)"
NSLog(text)
}
The output of NSLog() can be found under the process named ExecutionExtension in Console.app on macOS. The output of print messages is only shown as <private>, which can be seen on attached screenshot.

Related

How to see Print Debugging While Interface Builder Previews? IOS / XCode

When Interface Builder shows a preview of your ViewController, it must execute the code belonging to the views contained in that VC in order to draw them, right?
So... let's say you have some print debugging in your custom view...
print("draw() was executed")
... How can one see this output while Interace Builder is processing the preview?
Thanks!
As far as I have seen, there is no way of printing to the debug console when Interface Builder is executing your code. However, I did find it helpful to temporarily add messages to a label or textview instead.
If necessary, you can do conditional code that only execute when Interface Builder is running (or not) like below. That way, you can show a small message view that is only visible at design time, and otherwise hidden.
#if TARGET_INTERFACE_BUILDER
// IB only
#endif

How do I write to a file in Swfit2 from the Playground? [duplicate]

Files are not readable in Swift Playground.
How to make files readable?
Same code runs well on Xcode terminal app, but fails on Swift Playground.
Demo code below.
import Foundation
println("Hello, World!")
var fname:String = "/Users/holyfield/Desktop/com.apple.IconComposer.plist"
var fm:NSFileManager = NSFileManager.defaultManager()
if(fm.fileExistsAtPath(fname)){
println("File Exists")
if(fm.isReadableFileAtPath(fname)){
println("File is readable")
var fd:NSData? = NSData(contentsOfFile: fname)
println(fd?.length)
let pl = NSDictionary(contentsOfFile: fname)
println(pl?.count)
println(pl?.allKeys)
}else{
println("File is not readable")
}
}
else{
println("File does not exists")
}
Sample images:
I have to thank Nate Cook for first for his quick response and solid answer.
Just for case I share his answer from another post, which title is misleading.
See Nate's answer here: https://stackoverflow.com/a/26723557/2360439
Playgrounds are sandboxed, so you won't be able to just grab files from anywhere in your user folder. Here's how to add that file to your
playground to make it accessible:
Find your ".playground" file in the Finder Right click and choose "Show Package Contents"
You should see "timeline.xctimeline", "contents.xcplayground", and "section-1.swift"
Make a new folder called "Resources" if it doesn't exists yet.
Copy your files into Resources folder
Seems that there is no way to access files with Swift Playground outside of Playground sandbox. If you know how to access files outside of sandbox, you are welcome to share your solution!!
There are several ways to do load files into a Swift Playground. I'll highlight the Image Literal, File Menu and Context Menu techniques.
Image Literal technique
This is the easiest and COOLEST. You simply drag a file from anywhere on your machine into the code and assign it via a let or var statement. GIF here.
File Menu technique
Choose File -> Add Files to "MyProjectName"
See GIF of this here.
Context Menu technique
You can reveal the current playground in the Xcode (7.3.1) Project Navigator using the right-click menu. Upon revealing the current playground, you'll see a directory entitled Resources. Simply drag the file you want access to into that folder and watch the magic happen (given you've written the file access code).
Example resource loading code
Here's an example of doing this for showing an image:
let url: NSURL! = NSBundle.mainBundle().URLForResource("IMG_4099", withExtension: "JPG")
let imagePath = url.path
let image = UIImage(contentsOfFile: imagePath!)
let imageView = UIImageView.init(image: image)
I've produced an animated GIF that demonstrates this in action. Here's a screengrab from that:
Reading external code
If you want to add auxiliary code in addition to resources, use the Sources folder.
A note regarding the console
The console area of Xcode's Playground interface will show you that the UIImage instance is nil when you load an image file outside the sandbox. If you entered a path you know exists, but the image isn't showing, ensure the UIImage instance isn't printing as nil.
You also can create and use Shared Playground Data folder.
Just like that:
/Users/username/Documents/Shared Playground Data/file.txt
And any file located there becomes readable to any playground!

UITests in Xcode 7 finds wrong 'Next' button

I have a test that looks like the following:
func testNextButtonDisabled() {
let app = XCUIApplication()
XCTAssertFalse(app.buttons["Next"].enabled)
}
This test fails because, in addition to my own "Next" button that I've created, the keyboard return button is labeled 'Next'. This test fails with the error:
UI Testing Failure - Multiple matches found
How can I differentiate between my own 'Next' button and the keyboard 'Next' button?
The specific solution to this problem is to look for elements that are descendants of the main window.
func testNextButtonDisabled() {
let app = XCUIApplication()
XCTAssertFalse(app.childrenMatchingType(.Window).elementBoundByIndex(0).buttons["Next"].enabled)
}
For a general solution to solve problems like this: In Xcode run the "Record UI Test" again to see how Xcode thinks you should be referencing the element in which you're interested.

Swift Playground - Files are not readable

Files are not readable in Swift Playground.
How to make files readable?
Same code runs well on Xcode terminal app, but fails on Swift Playground.
Demo code below.
import Foundation
println("Hello, World!")
var fname:String = "/Users/holyfield/Desktop/com.apple.IconComposer.plist"
var fm:NSFileManager = NSFileManager.defaultManager()
if(fm.fileExistsAtPath(fname)){
println("File Exists")
if(fm.isReadableFileAtPath(fname)){
println("File is readable")
var fd:NSData? = NSData(contentsOfFile: fname)
println(fd?.length)
let pl = NSDictionary(contentsOfFile: fname)
println(pl?.count)
println(pl?.allKeys)
}else{
println("File is not readable")
}
}
else{
println("File does not exists")
}
Sample images:
I have to thank Nate Cook for first for his quick response and solid answer.
Just for case I share his answer from another post, which title is misleading.
See Nate's answer here: https://stackoverflow.com/a/26723557/2360439
Playgrounds are sandboxed, so you won't be able to just grab files from anywhere in your user folder. Here's how to add that file to your
playground to make it accessible:
Find your ".playground" file in the Finder Right click and choose "Show Package Contents"
You should see "timeline.xctimeline", "contents.xcplayground", and "section-1.swift"
Make a new folder called "Resources" if it doesn't exists yet.
Copy your files into Resources folder
Seems that there is no way to access files with Swift Playground outside of Playground sandbox. If you know how to access files outside of sandbox, you are welcome to share your solution!!
There are several ways to do load files into a Swift Playground. I'll highlight the Image Literal, File Menu and Context Menu techniques.
Image Literal technique
This is the easiest and COOLEST. You simply drag a file from anywhere on your machine into the code and assign it via a let or var statement. GIF here.
File Menu technique
Choose File -> Add Files to "MyProjectName"
See GIF of this here.
Context Menu technique
You can reveal the current playground in the Xcode (7.3.1) Project Navigator using the right-click menu. Upon revealing the current playground, you'll see a directory entitled Resources. Simply drag the file you want access to into that folder and watch the magic happen (given you've written the file access code).
Example resource loading code
Here's an example of doing this for showing an image:
let url: NSURL! = NSBundle.mainBundle().URLForResource("IMG_4099", withExtension: "JPG")
let imagePath = url.path
let image = UIImage(contentsOfFile: imagePath!)
let imageView = UIImageView.init(image: image)
I've produced an animated GIF that demonstrates this in action. Here's a screengrab from that:
Reading external code
If you want to add auxiliary code in addition to resources, use the Sources folder.
A note regarding the console
The console area of Xcode's Playground interface will show you that the UIImage instance is nil when you load an image file outside the sandbox. If you entered a path you know exists, but the image isn't showing, ensure the UIImage instance isn't printing as nil.
You also can create and use Shared Playground Data folder.
Just like that:
/Users/username/Documents/Shared Playground Data/file.txt
And any file located there becomes readable to any playground!

Getting Xcode 5 variable inspector to show custom summary and/or synthetic children

I have some C++ classes from a library which have opaque data types. Xcode doesn't understand them and so can't show them in the variable inspector. I've written Python scripts for lldb which can decompose these opaque types correctly and return synthetic children. I have a Python class OpaqVector_syntheticChildren which implements get_child_at_index(), num_children() and so on.
For example, at the lldb prompt when the program is paused at a breakpoint in Xcode:
(lldb) frame variable sarr
(OpaqueVector) sarr = {
[0] = 1
[1] = 2
[2] = 3
}
However, in the variable inspector, sarr shows the pink 'S' to show it's a structure and has no summary nor expansion arrow. I can right-click and choose 'Print description of "sarr"' and get the correct (matching above) output in the lldb console. Is there some extra trick to get Xcode itself show the structure's synthetic children?
Xcode calls the has_children() method of the class you provide to generate the synthetic children. If that function does not return True, it won't call num_children() or get_child_at_index(), whereas the lldb command prompt doesn't seem to do that check. Hence, if you have a bug in that function you'll get the behaviour I described in the question.

Resources