[swift2.1] Xcode7.1 Playground 변경사항

Swift 2015. 10. 27. 21:19

Xcode7.1 에서 변경된 Playground 기능에 대해 알아보겠습니다.


1. 파일, 이미지, 컬러를 editor로 드래그해서 객체 리터럴을 생성할 수 있습니다.

  • 리터럴은 플랫폼 특정 타입으로 아래와 같이 변환됩니다.
  • Color 리터럴 -> NSColor 또는 UIColor
  • File 리터럴 -> NSURL
  • Image 리터럴 -> NSImage 또는 UIImage


이미지 리터럴

  • Resources 폴더에서 이미지 파일을 에디터로 드래그 하면 그림과 같은 리터럴 형태로 추가됩니다.

UIImage 객체의 imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) 메소드는 템플릿 형태로 렌더링 된 UIImage를 반환합니다. 검정-투명 으로만 이루어진 이미지에서 black 영역을 UIImageView 의 tintColor 속성을 사용해서 원하는 색으로 변경할수 있습니다.




컬러 리터럴

  • Editor > Insert Color Literal 메뉴를 선택하면 컬러 선택창이 나타나 컬러를 변경할 수 있습니다.




파일 리터럴

  • Resources 폴더의 파일을 드래그하면, 아래와 같이 파일 리터럴 형태로 추가됩니다.






2. XCPlayground 가 제공하는 API가 상당수 변경되었습니다.

  • API들이 전역함수에서 XCPlaygroundPage 클래스의 메소드 형태로 변경되었습니다.

API 변경사항으로 XCPCaptureValue, XCPShowView, XCPSetExecutionShouldContinueIndefinitely, XCPExecutionShouldContinueIndefinitely 함수와 XCPSharedDataDirectoryPath 전역상수는 deprecated 되었음. Xcode 이후 버전에서 제거될 예정.


1) 현재 페이지에 대한 참조는 XCPlaygroundPage.currentPage 를 사용합니다.

import XCPlayground

XCPlaygroundPage.currentPage 


2) 타임라인으로 값을 캡처하려면XCPlaygroundPage.captureValue(_:withIdentifier:) 을 사용합니다.

// XCPCaptureValue("식별자", value: i) : deprecated

for i in 1...10 {
    XCPlaygroundPage.currentPage.captureValue(i, withIdentifier: "식별자")
}  




3) 비동기 코드를 포함할 경우 XCPlaygroundPage.needsIndefiniteExecution 을 사용하세요.

  • XCPlaygroundPage.needsIndefiniteExecution 를 true로 설정하면, 실행흐름이 playground 파일 끝에 도달해도 실행을 중단하지 않고, 대기합니다.
// XCPSetExecutionShouldContinueIndefinitely(true) : deprecated

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true




4) XCPlaygroundPage.liveView 를 설정하면 타임라인에 노출됩니다.

  • liveView 속성에 nil이 아닌 값을 설정하면 .needsIndefiniteExecution 가 true 로 설정됩니다.
  • StackView 를 타임라인에 노출하는 예제입니다.

class StackView: UIView {
    var kElementHeight = CGFloat(50)
    var elements:[Int] = []

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.blackColor()
        super.layer.borderColor = UIColor.blueColor().CGColor
        super.layer.borderWidth = 1
        self.layout()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func layout() {
        self.subviews.map { $0.removeFromSuperview() }

        for i in 0..<self.elements.count {
            let value = self.elements[i]

            let elementLabel = UILabel(frame:CGRectZero)
            elementLabel.backgroundColor = UIColor.greenColor()
            elementLabel.text = "\(value)"
            elementLabel.textAlignment = NSTextAlignment.Center
            elementLabel.font = UIFont.systemFontOfSize(15)
            elementLabel.textColor = UIColor.whiteColor()
            self.addSubview(elementLabel)

            elementLabel.frame = CGRectMake(8, self.frame.size.height-(8+kElementHeight)*CGFloat(i+1), self.frame.size.width-8*2, kElementHeight)
        }
    }

    func push(element:Int) {
        self.elements.append(element)
        self.layout()
    }
    func pop() -> Int? {
        if self.elements.count > 0 {
            let topElement = self.elements.removeLast()
            self.layout()
            return topElement
        } else {
            return nil
        }
    }
}

let bounds = CGRectMake(0, 0, 320, 400)
let view = UIView(frame: bounds)
view.backgroundColor = UIColor.whiteColor()

// liveView 속성을 설정하면, Timeline 에 표시됩니다.
// XCPlaygroundPage.currentPage.needsIndefiniteExecution = true 가 자동으로 설정됩니다.

XCPlaygroundPage.currentPage.liveView = view

let stackView = StackView(frame: CGRectInset(view.bounds, 30, 30))
view.addSubview(stackView)

stackView.push(1)
stackView.push(2)
stackView.push(3)  




