Apple integrated Playground into Xcode the same year Swift was released (2014). Compared with standard Xcode projects, Playground is faster to start up and lighter to use. It is widely used in Swift language learning, framework API testing, fast data processing, inspiration gathering and many other aspects. This series will cover a wide range of tips for using Xcode Playground, from stability, third-party libraries, resource management, asynchronous processing, document tagging, and more, so that you can play with Playground and use it as a tool for your work and learning.

The original post was posted on my blog wwww.fatbobman.com

Welcome to subscribe my public account: [Elbow’s Swift Notepad]

Create and Set

.playground vs .playgroundbook

The Playground project created in Xcode is saved as a package with the suffix. Playground (you can view the files in it by displaying the contents of the package). Playground can be opened directly in Xcode and Swift Playgrounds versions 3.x and above.

Playgroundbook is the unique package format of Swift Playgrounds. Compared with. Playground, it contains many unique functions, which are mainly used to improve the educational and entertainment experience of Swift Playgrounds. Playgroundbook format can only be opened on Swift Playgrounds.

For more on the latest Swift Playgrounds 4 read Swift Playgrounds 4 Entertainment or Productivity

The tips in this series are focused on Xcode Playground (A.K.A. Playground), most of which are applicable to both Xcode and Swift Playgrounds, while those that are only applicable to individual platforms are clearly labeled.

How to create Playground project

Create the Playground project in Xcode

In Xcode, click File -> New -> Playground to create an Xcode Playground project of the format. Playground.

Playground provides several preset templates. The system setting of the template selection interface (iOS, macOS) only affects the template code and does not automatically set the running environment of Page.

Xcode can either open the Playground Project or add the Playground Project to a Project or Workspace (helpful for testing SPM or calling custom types in Project).

Create Playground project in Swift Playgrounds

In Swift Playgrounds 4 it is possible to create xcode-compatible Playground projects (.playground) directly. Click [View All] at the bottom of the home page to select Xcode Playground.

Please note: The Playground button at the bottom of the home page createsplaygroundbook

Projects created by Swift Playgrounds are saved by default in the Playgrounds directory on the iCloud cloud drive. Try not to edit a project on Xcode for macOS and Swift Playgrounds for iPad at the same time.

How to create multiple Playground pages

Playground encourages developers to focus on one issue at a time, helping them organize their code and resources by splitting the issue into different pages.

By default, the new Playground project has only one Page (in single-page mode, the Page and Playground projects in the navigation bar on the left will be displayed together). You can set the corresponding real-time view for each Page.

In Xcode, you can create a new Playground Page either from the File menu or by right-clicking on the Playground project in the navigation bar.

When there is more than one Page, the Playground item and Page are displayed separately.

In Swift Playgrounds 4, click the Edit button in the sidebar to enter edit mode and click the + button to create a new Page.

You can adjust the Page order, and you can change the name of each Page (not only for identification, but also for quick jumps between different pages).

In single-page mode, there is only one set of Sources and Resources directories in the project. In multi-page mode, in addition to Sources and Resources in the project root directory, each Page also has its own Sources and Resources directories.

Each Page should be treated as A separate Module, and code in Page A cannot be called by Page B.

How to debug code

Playground does not provide breakpoint setting, but some debugging needs can be met by specifying end points or by stepping.

In Xcode, you specify where the current execution ends by clicking the execute button on the number of lines to the left of the code (the color of the button is required to be blue).

Click the blue execute button after the current end position to continue down. Click the Execute button below the code edit area to re-execute the entire code.

After entering new code, you can make Playground execute code that hasn’t been executed as of this line by typing shift-return. This approach can be very useful in situations where you don’t want to repeat time-consuming pieces of code (such as machine learning).

Swift Playgrounds doesn’t have the ability to set where execution ends, but it does have a step setting. Click the instrument button at the bottom of the screen to set the debugging mode.

Improved runtime stability under Xcode (Xcode Only)

Setting up the Operating Environment

In Xcode, you can set the environment for Playground to run in the Playground Settings on the right.

Without having to rely on iOS framework code, setting the runtime environment to macOS can reduce instability caused by iOS emulator errors.

When there are multiple Playground pages, you can set the corresponding running environment for each Page.

When there are multiple Playground pages, click the project name at the top to set a unified running environment for all the pages

Swift Playgrounds is only compatible with Playground on iOS.

Change the running mode to manual

When the operation mode is set to automatic, the system automatically runs the code and displays the results whenever you modify it. Automatic mode works fine when the code content is small and simple, but when the code content is large and complex, automatic mode leads to a large amount of system resources and unstable operation.

Long press the execute button below the code editing area to choose between two modes.

In the configuration of Xcode, we can specify appropriate shortcut keys for Playground to improve operation efficiency.

How do I view the results bar

Playground has a unique display area in Xcode, the result bar, that not only displays the current value and historical status of each line of code, but also displays information about the number of calls, files, and more.

For example, in the figure above, line 55 shows the size of the image, line 57 shows the value of y in the current line, and line 59 shows the number of times the line is executed in the loop.

The eye icon appears when the mouse moves close to the screen icon on the right. Clicking the eye icon displays the QuickLook content for that line of code. Clicking on the screen icon displays the QuickLook content in the code editing area.

QuickLook’s content can be toggled between the latest value, history, and chart modes (the number of toggable modes will vary depending on the type).

