Playground動手玩 (在OSx 10.9.3 、Xcode 6 beta環境下測試playground,只能用Swift語言)


0 本文的程序例子

  先說說代碼例子,文章最后面有個程序,直接將代碼拷貝到新建的playground文件中,就可以這樣展示和調試了

  

 

 

    普通的代碼編寫過程中直接就在右欄中顯示執行結果,點擊執行結果右邊有兩個小圖標,一個眼睛的圖標,可以直觀看到圖形或數值(當前狀態),另外一個是+號,可以回溯歷史數據和變量之間的相關性。 點擊+號就可以看到上面的蹺蹺板和變量執行圖,還有右下角的時間軸,可以手動拖放回滾。

 

 

 

  1、什么是playground?playground是Xcode的新的調試程序的一個工具,它提供靈活的數據展示方式,彌補了我們之前調試程序的手段的不足之處,它支持QuickLook多樣式調試顯示,不用添加測試代碼、也不用按Run執行程序,就可以直觀地查看運行情況,實時查看變量,可以直接查看的類型有:Color類型、String類型、Image類型、View類型、數據等等,可以自已開發動態展示的代碼(實現接口),使用XCPCaptureValue函數觀察和回溯動態過程。

  有什么情況不用playground ?游樂場雖好,但畢竟還是游樂場,目前它不支持界面交互,也就是說暫時無法在Playground上玩你實現的游戲。只能看不能動,還有就是無法直接執行你的App程序,畢竟它不是模擬器。

     

  2、playground有什么好處呢?從學習的用途上來說,它便於練習Swift,對初學編程的人來講更是有好處,不用整天按F6,F7,也不用等虛擬機運行程序看結果。對熟悉的開發者來講,它便於調試核心算法,測試一些涉及繪制的程序、圖像處理等一些又要看得見又不太方便用其他測試代碼做到的

    對使用開發環境的人來說,Playground有利於學習和嘗試各種API,因為你不用為此設立項目,帶着一個文件就可以到處跑

 

  3、 用個例子說明playground怎么用,我們直接上代碼吧,我從WWDC2014會上展示的內容好象沒有找到代碼下載,所以先從視頻上抄下一些代碼,動手測試一下。這些代碼只要直接拷到playground里面去就可以了,我們只要做幾個事情

    a、在文件頭引入 import XCPlayground,用於下文實現playground的一些接口

    b、實現func XCPCaptureValue<T>(identifier: String, value: T)用於顯示程序執行過程中的歷史數據,你可以用時間軸回滾,同時也看到變量與變量之間的關系。

    c、實現func XCPShowView(identifier: String, view: NSView),直接顯示程序的動態執行過程,兩個小孩在蹺蹺板上玩,然后你看到蹺蹺板變角度變量的歷史過程和實現手動操作回滾

 

代碼如下:

 import Cocoa

import QuartzCore

