巷で噂の新iOSアプリ開発言語「Swift」ですが、そのSwiftを使って色々と出来るPlaygroundという新機能が、Xcode6に追加されました。
今回は、そのPlaygroundを使ってどういった事ができるのか、色々試してみました。
Playgroundとは
・Swiftのインタラクティブインタプリタ
・コードを書くとすぐに結果を表示
・グラフの表示やSprite Kitを使ったアニメーションも可能
Playgroundの作成
Xcode起動時に表示される「Welocome to Xcode」ウィンドウの「Get started with a playground」からPlaygroundを作成します。
「Welocome to Xcode」が表示されない場合は、メニューの「Window->Welcome to Xcode」から表示出来ます。
また、「File->New->Playground…」からPlaygroundを作成することもできます。
Playground名を入力、Platformを「iOS」にして作成。
Playgroundの画面
タイムラインの表示
「View->Assistant Editor->Show Assistant Editor」でタイムラインが表示されます。
タイムラインでは、コンソールへの出力結果の他に、行ごとの実行結果を表示することが出来ます。
行の右端をマウスオーバーすると表示される+ボタンをクリックすると、タイムラインにその行の実行結果が追加されます。
UI系であればどのように表示されるかを確認することが出来ます。
また、パラメータが変更さえる箇所をタイムラインに追加していくことで、その過程を見る事もできます。
このようなことは、実際にビルドしシミュレータで実行してと手間がかかりますが、Playgroundを使えばすぐに簡単に行えます。
グラフの表示
ループ処理をタイムラインに追加するとグラフが表示され、グラフのポイントをクリックすることで、その値を確認することが出来ます。
こんなグラフだって書けたりします。(分割されてはいますが、、、)
Playgroundをもっと便利にするXCPlaygroundフレームワーク
Playgroundには、XCPlaygroundというユーティリティフレームワークが用意されており、インポートするだけで様々な機能が利用できます。
値のキャプチャリング
「XCPCaptureValue(identifier: String, value: T)」では、同じidentifierで指定をしたものをグルーピングしてタイムライン上に表示してくれます。
以下は、LCG(線形合同法)での値の変化をキャプチャしたものです。
import XCPlayground var seed: UInt = 1 func lcg() -> UInt { let a: UInt = 1664525 let c: UInt = 1013904223 let m: UInt = 4294967296 seed = (a * seed + c) % m XCPCaptureValue("lcg", seed) return seed } for i in 0..<100 { lcg() }
値の推移を確認することが確認でき、アルゴリズムのチェックなどに役立ちそうです。
また、数値以外の文字列など全ての型でキャプチャリングすることが出来ます。
非同期処理の実行
Playgroundでは、そのままでは同期処理しか実行出来ませんが、「XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: Bool)」でtrueを設定することにより、非同期処理の実行も行えるようになります。
XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true) println("開始") let time1 = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * NSEC_PER_SEC)) let time2 = dispatch_time(DISPATCH_TIME_NOW, Int64(2 * NSEC_PER_SEC)) let time3 = dispatch_time(DISPATCH_TIME_NOW, Int64(3 * NSEC_PER_SEC)) dispatch_after(time1, dispatch_get_main_queue(), { () -> Void in println("1秒経過...") }) dispatch_after(time2, dispatch_get_main_queue(), { () ->Void in println("2秒経過...") }); dispatch_after(time3, dispatch_get_main_queue(), { () -> Void in println("3秒経過...") });
上記のコードでは、1秒毎にログを出力します。
class ValueTimer: NSObject { var value: Int = 0 var count: Int = 1 func start() { XCPCaptureValue("value timer", value) NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("timerFunction"), userInfo: nil, repeats: true) } func timerFunction() { value += count++ XCPCaptureValue("value timer", value) } } XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true) var timer = ValueTimer() timer.start()
もちろんタイマーも使えます。
XCPCaptureValueを使うことで、動的にグラフを描くことも出来ます。
Viewのライブレンダリング
XCPCaptureValueでもViewを表示する事が出来ますが、その時点でのViewの状態が表示されるだけです。
そのため、パラメータを変更し、それを反映させるには再度XCPCaptureValueを使って最新のViewを表示し直す必要があります。
そこで、「XCPShowView(identifier: String, view: UIView)」を使うと、指定したViewを監視しパラメータが変更された際に、最新の状態へ再描画するといったようなことが出来るようになります。
var view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) XCPShowView("live rendering", view) view.backgroundColor = UIColor.redColor() view.layer.borderColor = UIColor.blackColor().CGColor view.layer.borderWidth = 1.0 view.layer.cornerRadius = 5.0
XCPShowViewを使う際の注意点として、監視するViewにはsuperViewを設定してはいけません。
XCPShowViewで、監視されるViewが自動的にタイムライン上のウィンドウに貼り付けられるためです。
また、frameも先に決定する必要があり、後から変更すると正しく反映されません。
Playgroundでのアニメーション
先ほどのXCPShowViewを使うことで、CALayerやSpriteKitのアニメーションを確認することが出来ます。
しかし、残念なことにUIKit上つまりiOSプラットフォームでは、UIViewアニメーションはもちろんCALayerやSpriteKitを使ったアニメーションを正しく実行することが出来ません。
但し、Xcode6のリリースノートに既知のバグであることが記されているので、いずれiOSプラットフォームでもアニメーションが実行出来るようになると思います。
以下、プラットフォームをOS Xでの簡単なCALayerアニメーションを行った例です。
import Cocoa import XCPlayground class View: NSView { var subLayer: CALayer! func setup() { self.wantsLayer = true subLayer = CALayer() subLayer.frame = CGRect(x:0, y:0, width:50, height:50) subLayer.position = CGPoint(x: self.frame.size.width/2.0, y: self.frame.size.height/2.0) subLayer.backgroundColor = NSColor.redColor().CGColor self.layer?.addSublayer(subLayer) } func animate() { var animation = CABasicAnimation(keyPath:"transform") animation.fromValue = NSValue(CATransform3D: CATransform3DIdentity) animation.toValue = NSValue(CATransform3D: CATransform3DMakeScale(2.0, 2.0, 1.0)) animation.duration = 1.0 animation.autoreverses = true animation.delegate = self subLayer.addAnimation(animation, forKey: "transform") } override func animationDidStop(anim: CAAnimation!, finished flag: Bool) { animate() } } var view = View(frame: CGRect(x: 0, y: 0, width: 200, height: 200)) XCPShowView("animation", view) view.setup() view.animate()
色々試してみて
アルゴリズムの確認や、使ったことのないAPIを試すには良い環境かなと思います。
また、UI系の表示もサポートされていて、そういった確認をするのにも非常に便利です。
なにより、ビルドし直さなくてもすぐに結果が確認できるのが最高ですね!
[参考] WWDC2014 – Swift Playgrounds(https://developer.apple.com/videos/wwdc/2014/#408)
この記事を書いた人
- プライベートは趣味で忙しいLegend先輩 アプリチームではヒカセンの加入をお待ちしております
この投稿者の最近の記事
- iOS2020.06.03Xcode 11で始めるスペルチェック
- iOS2015.04.13[Swift] Xcode6.3に上げたらビルドが通らなかった話
- iOS2014.10.22Xcode6でiOS7対応アプリを作るときのワナ
- iOS2014.09.08[Swift]グラフもレンダリングもイケる!Playgroundが超絶便利!