Swift, Playgrounds, and XCPlayground
http://www.codeschool.com/blog/2014/12/12/swift-playgrounds-xcplayground/
Swift, Playgrounds, and XCPlayground
Swift Playgrounds are a great feature of Xcode 6 that allow you to create a single file to test out code before adding it to your app’s main codebase. Prior to Playgrounds, if you wanted to test out code, you had a couple options — you could create a new git branch off of master of the app you’re working on, or, if you’re like me, you could open a brand new project with the Single View Application template and try to build enough of a base to start testing the feature you want.
Playgrounds reduce the amount of steps between having an idea and prototyping it, but there’s certain things they can’t do right out of the box, like network requests or showing rendered views when you try to draw UIViews.
Fortunately, these features are just a module import away.
XCPlayground
XCPlayground is a new module that has a few methods to help you get the most out of Playgrounds. Adding it to your playground is as simple as adding an import statement right near the default UIKit import, like this:
import UIKit // there by default
import XCPlayground // add this in
XCP EXECUTION SHOULD CONTINUE INDEFINITELY
Let’s say you want to prototype some code that requests an API endpoint and returns some JSON data. The setup for that scenario might look like this:
// create a session object
let session = NSURLSession(
configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
// make a network request for a URL, in this case our endpoint
session.dataTaskWithURL(NSURL(string: "http://localhost:8080/notes")!,
completionHandler: { (taskData, taskResponse, taskError) -> Void in
// create an NSArray with the JSON response data
var jsonReadError:NSError?
let jsonArray = NSJSONSerialization.JSONObjectWithData(
taskData, options: nil, error: &jsonReadError) as [AnyObject]
}).resume()
The problem you’ll run into when you run this code, though, is that your playground execution happens so fast the completion handler won’t have enough time to complete before execution stops. That means that none of the code inside of the handler will run, and you won’t have that JSON response data.
The solution? Call XCPSetExecutionShouldContinueIndefinitely() at the top of your file just below the imports, and set the continueIndefinitely boolean argument to true. This tells your playground it shouldn’t stop right away, and you’ll now see the jsonArrayobject has data that’s been returned from the API.

XCP SHARED DATA DIRECTORY PATH
It’s common to prototype apps with local data first. Often the design of the API that eventually returns real data is being built alongside the app, and not having to immediately account for all of the edge cases that come with asynchronous callbacks can help developers focus on view layout and other core features.
In a normal Xcode project you can easily import files and folders directly, but playgrounds don’t offer the same support. Instead, each time a playground is opened, it’s assigned a new random container buried deep in the /var folder. That container holds a Shared Playground Data folder that is symbolically linked to/Users/HOME_FOLDER/Documents/Shared Playground Data, so anything you put in that folder will be available in your playground.
The XCPSharedDataDirectoryPath string constant always holds a reference to that shared folder, so any files you want to access in your project can be put in that Shared Playground Data folder and accessed in the playground.
A SMARTER SHARED DIRECTORY PATH
Putting all of your files in that shared /Documents subfolder is fine until you’ve got multiple playgrounds, so why not organize all of your files per-playground just like you usually do per-project? There’s no direct support out of the box for this, but you can create a helper method that makes things easier. Here’s the one I use:
func pathToFileInSharedSubfolder(file: String) -> String {
return XCPSharedDataDirectoryPath +
"/" +
NSProcessInfo.processInfo().processName +
"/" +
file
}
NSProcessInfo().processInfo() creates an object that contains tons of information about what Xcode is currently running, which right now is your playground! The processNameproperty of that process is the same as the file name of your playground, so if I haveNetworkPrototype.Playground, then processName will be NetworkPrototype. That gets appended along with a / to the end of that Shared Playground Data folder path. Finally, I append the file name string I passed into the function as an argument called file.

Now, grabbing the contents of a file inside a playground is a little easier. For example, like grabbing a JSON data object from a local JSON file:
let jsonData = NSFileManager.defaultManager().contentsAtPath(
pathToFileInSharedSubfolder("data.json"))!
Or, loading a locally stored image into a UIImageView:
let imageView = UIImageView()
imageView.image = UIImage(contentsOfFile: pathToFileInSharedSubfolder("code-school.png"))
XCP CAPTURE VALUE
Prototyping data operations is nice, but you’re also probably going to want to build up some actual views at some point. For example, take the following playground code:
let view = UIView()
view.frame = CGRectMake(0,0,320,568)
view.backgroundColor = UIColor.lightGrayColor()
let imageView = UIImageView()
imageView.frame = CGRectMake(20, 20, 280, 51)
imageView.image = UIImage(contentsOfFile: pathToFileInSharedSubfolder("code-school.png"))
view.addSubview(imageView)
let label = UILabel()
label.frame = CGRectMake(0, 100, 320, 30)
label.textAlignment = .Center
label.text = "Welcome!"
view.addSubview(label)
This creates a view and sets the background color to gray, adds an image view that’s sourced from a local file (see the above section), and adds a label with the text “Welcome!”. One way to see that rendered view is to click on the tiny eyeball icon in the debug panel in the playground, but even then you only get to see the view preview once before you have to collapse the panel and get back to coding.
By calling XCPCaptureValue() and passing it an identifier string and a view object, you’ll be able to see that view in the timeline, like this:
...
label.text = "Welcome!"
view.addSubview(label)
XCPCaptureValue('mainView', view)
view there is that gray UIView object we created above. If you pair this withXCPExecutionShouldContinueIndefinitely like I described above, you’ll have a continuously updating UIView preview right inside of your playground!

Here’s a zip file that contains the Code School logo and a playground that has all of the code in this post: CodeSchoolProtoPlayground.zip. Let us know what you think about Swift Playgrounds, and if you’d like to see more blog posts on iOS, in the comments section below!
ABOUT THE AUTHOR
Jon Friskics
Content Producer and Developer at Code School. Enjoys building iOS and web apps, and then figuring out the best way to teach people how to build their own.
View Discussion
Swift, Playgrounds, and XCPlayground的更多相关文章
- Swift Playgrounds for mac基础知识介绍
Swift Playgrounds是一款适用于iPad和Mac的革命性应用程序,它使Swift学习变得互动而有趣.它不需要编码知识,因此非常适合刚开始的学生.使用Swift解决难题,以掌握基本知识.S ...
- Swift vs. Objective-C:未来看好 Swift 的十个理由
Swift vs. Objective-C:未来看好 Swift 的十个理由 是时候使用易入手又全面的Swif语言为iOS和mac OS X做应用开发了. 虽然编程语言不会那么容易消逝,但坚持衰落范例 ...
- iOS开发者知识普及,Swift 挑战 Objective-C,谁会笑到最后?
前言: 目前全球共有超过 7 亿台 iPhone 处于活跃状态,全球约有2000万名 iOS 开发者,这造就了 iOS 作为全球第二大移动设备平台的状态. 虽然安卓系统的全球市场占有率超过 iOS 系 ...
- Swift Playground All In One
Swift Playground All In One Swift 5.3 Playgrounds in Xcode Xcode 11.5 https://developer.apple.com/vi ...
- Swift in Action
Swift in Action Swift Playgrounds https://apps.apple.com/us/app/swift-playgrounds/id1496833156?mt=12 ...
- 2016 苹果全球开发者大会(WWDC)
纵观WWDC 2016开发者大会的全部内容,尽管本次大会没有那些新的产品发布,不过能让各位果粉的肾留到秋天,那也是苹果公司对各位果粉的关爱啊.但是对iOS开发者而言,新发布的技术还是比较不错的.主要内 ...
- iOS 单元测试和UI测试教程
原文:iOS Unit Testing and UI Testing Tutorial 作者:Audrey Tam 译者:kmyhy 编写测试不是为了追求刺激,测试是为了避免你崭新的 App 变成了充 ...
- WWDC 2016 盛宴
转自:http://www.jianshu.com/p/72dd8306c817 整理和维护人:pmstGitHub 链接:WWDC-2016-Feast目前只是整理官方给出的 WWDC 2016 视 ...
- The Swift Programming Language 中文翻译版(个人翻新随时跟新)
The Swift Programming Language --lkvt 本人在2014年6月3日(北京时间)凌晨起来通过网络观看2014年WWDC 苹果公司的发布会有iOS8以及OS X 10.1 ...
随机推荐
- Python 3基础教程17-提问频率较高的几个Python问题
这里,介绍几个初学者经常上网查询的问题,直接看下面的例子 # 常见的一些常识问题汇总 #!/user/bin/python # 这个是linux下python文件的写法,告诉程序,这个文件是pytho ...
- Micro Average vs Macro average Performance in a Multiclass classification setting
整理摘自 https://datascience.stackexchange.com/questions/15989/micro-average-vs-macro-average-performanc ...
- 分词(Tokenization) - NLP学习(1)
自从开始使用Python做深度学习的相关项目时,大部分时候或者说基本都是在研究图像处理与分析方面,但是找工作反而碰到了很多关于自然语言处理(natural language processing: N ...
- Linux的常用目录学习笔记
首先,先查看一下Linuxi的一级目录结构: ls: /:表示根目录,文件系统的入口,最高一级目录. bin和sbin:命令保存目录,bin是普通用户能,sbin是root用户用的:/bin存放着系统 ...
- lintcode-123-单词搜索
123-单词搜索 给出一个二维的字母板和一个单词,寻找字母板网格中是否存在这个单词. 单词可以由按顺序的相邻单元的字母组成,其中相邻单元指的是水平或者垂直方向相邻.每个单元中的字母最多只能使用一次. ...
- lincode-58-四数之和
58-四数之和 给一个包含n个数的整数数组S,在S中找到所有使得和为给定整数target的四元组(a, b, c, d). 注意事项 四元组(a, b, c, d)中,需要满足a <= b &l ...
- 【Linux】——搭建redis
1.准备安装文件 redis-3.0.5.tar.gz redis-desktop-manager(可视化管理工具) 2.解压.编译 软件存放目录:/usr/local/software 解压存放路径 ...
- vue2.0中改变了数组值不能实时反映到页面
页面中点击事件checkContent,改变row数组中的row[99]的值,如果注释更改,那么页面是不能实时获取的,如图更改,则可以 具体原理:http://blog.csdn.net/websof ...
- [CF1019A]Elections
题目大意:有$n$个人,$m$个政党,每个人都想投一个政党,但可以用一定的钱让他选你想让他选的政党. 现在要$1$号政党获胜,获胜的条件是:票数严格大于其他所有政党.求最小代价 题解:暴力枚举其他政党 ...
- [bzoj] 2038 小Z的袜子(hose) || 莫队
原题 给出一个序列,求给定[l,r]内有任意取两个数,有多大概率是一样的 简单的莫队,每次+-当前区间里有的这个颜色的袜子的个数,最后除以(r-l+1)*(r-l)/2即可. 记得约分. #inclu ...