import XCPlayground

 class PlaygroundIconView:NSView {

    let backgroundLayer=CAShapeLayer()

    let seesawBaseLayer=CAShapeLayer()

    let seesawLayer=CAShapeLayer()

    init(){

        super.init(frame:NSRect(x:0,y:0,width:568,height:568))

        

        backgroundLayer.frame=self.bounds

        seesawBaseLayer.frame=NSRect(x:254,y:124,width:60,height:111)

        seesawLayer.frame=NSRect(x:40,y:197, width:488,height:30)

        

        setUpBackgroundLayer()

        setUpSeesawBaseLayer()

        setUpSeesawLayer()

        

        self.wantsLayer=true

        

        self.layer.addSublayer(backgroundLayer)

        self.layer.addSublayer(seesawBaseLayer)

        self.layer.addSublayer(seesawLayer)

    }

    

    func setUpBackgroundLayer(){

        let lineWidth=9.0

        let backgroundPath=NSBezierPath(roundedRect:NSInsetRect(bounds, lineWidth/2, lineWidth/2),xRadius:35.0,yRadius:35.0)

        backgroundPath.lineWidth=lineWidth

        

        backgroundLayer.strokeColor=NSColor.playgroundIconStrokeColor().CGColor

        backgroundLayer.fillColor=NSColor.playgroundIconFillColoer().CGColor

        backgroundLayer.lineWidth=lineWidth

        

        backgroundLayer.path=CGPathFromNSBezierPath(backgroundPath)

    }

    

    func setUpSeesawBaseLayer(){

     

        let seesawBasePath=NSBezierPath()

        

        

        let rectHeight:Int=50;

        

        

        seesawBasePath.moveToPoint(NSPoint(x:0,y:rectHeight))

        seesawBasePath.lineToPoint(NSPoint(x:seesawBaseLayer.bounds.width/2,y:seesawBaseLayer.bounds.height))

        seesawBasePath.lineToPoint(NSPoint(x:seesawBaseLayer.bounds.width,y:50))

         seesawBaseLayer.fillColor=NSColor.whiteColor().CGColor

        seesawBaseLayer.path=CGPathFromNSBezierPath(seesawBasePath)

    }

    

    func setUpSeesawLayer(){

       

        let createChildLayer:()->CAShapeLayer={

            let childLayer=CAShapeLayer()

            let headPath=NSBezierPath(ovalInRect:NSRect(x:60,y:150,width:49,height:49))

            

            let bodyPath=NSBezierPath()

            

            bodyPath.moveToPoint(NSPoint(x:58,y:155))

            bodyPath.lineToPoint(NSPoint(x:88,y:140))

            bodyPath.lineToPoint(NSPoint(x:126,y:100))

            

            bodyPath.lineToPoint(NSPoint(x:120,y:90))

            

            bodyPath.lineToPoint(NSPoint(x:125,y:71))

            

            bodyPath.lineToPoint(NSPoint(x:113,y:71))

            

            bodyPath.lineToPoint(NSPoint(x:112,y:94))

            bodyPath.lineToPoint(NSPoint(x:83,y:113))

            bodyPath.lineToPoint(NSPoint(x:68,y:94))

            

            bodyPath.lineToPoint(NSPoint(x:97,y:70))

            

            bodyPath.lineToPoint(NSPoint(x:122,y:12))

                

            bodyPath.lineToPoint(NSPoint(x:98,y:0))

            

            bodyPath.lineToPoint(NSPoint(x:64,y:41))

            

            bodyPath.lineToPoint(NSPoint(x:7,y:71))

            

            bodyPath.lineToPoint(NSPoint(x:0,y:94))

            

            bodyPath.moveToPoint(NSPoint(x:58,y:155))

            

            let childPath=NSBezierPath()

            

            childPath.appendBezierPath(headPath)

            childPath.appendBezierPath(bodyPath)

            

            childLayer.fillColor=NSColor.whiteColor().CGColor

            childLayer.path=CGPathFromNSBezierPath(childPath)

            

            return childLayer

        }

    

    

    let leftChildLayer = createChildLayer()

    let rightChildLayer = createChildLayer()

    

    rightChildLayer.transform=CATransform3DMakeRotation(M_PI,0.0,0.0,1.0)

    rightChildLayer.geometryFlipped=true

 

    let benchLayer = CALayer()

    

    benchLayer.frame=NSRect(x:0,y:41,width:self.seesawLayer.bounds.width,height:30)

    

    benchLayer.backgroundColor=NSColor.whiteColor().CGColor

    

    leftChildLayer.frame=NSRect(x:25,y:0,width:126,height:200)

    rightChildLayer.frame=NSRect(x:488-(126+25),y:0,width:126,height:200)

    

    seesawLayer.addSublayer(leftChildLayer)

    seesawLayer.addSublayer(rightChildLayer)

    seesawLayer.addSublayer(benchLayer)

    

    seesawLayer.delegate=self

    }

    

    let maxSeesawAngle=M_PI / 12

    

    var currentSeesawAngle = 0.0

    

    var animate:Bool = false{

        

    didSet(oldAnimate){

        if animate != oldAnimate && animate {

            if currentSeesawAngle == 0  {

                

                //@Bailey

                //設置捕捉動態記錄和顯示的參數

                XCPCaptureValue("Left Seesaw Position",0 )

                 animateSeesawToAngle(maxSeesawAngle,duration: 0.75)

            }

            else

            {

               animateSeesawToAngle(currentSeesawAngle * -1)

            }

        }

    }

    }

    

    func animateSeesawToAngle(angle:CGFloat,duration:CFTimeInterval = 1.5 )-> CAAnimation{

        let angleAnimation = CABasicAnimation(keyPath:"transform")

        angleAnimation.fromValue=NSValue(CATransform3D:seesawLayer.transform)

        

        angleAnimation.toValue=NSValue(CATransform3D:CATransform3DMakeRotation(angle, 0.0, 0.0, 1.0))

        

        angleAnimation.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)

        

        angleAnimation.duration = duration

        angleAnimation.delegate=self

        seesawLayer.addAnimation(

            angleAnimation, forKey: "transform")

        

        seesawLayer.transform=CATransform3DMakeRotation(angle,0.0, 0.0, 1.0)

        currentSeesawAngle=angle

        return angleAnimation

        

    }

    

    override func animationDidStop(_:CAAnimation!,finished:Bool){

        if finished && animate {

            

            //@Bailey

            //設置捕捉動態記錄和顯示的參數

            XCPCaptureValue("Left Seesaw Position",-currentSeesawAngle )

            animateSeesawToAngle(currentSeesawAngle * -1)

        }

    }

}

 

