If you have experience in iOS development with Swift, making a Swift Playground application would not be a tough job for you. However, there are still some differences between developing an iOS application and a Swift Playground application, for example, using Storyboard and Xib files is almost impossible, and the code execution queue might be a little bit different. Here are some tips that can help iOS developers to quickly hands-on Swift Playground application development. Briefly speaking, here are the things that you should know about developing a Swift Playground:
- Create files in
./Sources/
folder to write your primary code (classes definition, instance method, struct definition, etc.), instead of writing everything directly inContents.swift
. - Use proper layout with
NSLayoutConstraint
, as it is too difficult to introduce the interface builder to your Swift Playground application. - Use Mark Up grammar with special indicators to write a good looking and interactive playground instruction.
- Write, AirDrop, test run, and again.
Note that the sample code in this article can be found in this repository.
Adding Source File to Your Project
Even though the single view playground template defines a UIViewController
class in the file Contents.swift
, the ./Sources/
folder is capable of placing the source code files, and it is strongly recommended to create the classes in separate files instead of writing everything in Contents.swift
.
I personally noticed that there would be unreasonable dispatch queue issues with the code execution. In brief, the code execution queue in Contents.swift
may not be identical to the queue that is supposed to be executed, this could cause run time error, and of course, iPad would not indicate anything about the error: it would just suggest that there is something going wrong, and you need to check your code. Sometimes the error would be eliminated with DispatchQueue.main.async
method, others are more complicated, and the performance varies from the version of iPad, and from each run to other runs. For instance, the Playground workes fine on iPad 2018 would fail on iPad Pro, and the code that works well this time might fail the next time you run it. Thus, to make your life easier, simply place most of the code on the files in ./Sources/
, instead of writing everything in a single file.
By the way, do not forget to use public
notation in front of the shared variable definition and override function definition since the code in ./Sources/
is actually a package. Here is some sample code.
1 | public func delay(for seconds: Double, block: @escaping ()->()) { |
Layout Your Interface
For Swift Playground projects, applying storyboard files or xib files is extremely complicated and could cause lots of problems. Besides, considering the functionality of the Swift Playground, the interface is usually simple. Thus, applying layout with code is a good option. NSLayoutConstraint
is used for this purpose.
Where to Add the Code
By creating an iOS playground with the Single View template, you will notice that the layout process is done in layoutView
, given as follows.
1 | override func loadView() { |
However, as far as I've noticed, writing the codes for layout within layoutView
works fine for the older version of Swift Playground in iOS 12, it causes layout problems in iOS 13, with a newer version of Swift Playground. You can try this older version of Swift Playground and see whether the layout works fine on your device. To fix the layout problem that the newer version brings, I'd suggest you only write the code for instantiating view
instance of the UIViewController
in loadView
, and leave any other layout code for viewDidLoad()
, as we usually do for normal iOS projects.
1 | public override func loadView() { |
Applying Constraint Programmatically
Since we've figured out where we should add the code for layout, now it's time to implement them.
Anchors of UIView
The essence of the layout is to place the views to the right location in its container, and the so-called 'right location' is usually defined by the view's height and width, the distance to the view next to it, or the horizontal or vertical centering. NSLayoutAnchor
, as one of the member variables of UIView
, is the thing that forms the relation. There are anchors on each boundary of the view, width, and height, as well as the center. The name of the anchors including topAnchor
, bottomAnchor
, leadingAnchor
, trailingAnchor
, widthAnchor
, heightAnchor
, centerXAnchor
and centerYAnchor
.
Before applying the constraint, do remember to set the view's translatesAutoresizingMaskIntoConstraints
property to false
, or the constraint would not take effect.
1 | nView.translatesAutoresizingMaskIntoConstraints = false |
Activating the Constraint
For static layout, you just need to activate the NSLayoutConstraint
in loadView()
. By accessing the member method constraint
of different anchors, it is easy to set up the relationship between anchors, say, constraints. Here are the sample codes.
1 | NSLayoutConstraint.activate([ |
1 | NSLayoutConstraint.activate([ |
Note that the constant
parameter defines the deviation of the layout, the positive direction of the X and Y axis are right and down.
Using Constraint as Member Variable
In some conditions, the layout needs to be changed (e.g. progress bars). The NSLayoutConstraint
can be initialized and set active later on, as follows.
1 | public var vConstraint: NSLayoutConstraint! |
To change the constraint (even with animation), use the following code.
1 | UIView.animate( |
Write a Mark Up
The mark up is used to instruct the users to use your Swift Playground, sometimes modify your code a little. Basically, variables that can be assigned to new values in Contents.swift
are global variables, say, variables defined outside the class or structure and marked as public
in files in ./Sources/
folder.
For the details of the mark up language, you can refer to Apple's Document.
Debugging Tips
The debug process is tough for Swift Playground projects since you cannot add breakpoints1. Using the 'Step Though My Code' or 'Step Slowly' could be a solution, but they are still not fancy. Most of the time, the developing process is simply write -> AirDrop to your iPad -> run and find error -> again, it is not odd to see almost a hundred duplicated playground files in your Swift Playgrounds app when you are debugging. Sometimes, methods such as commenting the doubtful code or use UITextField
as an output console (stupid option, but it is true that the console is not available on iPad, which means you could not simply print
and check the errors) would help a little. Anyway, good luck with that!
Reference
https://stackoverflow.com/questions/29710286/debug-breakpoint-in-swift-playground↩︎