5) NSURL 객체인 XCPlaygroundSharedDataDirectoryURL 전역상수가 추가되었습니다.

플랫폼 설정이 OS X 인 경우에만 유효한 상수입니다.

  • XCPlaygroundSharedDataDirectoryURL 는 playground 공유 데이터 디렉토리 경로를 나타냅니다.
  • OS X 에서는 ~/Document 경로에 Shared Playground Data 디렉토리를 수동으로 생성해야 합니다.
  • iOS 플랫폼에서는 playground 파일마다 경로가 다르기 때문에 데이터를 공유할 수 없습니다.






3. XCPlayground는 라이브 뷰로 뷰컨트롤러를 지원합니다.

LiveView 는 XCPlaygroundLiveViewable 프로토콜을 구현하는 객체입니다.

  • UIView, UIViewController 는 디폴트로 XCPlaygroundLiveViewable 프로토콜을 구현합니다.
  • XCPlaygroundLiveViewable 프로토콜 명세는 아래와 같습니다.
public protocol XCPlaygroundLiveViewable {
    public func playgroundLiveViewRepresentation() -> XCPlayground.XCPlaygroundLiveViewRepresentation
}

public enum XCPlaygroundLiveViewRepresentation {
    // 루트뷰를 갖지 않는 최상위뷰 
    case View(UIView)

    // 루트 뷰컨트롤러를 갖지 않는 최상위 뷰컨트롤러 
    case ViewController(UIViewController)
}
  • 위에서 구현했던 StackView 를 활용하여 네비게이션 컨트롤러를 라이브 뷰로 설정하는 예제입니다.
let stackView = StackView(frame: CGRectMake(0, 0, 200, 400))
stackView.push(1)
stackView.push(2)
stackView.push(3)

let contentViewController = UIViewController()
contentViewController.title = "StackView"
contentViewController.view.addSubview(stackView)

let liveViewController = UINavigationController(rootViewController: contentViewController)

XCPlaygroundPage.currentPage.liveView = liveViewController






4. XCPlaygroundPage.currentPage.finishExecution()를 호출해서 프로그래밍적으로 playground 실행을 중단 할 수 있습니다.

  • 이 메서드는 Xcode가 현재 playground 페이지 실행을 중단하도록 지시하여, 적절히 클린업을 수행하고 종료할 수 있도록 합니다.
XCPlaygroundPage.currentPage.finishExecution()




[swift] Swift 코딩환경 Playground

Swift 2015. 10. 5. 02:12

Playground는 xcode6 부터 지원된 인터랙티브한 swift 코딩환경입니다. 애플 공식문서에서는 Playground 를 다음과 같이 소개하고 있습니다.


  • 프로젝트 전체를 컴파일하지 않고도 코드를 실행하고 결과를 보여주는 인터랙티브한 스위프트 코딩환경.
  • Swift 언어를 학습하고, 앱의 일부분을 프로토타이핑하고, 다른 사람들을 위한 학습환경을 만드는데 활용가능.
  • 알고리즘과 시스템 API를 실험하고 커스텀뷰 구현이 가능함.
  • 학습결과에 리치 코멘트로 노트와 가이드 작성가능.


참고

  • 이글은 Playground_Help 문서를 참고하여 작성했습니다.
  • Playground_Help


1. Playground 에디터 구성

playground 에디터는 아래 그림과 같이 구성되어 있습니다.



  • Source editor 에 타이핑한 결과는 즉시 Results sidebar 에서 확인할수 있습니다.
  • Result sidebar의 Quick Look  버튼을 누르면 팝업으로 결과를 확인할수 있습니다. 



  • Result  버튼을 누르면 Source editor 영역에 결과를 인라인으로 삽입할 수 있습니다. 



  • Console 영역에는 print, NSLog 함수가 출력한 문자열을 확인할수 있습니다.

    View > Show Debug Area 메뉴를 통해 표시.



  • Timeline 영역은 XCPlayground 모듈의 렌더링 결과를 표시합니다.

    View > Assitant Editor > Show Assistant Editor 메뉴를 통해 표시. 



2. 결과뷰 Display 방식 변경하기

  • 인라인으로 삽입된 결과뷰의 Display 방식을 변경할 수 있습니다.
  • 삽입된 결과뷰를 선택하고 오른쪽 클릭을 하면 지원하는 display 방식을 표시합니다.

Lasest Value: 최종 결과만 표시.
Value History: 결과를 리스트로 출력.
Graph: 결과를 그래프로 출력.


3. 보조파일 추가하기

  • playground 파일의 Sources 폴더에 보조코드 파일을 추가 할수 있습니다.
  • Sources 폴더의 swift 파일들은 framework 로 미리 컴파일되어 메인 playground 파일에 module 로 자동으로 import 됩니다.
  • 주의할 점으로 playground 메인파일에서 접근할 수 있도록 클래스, 메서드, 함수, 변수, 프로토콜들은 public 으로 선언되어여야합니다.



