검색결과 리스트
2015/10에 해당되는 글 6건
- 2015.10.27 [swift2.1] Xcode7.1 Playground 변경사항
- 2015.10.25 [swift2] Functor 와 Monad
- 2015.10.18 [swift2] 타입변환 연산자 (is, as, as?, as!)
- 2015.10.17 [아이폰] 글 목록
- 2015.10.16 [iOS9] 3D Touch 시작하기
- 2015.10.05 [swift] Swift 코딩환경 Playground
글
[swift2.1] Xcode7.1 Playground 변경사항
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' 카테고리의 다른 글
| [swift2] Currying 함수 (0) | 2015.11.25 |
|---|---|
| [swift2] Core Image Filter 예제 (0) | 2015.11.10 |
| [swift2.1] Xcode7.1 Playground 변경사항 (0) | 2015.10.27 |
| [swift2] Functor 와 Monad (0) | 2015.10.25 |
| [swift2] 타입변환 연산자 (is, as, as?, as!) (0) | 2015.10.18 |
| [swift] Swift 코딩환경 Playground (0) | 2015.10.05 |
설정
트랙백
댓글
글
[swift2] Functor 와 Monad
이 포스트는 아래 원문을 참고하여, Functor 와 Monad 에 대해 설명합니다.
1. Functor 란?
Functor 란 map 함수를 지원하는 컨테이너 타입입니다.
- Array 타입은 map 함수를 지원하기 때문에 Functor 입니다.
- Array 엘리먼트들을 2 배로 곱하는 예제를 살펴보겠습니다.
var doubledImperative:[Int] = [1, 2, 3]
for number in numbers {
doubledImperative.append(number * 2)
}
print(doubledImperative) // 2, 4, 6
- 단순히 루프문을 사용하여 배열 엘리먼트를 2배하여 새 배열에 담습니다.
Map
- map 함수를 사용하면 다음과 같이 처리할 수 있습니다.
let numbers = [1, 2, 3]
let doubledNumbers = numbers.map { $0*2 }
print(doubledNumbers) // 2, 4, 6
- 예제에서처럼, map 을 사용하면 Array 엘리먼트를 변환하는 작업의도를 더 명확하게 표현할 수 있습니다.
- 즉, 어떻게가 아닌 무엇을 달성하려는지 를 더 잘 표현합니다.
- 함수형 프로그래밍의 장점 중 하나라고도 할수 있습니다.
Optional도 map 적용이 가능한 컨테이너 타입입니다.
- map은 Array 뿐만 아니라 어떤 컨테이너 타입에도 구현할수 있는 고차원 함수입니다.
- 값이 있거나 또는 없음을 포장하는 Optional 타입도 해당합니다.
고차원 함수: 파라미터 또는 반환값으로 함수를 전달할수 있는 함수.
let number:Int? = 815 // Optional(815)과 동일함
let transformedNumber = number.map{ $0*2 }.map{ $0%2 == 0 }
print(nilNumber.map{ $0*2 }.map{ $0%2 == 0 }) // Optional(true)
Optional.map 은 우리를 대신에 nil 을 처리해줍니다.
- Optional 타입에 map을 사용했을 때 장점은 우리를 대신해 nil 값을 처리준다는 것입니다.
- 원래 값이 nil 이었다면 map을 적용해도 nil을 반환합니다.
- 이로인해 연산의 중간과정에서 중첩된 if let을 사용해야하는 번거로움을 피할수 있습니다.
// 원래값이 nil인 경우
let nilNumber:Int? = nil
let transformedNilNumber = nilNumber.map{ $0*2 }.map{ $0%2 == 0 }
print(transformedNilNumber) // nil
- map을 사용하지 않았다면 다음과 같이 처리했을 것입니다.
let nilNumber:Int? = nil
var result = false
if let number = nilNumber {
result = ((number*2) % 2) == 0
}
print(result)
컨테이너 타입에 따라 map은 조금 다르게 동작합니다.
- map은 컨테이너 타입에 따라, 의미적으로 조금 다르게 동작한다는 것을 알 수 있습니다.
- T 타입의 값을 포함하는 컨테이너 타입을 구현할 때, map 메서드의 일반적인 시그니처는 다음과 같습니다.
func map<U>(transformFunction: T -> U) -> Container<U>
- T 는 현재 컨테이너가 포함하는 엘리먼트 타입.
- U 는 반환될 컨테이너의 엘리먼트 타입.
커스텀 컨테이너 Container 구조체에 map을 구현해보겠습니다.
- 예제로, Container 라는 커스텀 컨테이너 타입을 구현해보겠습니다.
struct Container<T> {
var value:T
func map<U>(transform: T -> U) -> Container<U> {
let newContainer = Container<U>(value: transform(self.value))
return newContainer
}
}
- 우리는 T 타입을 파라미터로 받아, U 타입을 반환하는 함수(transform)를 map 에 제공합니다.
- map은 내부값에 변환함수를 적용하고 교체된 값을 갖는 다른 컨테이너 인스턴스를 생성하여 반환합니다.
- 아래와 같이 사용할 수 있습니다.
var container = Container<Int>(value: 5)
var resultContainer = container.map { "\($0 * 10)" }
print(resultContainer.value) // "50"
또다른 커스텀 컨테이너 Result 타입을 구현해봅시다.
- Result enum 은 요즘 오픈소스 swift 코드에서 많이 볼수 있는 패턴입니다.
enum Result<T> {
case Value(T)
case Error(NSError)
}
- 몇몇 프로그래밍 언어에서 Either 라고 알려진 타입의 구현입니다.
- case Error 연관값은 제네릭 대신 NSError 타입으로 연산의 결과를 보고하는데 사용합니다.
- 개념적으로 Result는 값이 있을 수도 있고, 없을 수도 있는 임의의 타입의 값을 포장하는 Optional과 유사합니다.
- 이 경우에는 추가적으로 왜 그 값이 없는지도(NSError) 알려줍니다.
- 아래와 같이 파일에서 컨텐츠를 읽고 Result 객체로 반환하는 함수를 구현해보겠습니다.
func dataWithContentsOfFile(file:String, encoding:NSStringEncoding) -> Result<NSData> {
do {
let data = try NSData(contentsOfFile: NSBundle.mainBundle().pathForResource(file, ofType: nil)!, options: NSDataReadingOptions.DataReadingMapped)
return Result.Value(data)
} catch {
return Result.Error(error as NSError)
}
}
- 이 함수는 NSData 값을 담은 Result.Value를 반환하거나, (파일을 읽을 수 없는 경우에는) NSError를 갖는 Result.Error를 반환합니다.
텍스트 파일을 읽어 대문자로 변환하는 작업을 구현해봅시다.
var stringContents:String?
switch data {
case let .Value(value):
stringContents = NSString(data: value, encoding: NSUTF8StringEncoding) as? String
case let .Error(error):
break
}
let uppercasedContents:String? = stringContents?.uppercaseString
- 매 단계마다 값이 있는지 검색해야 하기 때문에, 중첩된 if let 와 switch 문을 사용하게 됩니다.
map을 사용하면 이렇게 처리할 수 있습니다.
- NSData 를 받아서, String 으로 변환하고, 그리고 다시 대문자로(String) 변경하는 과정을 수행합니다.
NSData -> String -> String
- 일련의 map 변환을 적용하여 아래와 같이 처리할 수 있습니다. (map의 구현에 대해서는 아래에서 다룹니다.)
let data:Result<NSData> = dataWithContentsOfFile("test.txt", encoding: NSUTF8StringEncoding)
let uppercaseContents:Result<String> = data.map { NSString(data: $0, encoding: NSUTF8StringEncoding)! }.map { $0.uppercaseString }
- Array 에 map을 적용했던 이전 예제와 유사하게 이 코드는 훨씬더 의도가 명확합니다.
어떻게 Result.map 을 구현했을까요?
extension Result {
func map<U>(f: T -> U) -> Result<U> {
switch self {
case let .Value(value):
return Result<U>.Value(f(value))
case let .Error(error):
return Result<U>.Error(error)
}
}
}
- 변환함수 f는 타입 T (NSData)의 값을 받고, 타입 U (String)을 반환합니다.
- 값이 있으면 단순히 value를 파라미터로 f를 호출하고, 값이 없으면 동일한 error를 갖는 다른 Result.Error를 반환합니다.
- Result라는 껍질(컨테이너)이 포장하고 있는 알맹이에 f함수를 젹용한다고 생각하면 쉽게 이해할수 있을 것입니다.
요약하면
- Optional, Array 와 같은 컨테이너 타입에 구현된 map 함수가 무엇을 하는지 알아보았습니다.
- map 은 변환함수에 의해 변경된 값을 갖는 새 컨테이너를 반환합니다. (알맹이만 변경합니다.)
- Functor는 map 을 구현하는 타입입니다.
- Dictionary, 클로져와 같은 타입도 Functor 라고 할 수 있고, map 함수가 어떻게 동작하는지 대략 예측해볼 수 있습니다.
2. Optional 은 Monad 입니다.
- Monad는 값이 있을 수도 있고 없을 수도 있는 상태를 포장하는 타입입니다. (swift 에서는 Optional)
- Monad 는 Functor 의 한 유형입니다.
map 의 변환함수의 반환타입이 Result 라면 어떤일이 발생할까요?
- 위 예에서 변환함수를 다른 값으로 변환하는데 사용했습니다.
- 만일 변환함수가 새 Result 객체를 반환하게 되면 어떻게 될까요?
- 마찬가지로 변환함수가 새 Error 에러를 반환하면 어떻게 될까요?
- 먼저 map 함수 시그니처를 통해 알아봅시다.
func map<U>(f: T -> U) -> Result<U>
- T는 NSData 이고 U는 Result
입니다. 반환타입 Result를 시그니처에 대입해보면
func map(f: NSData -> Result<String>) -> Result<Result<String>>
- 반환 값에 Result 가 중첩 되었다는 것에 주목하세요. 우리가 원했던 결과는 아닙니다.
중첩된 Result를 받아 단순 Result로 flatten 하는 함수를 구현해봅시다.
extension Result {
static func flatten<T>(result:Result<Result<T>>) -> Result<T> {
switch result {
case let .Value(innerResult):
return innerResult
case let .Error(error):
return Result<T>.Error(error)
}
}
}
- flatten 함수는 중첩된 내부타입 T를 갖는 Result를 받아, 단순히 Value와 Error의 연관값을 추출해서 단일 Result
를 반환합니다. flatten 함수는 다른 문맥에서도 찾을수 있는데, 그중 하나로 배열의 배열을 일차원 배열로 flatten 하는 예입니다.
map, flatten 을 결합해서 우리의 Result
-> Result 변환에 적용해봅시다.
let stringResult = Result<String>.flatten(data.map { (data:NSData) -> (Result<String>) in
if let string = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
return Result<String>.Value(string)
} else {
return Result<String>.Error(NSError(domain: "error", code: -1, userInfo: nil))
}
})
일반적으로 map 함수에 flatten 과정을 적용해 flapMap 또는 flattenMap이라 불립니다.
extension Result {
func flapMap<U>(f:T -> Result<U>) -> Result<U> {
return Result.flatten(map(f))
}
}
Monad 타입은 flapMap 함수와 찰떡궁합 입니다.
- map이 동작하는 타입은 여기서 보았던 것과 유사한 시그니처를 갖는 flatMap 함수를 구현합니다.
- 다음에 Functor와 Monad라는 단어를 들으면 두려워하지 맙시다.
- Functor와 Monad는 단순히 컨테이너 타입에 적용할수 있는 공통 연산을 기술하기 위한 디자인 패턴입니다.
'Swift' 카테고리의 다른 글
| [swift2] Core Image Filter 예제 (0) | 2015.11.10 |
|---|---|
| [swift2.1] Xcode7.1 Playground 변경사항 (0) | 2015.10.27 |
| [swift2] Functor 와 Monad (0) | 2015.10.25 |
| [swift2] 타입변환 연산자 (is, as, as?, as!) (0) | 2015.10.18 |
| [swift] Swift 코딩환경 Playground (0) | 2015.10.05 |
| [swift2] Swift Guard (0) | 2015.09.11 |
설정
트랙백
댓글
글
[swift2] 타입변환 연산자 (is, as, as?, as!)
이 글은 애플 Language Reference 문서를 참고하여 작성하였습니다.
- 4개의 타입캐스팅 연산자가 있습니다.
- is 연산자, as 연산자, as? 연산자, as! 연산자.
is 연산자
- 런타임에 표현식이 특정 타입으로 다운캐스팅 될수 있는지 검사합니다.
- 특정 타입으로 다운캐스팅이 가능하면true, 그렇지 않으면 false를 반환합니다.
as 연산자
- 컴파일 타임에 업캐스팅 또는 브리징과 같이 타입변환이 항상 성공하는 경우에 타입변환을 수행합니다.
- 업캐스팅(upcasting)은 중간변수 없이 표현식을 타입의 수퍼타입 인스턴스처럼 사용할수 있게합니다.
func f(any: Any) { print("Function for Any") }
func f(int: Int) { print("Function for Int") }
let x = 10
f(x)
// "Function for Int" 출력
let y: Any = x
f(y)
// "Function for Any" 출력
f(x as Any)
// "Function for Any" 출력
- 브리징(bridging)은 새 인스턴스를 생서하지 않고도, String과 같은 표준라이브러리 타입 표현식을 NSString과 같은 파운데이션 타입으로 사용할 수 있게합니다.
as? 연산자
- 표현식을 특정타입으로 조건부 타입변환을 수행합니다.
- as? 연산자는 특정 타입의 옵셔널을 반환합니다.
- 타입변환이 성공하면 표현식의 값은 옵셔널 타입으로 랩핑되어 반환됩니다. 실패하면 nil을 반환합니다.
- 특정 타입으로 타입변환이 실패 또는 성공으로 보장되면 컴파일 타임 에러가 발생합니다.
as! 연산자
- 표현식을 특정 타입으로 강제 타입변환을 수행합니다.
- as! 연산자는 옵셔널 타입이 아닌 특정 타입의 값을 반환합니다.
- 타입변환이 실패하면, 런타임 에러가 발생합니다.
- x as! T 는 (x as? T)! 과 동일하게 동작합니다.
'Swift' 카테고리의 다른 글
| [swift2.1] Xcode7.1 Playground 변경사항 (0) | 2015.10.27 |
|---|---|
| [swift2] Functor 와 Monad (0) | 2015.10.25 |
| [swift2] 타입변환 연산자 (is, as, as?, as!) (0) | 2015.10.18 |
| [swift] Swift 코딩환경 Playground (0) | 2015.10.05 |
| [swift2] Swift Guard (0) | 2015.09.11 |
| [swift2] Swift2에서의 문자열(strings) (0) | 2015.09.02 |
설정
트랙백
댓글
글
[아이폰] 글 목록
UX
iOS 9
iOS 8
iOS 6
- [Mask 레이어 활용] 이미지 일부만 보여주기
- [iPhone] UIView 애니메이션과 코어 애니메이션(CoreAnimation)
- [iPhone] iOS6 회전 지원하기
- 애플리케이션 응답성 향상을 위해 동시성 사용하기
Notification
'아이폰 > 글 목록' 카테고리의 다른 글
| [아이폰] 글 목록 (0) | 2015.10.17 |
|---|
설정
트랙백
댓글
글
[iOS9] 3D Touch 시작하기
애플개발자 라이브러리 Getting Started With 3D Touch를 번역한 글입니다.
iOS 9부터 새 아이폰 모델들의 유저인터페이스에 3차원 개념이 도입되었습니다.
- 사용자는 앱 기능에 즉시 접근하기 위해 홈스크린 아이콘을 press 할수 있습니다.
- 앱 안에서는, 컨텐츠를 미리보기하거나 특정 기능에 대한 빠르게 접근하기 위해 뷰를 press 할수 있습니다.
샘플코드를 참고하려면, 다음 Xcode 프로젝트를 다운로드 하세요.
- ApplicationShortcuts: Using UIApplicationShortcutItem 예제는 홈스크린 정적, 동적 퀵액션(quick actions)을 설명합니다.
- ViewControllerPreviews: Using the UIViewController previewing APIs 는 퀵액션 뿐만아니라 peek(미리보기), pop(커밋)을 설명합니다.
- Touch Canvas: UITouch 클래스의 새로운 force 속성을 설명합니다.
홈스크린 퀵액션
사용자는 앱을 시작하기 위해 아이콘을 탭할 수 있고, 홈스크린을 편집하기 위해 앱아이콘을 터치 앤 홀드할수 있습니다. iPhone 6s, iPhone 6s Plus 에서는 앱 아이콘을 pressing 해서 퀵액션 집합을 볼수 있습니다. 사용자가 퀵액션을 선택하면 앱은 활성화되어 실행되고 app delegate는 퀵액션 메시지를 수신합니다.
가장 좋은 퀵액션은 사용자와 앱과의 인터랙션을 예측가능하게 합니다. iOS 9 SDK는 새 아이폰 모델에서 사용가능한 정적,동적 퀵액션을 정의하는 API들을 제공합니다.
- Info.plist 파일에 UIApplicationShortcutItems 배열의 정적 퀵액션을 정의하세요.
- UIApplicationShortcutItem 클래스 및 API와 함께 동적 퀵액션을 정의하세요. 앱의 shared UIApplication에 새로 추가된 shortcutItems 속성을 사용하여 동적퀵액션을 추가하세요.
두 타입의 퀵액션 모두 최대 두줄의 텍스트 라인과 옵셔널 아이콘을 노출합니다.
Peek 과 Pop
다양한 강도의 사용자 press 에 반응하도록 뷰컨트롤러들을 활성화할수 있습니다. 사용자가 더 깊이 press 할수록 3단계의 인터렉션이 처리됩니다.
- 1단계: 컨텐츠 preview 사용가능이 표시됨
- 2단계: 직접 수행할수 있는 옵션들(peek quick action)과 함께 preview가 보여짐(peek)
- 3단계: preview 에서 보여졌던 뷰로 네비게이션됨(pop)
peek과 pop를 적용하면 시스템이 다음단계 전환에 대한 압력의 강도를 결정합니다. 사용자는 Settings > Accessibility > 3D Touch 에서 전환에 대해 조정할수 있습니다.
Peek 가용유무 표시
- 가볍게 누르면, 주변 컨텐츠가 블러처리 되면서 추가컨텐츠 미리보기 가능함이 표시됩니다.
Peek
- 좀더 깊게 누르면, preview 로 전환됩니다. preview는 일반적으로 더 많은 컨텐츠를 보여주도록 구성됩니다.(그림은 메일앱)
- 사용자가 이 시점에 터치를 멈추면 peek 은 사라지고, 앱은 이전 상태로 되돌아갑니다.
- 대신 좀더 깊게 누르면, 시스템이 제공하는 pop 전환을 사용하여 preview가 네비게이션되고, pop 뷰는 앱 루트뷰를 채우고 네비게이션 백버튼이 노출됩니다. (마지막 단계의 pop view 사진은 표시하지 않았음)
Peek quick actions
- 터치를 멈추지 않고 preview 위쪽으로 스와이프하면, 시스템은 preview 와 연관있는 peek 퀵액션을 노출합니다.
- 각 peek 퀵액션은 앱에 대한 딥링크입니다.
- 일단 peek 퀵액션이 화면에 노출되면, 사용자가 터치를 멈추어도 preview 는 퀵액션을 탭 할때까지 화면에 남아있습니다.
웹뷰 내의 링크들에 대한 peek과 pop도 활성화 할수 있습니다. Web View Peek and Pop 를 참고하세요.
Force Properties
- iOS 9 부터 UITouch 클래스는 3D Touch 커스텀 구현을 지원하기 위한 2개의 새로운 속성인 force와 maximumPossibleForce 를 갖습니다.
- iOS 디바이스에 최초로, 이 속성들은 앱이 수신하는 UIEvent 객체안에서 터치압력을 탐지하고 반응할수 있게해줍니다.
- 터치의 force는 매우 동적인 범위를 갖으며 부동소수로 표현됩니다.
접근성과 3D Touch 휴먼인터페이스 가이드라인
- 모든 사용자가 앱의 피처에 접근할수 있도록 보장하기 위해서, 3D Touch 가용유무에 따라 코드를 브랜치하세요.
- Checking for 3D Touch Availability 를 참고하세요.
3D Touch 는 3D Touch 디바이스들, 그리고 활성화 되었을 때에만 사용가능합니다. iOS 9 에서 3D 터치는 기본으로 활성화되어 있으며 Setting > Accessibility > 3D Touch 메뉴에서 비활성화 할수 있습니다.
- 3D Touch 가 사용가능하면, 기능의 장점을 활용하세요. 사용가능하지 않다면, touch and hold 와 같은 대안을 제공하세요.
- 3D Touch 기능은 VoiceOver를 지원합니다. VoiceOver 를 배우려면, Accessibility Programming Guide for iOS 를 참고하세요.
- 3D Touch 와 함께 사용가능한 새로운 기능에 대한 가이드는 iOS Human Interface Guidelines 문서의 3D Touch 를 참고하세요.
개발환경
- Xcode7 은 3D Touch 개발을 지원합니다. Xcode의 모든 디버깅 기능은 새 기능을 구현하는데 사용할 수 있습니다.
- Xcode7과 함께 3D Touch 를 지원하는 디바이스 상에서 개발해야합니다. 시뮬레이터는 3D Touch를 지원하지 않습니다.
코드로 peek 과 pop 뷰컨트롤러들을 구현해야합니다. 인터페이스 빌더는 3D Touch 전환과 뷰컨트롤러들 설정에 대한 그래피컬한 지원을 하지 않습니다.
모든 기능을 모든 사용자들이 사용할수 있도록 3D Touch 활성화상태와 비활성상태 모두 테스트 해야합니다.
- 3D Touch 디바이스의 Settings > General > Accessibility > 3D Touch 메뉴에서 비활성화 할수 있습니다.
'아이폰' 카테고리의 다른 글
| [iOS9] 3D Touch 시작하기 (0) | 2015.10.16 |
|---|---|
| [iOS] 익스텐션 (Extension) (0) | 2015.08.18 |
| [iPhone] 아이폰앱 디자인 정석(TapWorthy) (1) | 2013.07.07 |
| [iPhone] 아이폰 앱 디자인 실수: 문맥에 대한 간과 (0) | 2013.02.16 |
| [iPhone] iOS6 회전 지원하기 (0) | 2013.01.25 |
| [iPhone] UIView 애니메이션과 코어 애니메이션(CoreAnimation) (0) | 2013.01.23 |
설정
트랙백
댓글
글
[swift] Swift 코딩환경 Playground
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

*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 에 네비게이션을 추가하고
- 렌디링 모드에서 다음과 같은 결과를 확인할 수 있습니다.
'Swift' 카테고리의 다른 글
| [swift2] Functor 와 Monad (0) | 2015.10.25 |
|---|---|
| [swift2] 타입변환 연산자 (is, as, as?, as!) (0) | 2015.10.18 |
| [swift] Swift 코딩환경 Playground (0) | 2015.10.05 |
| [swift2] Swift Guard (0) | 2015.09.11 |
| [swift2] Swift2에서의 문자열(strings) (0) | 2015.09.02 |
| [swift2] Xcode7 beta6 Swift 언어 변경사항 (0) | 2015.08.27 |