extension NSColor {

    class func playgroundIconFillColoer()->NSColor{

        return NSColor(red:12/255,green:65/255,blue:135/255,alpha:1.0)

    }

    class func playgroundIconStrokeColor()->NSColor{

        return NSColor(red:9/255,green:44/255,blue:91/255,alpha:1.0)

    }

}

 

func CGPathFromNSBezierPath(nsPath:NSBezierPath)->CGPath! {

    if nsPath.elementCount==0{

        return nil

    }

    

    let path=CGPathCreateMutable()

    var didClosePath=false

    for i in 0..nsPath.elementCount{

        var points=NSPoint[](count:3,repeatedValue:NSZeroPoint)

        

        switch nsPath.elementAtIndex(i, associatedPoints: &points){

        case .MoveToBezierPathElement:

            CGPathMoveToPoint(path,nil,points[0].x,points[0].y)

            

        case .LineToBezierPathElement:

            CGPathAddLineToPoint(path, nil, points[0].x, points[0].y)

            

        case .CurveToBezierPathElement:

            CGPathAddCurveToPoint(path,nil, points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y)

        case .ClosePathBezierPathElement:

            CGPathCloseSubpath(path)

            didClosePath=true

         }

    }

    if !didClosePath{

        CGPathCloseSubpath(path)

    }

    return CGPathCreateCopy(path)

}

 

let view=PlaygroundIconView()

 

view.animate=true

 

//@Bailey

//顯示游樂場蹺蹺板動態圖標以及時間軸用於程序計算回溯

XCPShowView("20140605",view)

 

view

 

 

 

 

 

 

 

 

 

 

//修正程序以適應新swift的語法 ,在 xcode 6.1 下運行

 

 

 

 

 

 

 

 

 

import Cocoa

import Foundation

import QuartzCore

import XCPlayground