4. 리소스 추가하기

  • playground 또는 page 에 이미지, 정적데이터 파일, 사운드와 같은 리소스를 포함할수 있습니다.



5. 커스텀 프레임워크 임포트

  • UIKit 과 같은 시스템 프레임워크 외에 커스텀 프레임워크의 import도 가능합니다.
  • 커스텀 프레임워크를 import 하기 위해서는 프로젝트와 playground 파일이 동일한 워크스페이스에 존재해야합니다.
  • 프로젝트의 워크스페이스가 존재하지 않으면 워크스페이스를 생성하고, playground 파일을 워크스페이스에 포함시킵니다.
  • playground 에서 접근하기 위해서 프로젝트의 클래스, 메서드, 함수, 변수, 프로토콜들은 public 으로 선언되어여야합니다.



6. UIView 렌더링 

  • playground의 멋진 기능 중의 하나로 UIView 를 구현하고 그 렌더링 결과를 확인할 수 있습니다.
let view = UIView(frame: CGRectMake(0,0,320,320))
view.backgroundColor = UIColor.magentaColor()

let label = UILabel(frame: CGRectMake(100, 100, 100, 30))
label.textAlignment = .Center
label.text = "Welcome!"
view.addSubview(label)

code 에 렌더링 결과를 삽입하거나, quick look 으로도 확인이 가능합니다.



7. 비동기 처리

  • playground는 디폴트로 위에서 아래로 코드를 실행하며 흐름을 종료합니다.
  • 비동기 api 통신의 경우 결과를 출력하지 못하고 바로 실행을 종료하게 됩니다.
  • XCPSetExecutionShouldContinueIndefinitely(true)를 상위해서 호출하면 비동기 요청이 완료할 때까지 playground 를 종료하지 않고 대기시킬 수 있습니다.
  • XCPSetExecutionShouldContinueIndefinitely 함수를 사용하려면 XCPlayground 프레임워크를 import 해야합니다.
import XCPlayground

// 비동기 처리하기 

XCPSetExecutionShouldContinueIndefinitely(true)

var imageSearch = "https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=girl"

let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
var task = session.dataTaskWithURL(NSURL(string: imageSearch)!) {
    (data:NSData?, response:NSURLResponse?, error:NSError?) in
    if let res = response as? NSHTTPURLResponse {
        print("\(res.statusCode)", terminator:"\n")
        print("\(res.allHeaderFields)", terminator:"\n")
    }
    if let data = data {
        if let json = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) {
            print("\(json)")
        }
    }
}
task.resume()


8. 마크다운 사용하기

  • 마크다운 문법을 지원하여 rich한 playground 문서를 작성할 수 있습니다.
  • 코드의 실행결과도 삽입할 수 있기 때문에 시각적인 컨텐츠를 작성할 수 있습니다.
  • swift 주석문 // 과 /* */ 구문에 콜론을 사용하면 마크다운 문법으로 인식합니다.
  • Editor > Show Rendered Markup 메뉴를 통해 마크다운 렌더링 결과를 확인할수 있습니다.
// 1. 마크다운 사용하기

//: This line will have **bold** and *italic* text.

/*:
## Headers of All Sizes

### Lists of Links

- [NSHipster](http://nshipster.com)
- [ASCIIwwdc](http://asciiwwdc.com)
- [SwiftDoc](http://swiftdoc.org)

### Images, Too

![Remote Image](http://nshipster.s3.amazonaws.com/alert.gif)


*Images in the Resources directory can be referenced locally*
*/

렌더링 결과를 확인해 볼까요?



8. 페이지 추가하기

  • playground에 페이지를 추가하여 모듈화된 학습환경을 만들 수 있습니다.

    File > New > Playground Page 메뉴.

  • Page 마다 Sources, Resources 폴더가 생성됩니다.
  • 가장 위의 Page 부터 빠른 순서를 갖으며, 페이지간 네비게이션을 추가할 때 의미를 가지게 됩니다.


9. 페이지간 네비게이션 추가하기

  • rich comment를 사용하여 페이지 간의 네비게이션을 추가할 수 있습니다.
  • 네비게이션은 rich comment 렌더링 모드에서 페이지 링크로 표시됩니다.
  • 3가지 종류의 네비게이션, 다음 페이지, 이전 페이지, 특정 페이지로 이동이 존재하며 아래와 같이 표현합니다.
// 다음 페이지로 이동하며, 마지막 페이지에서는 무시됩니다.
//: [Go to Next Page](@next)

// 이전 페이지로 이동하며, 첫 페이지에서는 무시됩니다.
//: [Go to Previous Page](@previous)

// 특정 페이지로 이동합니다. 공백은 %20으로 표기합니다.  
//: [Go to The End](Page%20Third)  
  • Page Second 에 네비게이션을 추가하고


  • 렌디링 모드에서 다음과 같은 결과를 확인할 수 있습니다.