QuickLook in Swift Playgrounds operates similarly to Xcode and can be turned off to improve code execution.

How to create a custom QuickLook

Apple already provides QuickLook support under Playground for a number of system types. By making the other system types (focused on a new API) and our custom types satisfy CustomPlaygroundDisplayConvertible agreement, to provide QuickLook support.

For example, WWDC 2021’s new AttributedString doesn’t currently support QuickLook, but by converting it to NSAttributedString in playgroundDescription, You can display the correct QuickLook directly on Playground.

The status of the below for, does not meet CustomPlaygroundDisplayConvertible agreement. The QuickLook of an AttributedString is the Dump style of the structure.

Apple provides the correct QuickLook implementation for NSAttributedString, which converts the AttributedString to NSAttributedString for better display.

extension AttributedString: CustomPlaygroundDisplayConvertible {
    public var playgroundDescription: Any {
        NSAttributedString(self)}}Copy the code

PlaygroundSupport

What is a PlaygroundSupport

PlaygroundSupport is a framework specifically designed to extend Playground. It provides the ability to share data in Playground, manage live views, and control how Playground runs.

Import the framework by importing PlaygroundSupport in the code for the Playground Page you want.

How to get results for asynchronous execution (Swift Playgrounds Only)

In older versions of Xcode (Xcode 12 and Xcode 13 already solved this problem) and Swift Playgrounds, Playground doesn’t wait for the asynchronous code to return results until all code calls are made. Playground needs to be set to infinite execution mode before it terminates after the results of asynchronous execution are obtained.

Executing the following code in Swift Playgrounds does not result in a print

DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    print("Hello world")}Copy the code

Import PlaygroundSupport and set needsIndefiniteExecution to true.

import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    print("Hello world")}Copy the code

Each Page needs to be set separately and not at the end of the code.

How to execute async/await code

This section does not require the support of PlaygroundSupport, but is placed here in order to keep close to the section “How to Get results for Asynchronous execution”

When using new async/await code in Playground, you need to import _Concurrency to run the code properly.

import _Concurrency

Task {
    try await Task.sleep(nanoseconds: 2 _000_000_000)
    print("Hello world")}Copy the code

To execute the above code in Swift Playgrounds, you need to set needsIndefiniteExecution.

How do I create a live view

You can use live views to add interactivity to the Playground, experiment with different user interface elements, and build custom elements. You can add an interactive live view to your Playground Page by importing PlaygroundSupport and setting the live view of the current Page as your custom view or view controller.

Real-time View Supports SwiftUI view and UIKit view and view controller. The SwiftUI view needs to be set using setLiveView.

import PlaygroundSupport
import UIKit

let lable = UILabel(frame: .init(x: 0, y: 0, width: 200, height: 100))
lable.text = "Hello world"
lable.textAlignment = .center
lable.textColor = .red

/ / PlaygroundPage. Current. SetLiveView (lable) UIKit views, two methods of setting
PlaygroundPage.current.liveView = lable
Copy the code

After setting up a live view, Playground automatically sets needsIndefiniteExecution to True.

If you want to terminate execution through the code, you can use PlaygroundPage. Current. FinishExecution ()

In Xcode, you can also through PlaygroundPage. Current. LiveTouchBar Touchbar from definition.

How can other type instances be displayed in live view

Any type that complies with the PlaygroundLiveViewable protocol can be set to live view.

The following code allows the UIBezierPath to be displayed directly in a dynamic view

import PlaygroundSupport
import UIKit

let path = UIBezierPath(a)var point = CGPoint(x: 0, y: 0)
path.move(to: point)
point = CGPoint(x: 100, y: 0)
path.addLine(to: point)
point = CGPoint(x: 200, y: 200)
path.addLine(to: point)

extension UIBezierPath: PlaygroundLiveViewable {
    public var playgroundLiveViewRepresentation: PlaygroundSupport.PlaygroundLiveViewRepresentation {
        let frame = self.bounds
        let view = UIView(frame: frame)
        view.backgroundColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1)
        let layer = CAShapeLayer()
        layer.path = self.cgPath
        view.layer.mask = layer
        return .view(view)
    }
}

PlaygroundPage.current.liveView = path
Copy the code

Obtain the Playground Shared directory (playgroundSharedDataDirectory)

PlaygroundSharedDataDirectory pointing to a Shared resource between the Playground Page directory.

If Playground Page is set in macOS mode, the contents of this directory can be shared among the macOS mode pages of different Playground projects. If Playground Page is running in iOS mode, the contents of this directory can only be shared within the iOS mode pages of the same Playground project (each Playground project has its own iOS emulator).

import PlaygroundSupport
import AppKit

let url = playgroundSharedDataDirectory.appendingPathComponent("playground1.png")
if let data = try? Data(contentsOf: url) {
    _ = NSImage(data: data)
}
Copy the code

On macOS, this directory is a subdirectory of Shared Playground Data under the user documentation directory. The system does not automatically create the directory. You need to manually create the directory.

PlaygroundSharedDataDirectory is mainly used to hold multiple under macOS Playground common data needed for the project. Within a single Playground project, you can share data across pages through the project’s Resource directory.

conclusion

In “Playing Xcode Playground (part 2)”, we will focus on SPM, resource management, auxiliary code, document annotations and other aspects.

I hope this article has been helpful to you.

The original post was posted on my blog wwww.fatbobman.com

Welcome to subscribe my public account: [Elbow’s Swift Notepad]