import SpriteKit

 

 class PlaygroundIconView:NSView {

    let backgroundLayer=CAShapeLayer()

    let seesawBaseLayer=CAShapeLayer()

    let seesawLayer=CAShapeLayer()

    required init?(coder: NSCoder){

        super.init(frame:NSRect(x:0,y:0,width:568,height:568))

        backgroundLayer.frame=self.bounds

        seesawBaseLayer.frame=NSRect(x:254,y:124,width:60,height:111)

        seesawLayer.frame=NSRect(x:40,y:197, width:488,height:30)

        setUpBackgroundLayer()

        setUpSeesawBaseLayer()

        setUpSeesawLayer()

        self.wantsLayer=true

        self.layer?.addSublayer(backgroundLayer)

        self.layer?.addSublayer(seesawBaseLayer)

        self.layer?.addSublayer(seesawLayer)

    }

    

    func setUpBackgroundLayer(){

        let lineWidth=9.0

        let backgroundPath=NSBezierPath(roundedRect:NSInsetRect(bounds, CGFloat(lineWidth/2), CGFloat(lineWidth/2)),xRadius:35.0,yRadius:35.0)

        backgroundPath.lineWidth=CGFloat(lineWidth)

        backgroundLayer.strokeColor=NSColor.playgroundIconStrokeColor().CGColor

        backgroundLayer.fillColor=NSColor.playgroundIconFillColoer().CGColor

        backgroundLayer.lineWidth=CGFloat(lineWidth)

        backgroundLayer.path=CGPathFromNSBezierPath(backgroundPath)

    }

    

    func setUpSeesawBaseLayer(){

        let seesawBasePath=NSBezierPath()

        let rectHeight:Int=50;

        seesawBasePath.moveToPoint(NSPoint(x:0,y:rectHeight))

        seesawBasePath.lineToPoint(NSPoint(x:seesawBaseLayer.bounds.width/2,y:seesawBaseLayer.bounds.height))

        seesawBasePath.lineToPoint(NSPoint(x:seesawBaseLayer.bounds.width,y:50))

        seesawBaseLayer.fillColor=NSColor.whiteColor().CGColor

        seesawBaseLayer.path=CGPathFromNSBezierPath(seesawBasePath)

    }

    

    func setUpSeesawLayer(){

        let createChildLayer:()->CAShapeLayer={

        let childLayer=CAShapeLayer()

        let headPath=NSBezierPath(ovalInRect:NSRect(x:60,y:150,width:49,height:49))

        let bodyPath=NSBezierPath()

        bodyPath.moveToPoint(NSPoint(x:58,y:155))

        bodyPath.lineToPoint(NSPoint(x:88,y:140))

        bodyPath.lineToPoint(NSPoint(x:126,y:100))

        bodyPath.lineToPoint(NSPoint(x:120,y:90))

        bodyPath.lineToPoint(NSPoint(x:125,y:71))

        bodyPath.lineToPoint(NSPoint(x:113,y:71))

        bodyPath.lineToPoint(NSPoint(x:112,y:94))

        bodyPath.lineToPoint(NSPoint(x:83,y:113))

        bodyPath.lineToPoint(NSPoint(x:68,y:94))

        bodyPath.lineToPoint(NSPoint(x:97,y:70))

        bodyPath.lineToPoint(NSPoint(x:122,y:12))

        bodyPath.lineToPoint(NSPoint(x:98,y:0))

        bodyPath.lineToPoint(NSPoint(x:64,y:41))

        bodyPath.lineToPoint(NSPoint(x:7,y:71))

        bodyPath.lineToPoint(NSPoint(x:0,y:94))

        bodyPath.moveToPoint(NSPoint(x:58,y:155))

        

        let childPath=NSBezierPath()

        childPath.appendBezierPath(headPath)

        childPath.appendBezierPath(bodyPath)

        childLayer.fillColor=NSColor.whiteColor().CGColor

        childLayer.path=CGPathFromNSBezierPath(childPath)

        

        return childLayer

        }

        

        let leftChildLayer = createChildLayer()

        let rightChildLayer = createChildLayer()

        rightChildLayer.transform=CATransform3DMakeRotation(CGFloat(M_PI),0.0,0.0,1.0)

        rightChildLayer.geometryFlipped=true

        let benchLayer = CALayer()

        benchLayer.frame=NSRect(x:0,y:41,width:self.seesawLayer.bounds.width,height:30)

        benchLayer.backgroundColor=NSColor.whiteColor().CGColor

        leftChildLayer.frame=NSRect(x:25,y:0,width:126,height:200)

        rightChildLayer.frame=NSRect(x:488-(126+25),y:0,width:126,height:200)

        seesawLayer.addSublayer(leftChildLayer)

        seesawLayer.addSublayer(rightChildLayer)

        seesawLayer.addSublayer(benchLayer)

        seesawLayer.delegate=self

    }

    let maxSeesawAngle=M_PI / 12

    var currentSeesawAngle = 0.0

    var animate:Bool = false{

    

    didSet(oldAnimate){

            if animate != oldAnimate && animate {

                if currentSeesawAngle == 0  {

                    //@Bailey

                    //設置捕捉動態記錄和顯示的參數

                    XCPCaptureValue("Left Seesaw Position",0 )

                    animateSeesawToAngle(CGFloat(maxSeesawAngle),duration: 0.75)

                }

                else

                {

                    animateSeesawToAngle(CGFloat(currentSeesawAngle * -1))

                }

            }

        }

    }

    

    func animateSeesawToAngle(angle:CGFloat,duration:CFTimeInterval = 1.5 )-> CAAnimation{

        let angleAnimation = CABasicAnimation(keyPath:"transform")

        angleAnimation.fromValue=NSValue(CATransform3D:seesawLayer.transform)

        angleAnimation.toValue=NSValue(CATransform3D:CATransform3DMakeRotation(angle, 0.0, 0.0, 1.0))

        angleAnimation.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)

        angleAnimation.duration = duration

        angleAnimation.delegate=self

        seesawLayer.addAnimation(

            angleAnimation, forKey: "transform")

        seesawLayer.transform=CATransform3DMakeRotation(angle,0.0, 0.0, 1.0)

        currentSeesawAngle=Double(angle)  //tag

        return angleAnimation

    }

    

    override func animationDidStop(_:CAAnimation!,finished:Bool){

        if finished && animate {

            //@Bailey

            //設置捕捉動態記錄和顯示的參數

            XCPCaptureValue("Left Seesaw Position",-currentSeesawAngle )

            animateSeesawToAngle( CGFloat(currentSeesawAngle * -1)  )

        }

    }

 }

 

 extension NSColor {

    class func playgroundIconFillColoer()->NSColor{

        return NSColor(red:12/255,green:65/255,blue:135/255,alpha:1.0)

    }

    

    class func playgroundIconStrokeColor()->NSColor{

        return NSColor(red:9/255,green:44/255,blue:91/255,alpha:1.0)

    }

 }

 

 func CGPathFromNSBezierPath(nsPath:NSBezierPath)->CGPath! {

    if nsPath.elementCount==0{

        return nil

    }

    let path=CGPathCreateMutable()

    var didClosePath=false

    for i in 0..<nsPath.elementCount{

        var points=[NSPoint](count:3,repeatedValue:NSZeroPoint)

        switch nsPath.elementAtIndex(i, associatedPoints: &points){

        case .MoveToBezierPathElement:

            CGPathMoveToPoint(path,nil,points[0].x,points[0].y)

        case .LineToBezierPathElement:

            CGPathAddLineToPoint(path, nil, points[0].x, points[0].y)

        case .CurveToBezierPathElement:

            CGPathAddCurveToPoint(path,nil, points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y)

        case .ClosePathBezierPathElement:

            CGPathCloseSubpath(path)

            didClosePath=true

        }

    }

    if !didClosePath{

        CGPathCloseSubpath(path)

    }

    return CGPathCreateCopy(path)

 }

 

 let view=PlaygroundIconView(coder: NSCoder())

 

 view?.animate=true

 

 //@Bailey

 //顯示游樂場蹺蹺板動態圖標以及時間軸用於程序計算回溯

 XCPShowView("20140605",view!)

 view

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM