검색결과 리스트
Swift에 해당되는 글 32건
- 2015.10.05 [swift] Swift 코딩환경 Playground
- 2015.09.11 [swift2] Swift Guard
- 2015.09.03 Swift 글 목록
- 2015.09.02 [swift2] Swift2에서의 문자열(strings)
- 2015.08.27 [swift2] Xcode7 beta6 Swift 언어 변경사항
- 2015.08.14 [swift2] Xcode7 beta5 Swift 언어 변경사항
- 2015.08.06 [swift1.2] Swift 프로토콜 지향 프로그래밍
- 2015.08.01 [swift] 문자열과 문자 -1 (Strings and Characters)
- 2015.07.30 [swift2] Xcode7 beta4 Swift 언어 변경사항
- 2015.07.16 [swift] 성능향상 시키기 - 다이나믹 디스패치를 최소화
글
[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 |
설정
트랙백
댓글
글
[swift2] Swift Guard
Guard 문을 이해하기 쉽게 설명하고 있는 글을 발견하여 소개합니다. 원문을 조금 의역하고 예제를 수정했습니다.
원문: Swift's Guard
Swift2.0에 추가된 guard 구문은 멋집니다. 실 세계에서 가드가 하는 것과 같은 유사한 역할을 하지요. 학교 경비는 학교에 소속된 학생들만 교문을 입장하도록 허용합니다. 소속되지 않는 학생이 들어오려고 하면, 저지하고 되돌려 보냅니다. guard 문은 뒤따르는 조건이 충족되지 않을 경우, 로직실행을 멈추고 함수를 반환합니다.
guard 문의 사용법에 대해 몇가지 알아보겠습니다.
1. 함수안에서 Guard
- 함수 안에서 guard 문은 올바른 입력에 대해서만 함수의 실행을 허용합니다.
func guardInFunction(string: String?) {
guard string != nil else { return }
print(string!, "second param", separator: " ", terminator: "\n")
}
guardInFunction("test")
guardInFunction(nil)
위 함수는 nil 입력을 가드합니다. 만일 입력이 nil이면 guard문은 else 절을 수행하고 다른 구문이 수행되기 전에 함수를 return합니다.
2. 옵셔널 바인딩(Optional Binding)
옵셔널 바인딩을 guard문과 조합하여 사용하면, 이전의 코드를 다음과 같이 재작성 할 수 있습니다.
func guardWithOptionalBinding(string: String?) {
guard let letString = string else { return }
print(letString, "second param", separator: " ", terminator: "\n")
}
guardWithOptionalBinding("test")
인자 string이 nil이면 else 절을 수행하고 그렇지 않으면 함수는 정상흐름을 계속하고, string을 출력합니다. if-let 문법을 사용한 옵셔널 바인딩을 사용해봤다면 무엇인가 다르다는 것을 느낄수 있을 것입니다. 옵셔널 바인딩된 상수를 조건문 범위 바깥에서도 사용할 수 있습니다. if-let의 경우에는 if문 조건을 만족하는 경우 if 블럭 내부에서만 사용할 수 있습니다.
guard 문의 경우에 조건이 true이면, 상수의 사용범위는 함수의 나머지 영역이 됩니다. guard문 이후 어디에서라도 사용할수 있습니다.
3. 복합 옵셔널 바인딩(Compound Optional Binding)
다음 예제처럼 복합해서 옵셔널 바인딩을 사용할 수 있습니다. 모든 파라미터가 nil이 아닐경우에 조건을 충족하고 출력문을 수행할 수 있습니다.
func guardWithCompoundOptionalBinding(firstName: String?, lastName:String?, dateOfBirth:String?, country:String? ) {
guard let fname = firstName, let lname = lastName, let dob = dateOfBirth, let cnt = country else { return }
print("\(fname) \(lname) \(dob) \(cnt)", separator: "", terminator: "\n")
}
guardWithCompoundOptionalBinding("sungbae", lastName: "kim", dateOfBirth: "", country: "korea")
4. 제어흐름 이동(Transferring Control)
위 예제에서 주목할 만한 것은, 조건이 충족되지 않으면 함수로부터 반환되는 것입니다. 이것은 guard 문이 조건을 만족하지 않으면 제어흐름의 이동시키는 구문을 가져야 하기 때문입니다. 위 예제에서 우리는 return문을 사용했습니다. 루프의 경우에는 continue와 break를 사용할 수 있습니다. 또한 우리는 error를 throw 할 수 있습니다. 예제를 보겠습니다.
func guardTransferringControl() {
var strings:Array<String> = ["Safe", "Coding", "why", "using", "guard", "statement"]
for string in strings {
guard string != "why" else {
continue
}
print("string", separator: "", terminator: "\n")
}
}
guardTransferringControl()
조건문을 만족하지 않으면, else 구문에서 제어흐름을 이동시키기 위해 continue를 사용했습니다.
이것이 guard 문이 하는 일입니다.
'Swift' 카테고리의 다른 글
| [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 |
| [swift2] Xcode7 beta5 Swift 언어 변경사항 (0) | 2015.08.14 |
설정
트랙백
댓글
글
Swift 글 목록
Xcode7.3 Release Notes
Swift 소개
Swift의 기초
- [swift] Swift 기초 - 1
- [swift] Swift 기초 - 2
- [swift] Swift 기초 - 3
- [swift] Swift 기초 - 4
- [swift2] 타입변환 연산자 (is, as, as?, as!)
- [swift2] 키워드로 보는 Swift
- [swift2.1] Array와 Dictionary 기초
Playground
String
- [swift] 문자열과 문자 -1 (Strings and Characters)
- [swift] 문자열 Indexing과 Slicing
- [swift2] Swift2에서의 문자열(strings)
Error Handling
Protocol Oriented Programming
- [swift1.2] Swift 프로토콜 지향 프로그래밍 1
- [swift2.1] Swift 프로토콜 지향 프로그래밍 2
- [swift2] 타입의 텍스트적인 표현 커스터마이징하기
- [swift] Map, Filter, Reduce
Performance
Functional Programming
Swift로 앱만들기
Xcode7 beta Release Notes
- [swift2] Xcode7 beta6 Swift 언어 변경사항
- [swift2] Xcode7 beta5 Swift 언어 변경사항
- [swift2] Xcode7 beta4 Swift 언어 변경사항
- [swift2] Xcode7 beta3 Swift 언어 변경사항
- [swift2] Xcode7 beta2 Swift 언어 변경사항
'Swift > 글 목록' 카테고리의 다른 글
| Swift 글 목록 (0) | 2015.09.03 |
|---|
설정
트랙백
댓글
글
[swift2] Swift2에서의 문자열(strings)
다음 포스트는 애플 공식 Swift 블로그의 Strings in Swift2 포스트를 번역했습니다.
Swift는 표준 라이브러리의 일부분으로, 성능이 뛰어나고 유니코드와 호환되는 String 구현을 제공합니다. Swift2에서, String 타입은 더이상 CollectionType 프로토콜을 구현하지 않습니다. (이전에는 String은 배열과 유사한 Character 값의 컬렉션이었습니다.) 이제 String은 character 컬렉션을 제공하는 characters 프로퍼티를 제공합니다.
무엇이 바뀌었을까요?
문자들의 컬렉션이 자연스러운 모델이지만, String 타입은 Array, Set, Ditionary와 같은 컬렉션 타입과 꽤 다르게 동작합니다. Swift2에서 프로토콜 extension이 추가되면서 몇몇 변경사항이 생겼습니다.
부분의 합과 다릅니다.
컬렉션에 엘리먼트를 추가하면, 컬렉션은 그 엘리먼트를 포함할 것이라 기대할수 있습니다. 즉 배열에 값을 추가하면, 배열은 그 값을 포함합니다. 동일한 규칙이 dictionary와 Set에도 적용됩니다. 그러나 string에 결합마크 문자를 추가하면 string 자체의 내용이 변합니다.
4개의 문자를 갖는 문자열 cafe를 예를 들어보겠습니다.
var letters: [Character] = ["c", "a", "f", "e"]
var string: String = String(letters)
print(letters.count) // 4
print(string) // cafe
print(string.characters.count) // 4
만일 악센트 문자 U+0301 ´를 결합하면, 문자열은 그대로 4글자 이지만 마지막 문자는 이제 é 입니다.
let acuteAccent: Character = "\u{0301}" // ´ COMBINING ACUTE ACCENT' (U+0301)
string.append(acuteAccent)
print(string.characters.count) // 4
print(string.characters.last!) // é
string의 characters 속성은 오리지널 소문자 e를 포함하지도 않고, 이전에 추가됐던 악센트 문자 ´도 포함하지 않습니다. string은 이제 악센트가 붙은 소문자 "e" 즉 é를 포함합니다.
string.characters.contains("e") // false
string.characters.contains("´") // false
string.characters.contains("é") // true
만일 다른 컬렉션처럼 string을 다룬다면 결과는 Set에 UIColor.redColor() 과 UIColor.greenColor()를 추가하면 set은 UIColor.yellowColor() 포함한다고 리포트하는 것만큼 놀라울 것입니다.
문자의 내용에 따라 결정됩니다.
string과 collection의 또 다른 차이점은 동등성을 판단하는 방법입니다.
- 두 배열은 엘리먼트의 개수가 같고, 대응하는 인덱스에 각 엘리먼트 쌍이 동일하면 동등합니다.
- 두 집합은 엘리먼트의 개수가 같고, 첫 번째 집합에 포함된 각 엘리먼트가 두 번째 집합에도 포함되어 있을때 동등합니다.
- 두 사전은 같은 키,값 쌍을 가지고 있을때 동일합니다.
그러나 String은 canonically equivalent 에 기초하여 동등성이 결정됩니다. 문자는 같은 언어적 의미와 외형을 가진다면 다른 유니코드 스칼라로 구성되어 있다하더라도 cannonically 동등합니다.
canonically equivalent: 유니코드 문자 인코딩 표준에 정의된 스펙. 코드포인트 순서집합이 출력되었을 때, 같은 외형과 의미를 갖을때 canonically equivalent 하다고 표현합니다.
자음과 모음을 나타내는 24개의 문자로 구성된 한국어 표기법을 예로 들어보겠습니다. 표기할때 각 문자들은 각 음절이 결합하여 글자를 이룹니다. 예를 들어 글자 '가'는 문자 'ㄱ' 과 'ㅏ' 로 구성됩니다. Swift에서는 String은 조합형인지 완성형인지에 상관없이 동등성을 판단합니다.
let decomposed = "\u{1100}\u{1161}" // ᄀ + ᅡ
let precomposed = "\u{AC00}" // 가
decomposed == precomposed // true
즉 String은 다른 Swift 컬렉션 타입의 어떤것들과도 완전 다르게 동작합니다. 🐟과 🍚 값으로 구성된 배열이 🍣과 동등하다고 여겨진다면 매우 놀라울 것입니다.
당신의 관점에 달려있습니다.
string은 collection이 아닙니다. 대신 string은 CollectionType 프로토콜을 따르는 뷰들을 제공합니다.
- characters는 Character 값 또는 extended grapheme cluster의 컬렉션입니다.
- unicodeScalars 는 유니코드 스칼라 값들의 컬렉션입니다.
- utf8는 UTF-8 코드 유닛의 컬렉션입니다.
- utf16은 UTF-16 코드 유닛의 컬렉션입니다.
extended grapheme cluster: 유니코드 스칼라 묶음이 조합되었을 때, 사람이 읽을 수 있는 문자가 되는 구성.
이전이 예제에서 단어 café 는 [ c, a, f, e ] 와 [ ´ ] 로 구성되어 있으며, string의 다양한 뷰들은 아래와 같습니다.
characers 속성은 사용자가 인식하는 문자인 extended grapheme clusters로 분리합니다. string은 문자열 내부에서 문자 경계를 결정하기 위해 코드 포인트라고 하는 각 위치를 순회해야 하기 때문에, 이 속성에 대한 접근은 O(n) 시간이 걸립니다. 인간이 읽을수 있는 텍스트를 포함하는 문자열을 처리할 때, localizedStandardCompare(_:) 메서드나 localizedLowercaseString 속성에서 사용되는 하이레벨 locale-sensitive 유니코드 알고리즘들에서 문자단위 처리가 자주 사용됩니다.
unicodeScalars 속성은 문자열에 저장된 내부의 스칼라 값을 노출합니다. 만일 원래 문자열이 조합형 e + ´ 로 구성되지 않고 완성형 é로 생성되었다면, 이런 구성이 유니코드 스칼라뷰에 반영됩니다. 문자 데이터의 low-level 조작을 수행할때 이 API를 사용하세요.
utf8과 utf16 속성들은 UTF-8과 UTF-16 표현에 대한 코드포인트를 제공합니다. 이 값들은 특정 인코딩으로부터 혹은 인코딩으로 변환할때 파일에 쓰여지는 실제 바이트에 대응합니다. UTF-8 코드 유닛은 많은 POSIX 문자열 처리 API에서 사용되며, UTF-16 코드 유닛은 문자열의 길이와 오프셋을 표현하기 위해 Cocoa & Cocoa Touch에서 전반적으로 사용됩니다.
'Swift' 카테고리의 다른 글
| [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 |
| [swift2] Xcode7 beta5 Swift 언어 변경사항 (0) | 2015.08.14 |
| [swift1.2] Swift 프로토콜 지향 프로그래밍 (0) | 2015.08.06 |
설정
트랙백
댓글
글
[swift2] Xcode7 beta6 Swift 언어 변경사항
Swift Language Enhancements and Changes
1. try? 키워드가 추가되었습니다.
- try? 구문은 에러를 던질수도 있는 연산을 수행합니다.
- 연산이 성공하면 결과는 optional로 랩핑되어 반환되고, 에러가 throw 되면 결과는 nil를 반환하고 error는 버려집니다.
- try?는 if let과 guard 문과 함께 사용될 때 특히 유용합니다.
func produceGizmoUsingTechnology() throws -> Gizmo { … }
func produceGizmoUsingMagic() throws -> Gizmo { … }
if let result = try? produceGizmoUsingTechnology() { return result }
if let result = try? produceGizmoUsingMagic() { return result }
print("warning: failed to produce a Gizmo in any way")
return nil
- try?에 의해 평가되는 표현식의 결과타입에 항상 optional이 추가된다는 것을 주목하세요.
- throwing 함수의 반환타입이 Int?이면, try?와 함께 함수를 호출한 결과는 Int?? 또는 'Optional<Optional
>' 이 됩니다.
2. Xcode는 . 문법을 사용할 때, 문맥을 인식한 enum 엘리먼트와 option sets의 코드완성 기능을 제공합니다.
3. 프로토콜 extension Static 계산속성을 정의할 수 있습니다.
4. 함수 또는 생성자 파라미터 리스트 어떤 위치에도 가변인자가 올 수 있습니다.
func doSomethingToValues(values: Int..., options: MyOptions = [], fn: (Int) ->
Void) {
// function body
}
5. Objective-C와 호환되지 않는 타입을 포함하는 컬렉션은 더이상 Objective-C 호환타입으로 간주되지 않습니다.
- 이전에는 Array
구문은 @objc가 마킹된 프로퍼티로 허용되었지만, 그러한 케이스는 더이상 허용되지 않습니다.
6. C typdefs으로 선언된 block은 이제 Swift 클로져 typealias로 임포트됩니다.
- BOOL 타입 파라미터가 사용된 typedefs 블럭은 Bool 타입 파라미터를 가진 클로져로 임포트됩니다.(이전 베타5에서는 ObjCBool 파리미터로 되었음.)
- 이것은 블럭 파라미터의 행동과 임포트된 Objective-C 메서드를 매칭시킵니다.
7. 타입체커가 생성한 에러메시지는 구체적이고 유용하게 개선되고 있습니다.
- 진단시에, type alias를 사용했다면 별칭(aka)을 출력합니다.
Swift Standard Library Enhancements and Changes
1. print()와 debugPrint()가 개선되었습니다.
- 가변인자 지원하여, 한번의 호출로 여러개의 아이템을 출력할수 있습니다.
- separator: String = " " 가 추가되어, 어떻게 아이템이 구분되는지 제어할 수 있습니다.
- appendNewline:bool = true 는 terminator:String = "\n"로 교체되었습니다.
- output stream을 인자로 받는 print 함수에는 stream 인자에 toStream 레이블을 추가했습니다.
2. RangeReplaceableCollectionType.extend() 메소드가 appendContentsOf()로 이름이 변경되었습니다.
- splice() 메서드는 insertContentsOf()로 이름이 변경되었습니다.
3. 클로져와 @autoclosure 인자를 갖는 대부분의 표준라이브러리 API은 이제 rethrows를 사용합니다.
- map과 filter 같은 메서드의 클로져 파라미터들이 에러를 throw할 수 있게 허용합니다.
- 에러를 발생시킬 수 있는 표현식과 &&, ||, ?? 같은 short-circuiting 연산자를 함께 사용할수 있습니다.
4. 모든 CollectionType은 이제 sliceable 합니다.
- 다음 sequence spllitting/slicing 함수들은 SequenceType 프로토콜 요구사항에 맞게 삭제되거나 프로토콜 extension 디폴트 구현으로 대체되었습니다.
/// Returns the first `maxLength` elements of `self`,
/// or all the elements if `self` has fewer than `maxLength` elements.
prefix(maxLength: Int) -> SubSequence
/// Returns the last `maxLength` elements of `self`,
/// or all the elements if `self` has fewer than `maxLength` elements.
suffix(maxLength: Int) -> SubSequence
/// Returns all but the first `n` elements of `self`.
dropFirst(n: Int) -> SubSequence
/// Returns all but the last `n` elements of `self`.
dropLast(n: Int) -> SubSequence
/// Returns the maximal `SubSequence`s of `self`, in order, that
/// don't contain elements satisfying the predicate `isSeparator`.
split(maxSplits maxSplits: Int, allowEmptySlices: Bool, @noescape isSeparator:
(Generator.Element) -> Bool) -> [SubSequence]
- split를 위해 다음 convenience extension을 제공합니다.
split(separator: Generator.Element, maxSplit: Int, allowEmptySlices: Bool) ->
[SubSequence]
- 또한 새로운 프로토콜 요구사항과 컬렉션 타입의 디폴트 구현이 사용가능합니다.
/// Returns `self[startIndex..<end]`
prefixUpTo(end: Index) -> SubSequence
/// Returns `self[start..<endIndex]`
suffixFrom(start: Index) -> SubSequence
/// Returns `prefixUpTo(position.successor())`
prefixThrough(position: Index) -> SubSequence
'Swift' 카테고리의 다른 글
| [swift2] Swift Guard (0) | 2015.09.11 |
|---|---|
| [swift2] Swift2에서의 문자열(strings) (0) | 2015.09.02 |
| [swift2] Xcode7 beta6 Swift 언어 변경사항 (0) | 2015.08.27 |
| [swift2] Xcode7 beta5 Swift 언어 변경사항 (0) | 2015.08.14 |
| [swift1.2] Swift 프로토콜 지향 프로그래밍 (0) | 2015.08.06 |
| [swift] 문자열과 문자 -1 (Strings and Characters) (0) | 2015.08.01 |
설정
트랙백
댓글
글
[swift2] Xcode7 beta5 Swift 언어 변경사항
Linker
- bitcode를 활성화하면 이제 weak frameworks와 weak libraries가 지원됩니다. linker는 더이상 -weak_framework, -weak-l 또는 -weak_librarys가 -bitcode_bundle 과 함께 사용될수 없다고 경고하지 않습니다.
Swift Language Changes
1. 구조체, 클래스도 이제 ErrorType 프로토콜을 구현할수 있습니다.
2. 실패가능한 initializer에 위임하거나 체이닝할 때 !를 사용하여 force-unwrap 할 수 있습니다.
- self.init(...) 또는 super.init(...)가 실패가능한 경우 아래코드와 같이 force-unwrap 할 수 있습니다.
extension UIImage {
enum AssetIdentifier: String {
case Isabella
case William
case Olivia
}
convenience init(assetIdentifier: AssetIdentifier) {
self.init(named: assetIdentifier.rawValue)!
}
}
- 위와같이 실패가능한 initializer에 체이닝한 non-optional initializer 정의가 가능해집니다.
3. 성능향샹을 위한 -Onone 빌드 옵션
- -Onone 옵션 (debug) 빌드를 사용하면 표준라이브러리 제네릭 타입에 특화된 인스턴스를 사용하여 빌드성능을 향상시킬 수 있습니다.
- 많은 경우에 컴파일 타임에 영향없이 debug 빌드에서 상당히 빠른 실행파일을 생성합니다.
4. Objective-C 클래스의 제네릭 서브클래스와 이것을 상속하는 non-제네릭 클래스들은 runtime metadata 인스턴스화가 요구됩니다.
- Objective-C 코드에서 직접적으로 네이밍을 지정할수 없습니다.
- Beta4에 Objective-C 클래스들의 제네릭 서브클래스 정의가 가능해졌지만, 생성된 Objective-C 브리징 헤더에는 그러한 클래스들을 에러항목으로 리스팅합니다. 이로인해 잘못된 런타임 행동과 컴파일 타임에러를 발생시키는 오류를 수정하였습니다.
- 클래스에 대한 @objc 속성의 행동이 좀더 명확해졌습니다.
- 브리징헤더에 나타날 수 없는 클래스에 @objc를 적용하면 이제 에러입니다.
- 클래스의 어떤 수퍼클래스라도 @objc 클래스라면, 그 클래스의 멤버들은 암묵적으로@objc 이며, 모든 @objc 클래스들은 NSObject 를 상속해야함. 따라서 유효한 코드에 대한 어떤 변경을 발생시키지는 않습니다.
5. MacTypes.h 에 정의된 Boolean은 Swift와 Objective-C 타입 브리징 상황에서 Bool로 임포트됩니다.
6. NSManaged 속성을 CoreData가 자동생성한 키밸류코딩 호환 to-many 접근자에 접근하기 위한 메서드와 프로퍼티에 사용할 수 있습니다.
@NSManaged var employees: NSSet
@NSManaged func addEmployeesObject(employee: Employee)
@NSManaged func removeEmployeesObject(employee: Employee)
@NSManaged func addEmployees(employees: NSSet)
@NSManaged func removeEmployees(employees: NSSet)
- 이것들은 NSManagedObject 서브클래스에 선언되어야 합니다.
7. 타입 이름들과 enum cases들은 이제 디폴트로 자격없이(프로토콜 구현없이) print하고 String으로 변환할수 있습니다. debugPrint와 String(refelcting:)은 fully-qualified 이름을 얻기 위해 사용할 수 있습니다.
enum Fruit { case Apple, Banana, Strawberry }
print(Fruit.Apple) // "Apple"
debugPrint(Fruit.Apple) // "Fruit.Apple"
8. print()와 Mirrors의한 reflection은 current case와 멀티 payload 타입을 갖는 모든 enums payload를 report 할수 있습니다.
- 유일하게 reflection이 지원되지 않고 남아있는 enum 타입들은 @objc enums와 C에서 임포트된 enums 입니다.
Swift Standard Library Enhancements and Changes
1. SequenceType 프로토콜 구현체에 .forEach 구문을 사용할 수 있습니다.
(0..<10).forEach {
print($0)
}
위 구문은 아래구문과 유사합니다.
for x in 0..<10 {
print(x)
}
하지만 다음과 같은 차이점이 있습니다.
for-in 루프문과 다르게 break, continute를 사용하여 현재 클로져 몸체 호출을 종료하거나 일련의 호출을 건너뛸수
없습니다.클로져 몸체에 return문을 사용하면 외부 스콥이 아닌 현재 호출만 종료할수 있으며, 이어지는 일련의 호출을 건너뛸수 없습니다.
이러한 제약때문에 forEach 멤버는 함수형 알고리즘에 일련의 체이닝을 적용하고, 몸체가 적을때만 사용하도록 권장합니다.
foo.map {...}.filter {...}.forEach {...}
- 다른 경우에는 for..in 문 사용을 권장합니다.
3. SIMD: simd 모듈의 정수형 벡터타입은 &+, &-, & 연산자를 사용하여 감싸진 unchecked 산술식만 지원합니다. +,-, 연산자들은 정수형 벡터에는 사용 불가능하고 Xcode가 자동으로 wrapping 연산자로 교체하라고 제안할 것입니다.
4. SIMD: smid 모듈의 정수형 벡터타입 코드생성은 벡터하드웨어를 더 잘 사용할 수 있도록 개선되어 대부분의 경우에 극적으로 성능이 향상되었습니다.
5. Dictionary의 removeAtIndex(_:) 메서드는 key,value 쌍을 제거하여 두 엘리먼트를 튜플로 반환합니다.
- 유사하게 Set의 removeAtIndex(_:)은 삭제된 엘리멘트를 반환합니다.
6. Word와 UWord 타입은 표준라이브러리에서 삭제되었습니다. 대신 UInt를 사용하세요.
'Swift' 카테고리의 다른 글
| [swift2] Swift2에서의 문자열(strings) (0) | 2015.09.02 |
|---|---|
| [swift2] Xcode7 beta6 Swift 언어 변경사항 (0) | 2015.08.27 |
| [swift2] Xcode7 beta5 Swift 언어 변경사항 (0) | 2015.08.14 |
| [swift1.2] Swift 프로토콜 지향 프로그래밍 (0) | 2015.08.06 |
| [swift] 문자열과 문자 -1 (Strings and Characters) (0) | 2015.08.01 |
| [swift2] Xcode7 beta4 Swift 언어 변경사항 (0) | 2015.07.30 |
설정
트랙백
댓글
글
[swift1.2] Swift 프로토콜 지향 프로그래밍
WWDC 2015 세션중 "Protocol-Oriented Programming in Swift" 라는 흥미로운 세션이 있습니다. 애플에서 Standard Library 그룹의 리더를 맡고 있는 Dave Abrahams 라는 분이 발표한 세션입니다. 세션에서 제공하는 슬라이드와 InfoQ에서 이 세션을 정리한 아티클을 바탕으로 내용을 요약했습니다.
클래스는 멋집니다!
다음과 같은 멋진 특징들을 제공하지요.
- 캡슐화 (Encapsulation)
- 접근제어 (Access Cotrol)
- 추상화 (Abstraction)
- 네임스페이스 (Namespace)
- 풍부한 문법 (Epressive Syntax)
- 확장성 (Extensibility)
그런데...
구조체로도 다 할수 있습니다.
클래스는 훌륭합니다.타입은 훌륭합니다!
사실 위 특징들은 모든 타입들의 특징이며 클래스는 그것을 구현하는 하나의 방법에 불과합니다. 그렇다면 클래스 사용으로 인한 단점은 무엇이 있을까요?
1. 암묵적인 참조(Reference) 공유
- 두 객체가 동시에 어떤 객체를 참조하는 경우, 서로 그 사실을 모른채 그 객체를 변경할 수 있습니다.
- 참조 공유를 방지하기 위해 참조하는 객체를 복사할 수 있지만, 그렇게 하면 효율성이 나빠집니다.
- 참조를 공유하는 객체에 Race Conditions 이 발생할 수도 있습니다.
- Lock을 사용하여 레이스 컨디션을 방지할수 있지만 효율성은 더 나빠집니다.
- Lock을 잘못 사용하면 Deadlock 상태에 빠질 수 있습니다.
- 잦은 Lock 사용은 코드를 복잡하게 합니다.
- 복잡성은 더 많은 버그를 유발합니다.
Values Don't Share. (That's a good thing)
2. 상속 (비지니스에 관한 모든 것을 가지고 있습니다.)
- 슈퍼 클래스를 하나 밖에 가질수 없기 때문에, 초기에 잘 선택해야합니다.
- 슈퍼 클래스를 나중에 변경하는 것은 매우 어렵습니다.
- 슈퍼클래스가 갖는 모든 저장속성은 서브클래스에도 (강제적으로) 상속됩니다.
- 초기화 처리가 복잡해집니다.
- 수퍼클래스의 불변성을 깨뜨리지 않을수 없게됩니다.
- 언제 무엇을, 어떻게 재정의해야 하는지 (수퍼 클래스에 대해서)알아야 합니다.
More and more, we promote delegation.
3. 타입관계를 잃어버립니다.(Lost Type Relationships.)
- 추상 수퍼클래스와 서브클래스의 구현코드가 함께 존재하게 됩니다.
서브클래스 메소드에 접근하기 위해 수퍼클래스를 서브클래스로 다운캐스팅하면서 타입관계를 잃게됩니다.
이진탐색 클래스 모델 Ordered 정의
class Ordered {
func precedes(other: Ordered) -> Bool { fatalError("메소드를 구현해주세요.") }
}
class Number:Ordered {
var value:Double = 0
override func precedes(other: Ordered) -> Bool {
return value < (other as! Number).value //
}
}
func binarySearch(sortedKeys: [Ordered], forkey k: Ordered) -> Int {
var lo = 0
var hi = sortedKeys.count
while hi > lo {
let mid = lo + (hi - lo) / 2
if sortedKeys[mid].precedes(k) { lo = mid + 1 }
else { hi = mid }
}
return lo
}
as! ASubclass 는 타입 관계를 잃어버렸다는 신호
대부분 추상화를 위해 클래스를 사용하기 때문이다.
4. 좋은 추상화 메커니즘이란?
- Value type을 지원합니다.(클래스 외에도)
- 정적 타입관계를 지원합니다. (동적 디스패치 외에도)
- 큰 덩어리로 뭉치지 않아야합니다.
- Retroactive 모델링을 지원합니다.
- 모델에 인스턴스 데이터를 강요하지 않아야 합니다.
- 모델에 초기화의 부담이 없어야 합니다.
- 무엇을 구현해야 하는지 명확해야 합니다.
Swift는 프로토콜 지향 프로그래밍 언어!
5. 프로토콜 지향 프로그래밍
- Swift에서 새롭게 추상화를 생각할 때 첫 번째 포인트는 프로토콜!
이진탐색 프로토콜 모델 Ordered 변경해보겠습니다.
protocol Ordered {
func precedes(other:Self) -> Bool
}
struct Number : Ordered {
var value:Double = 0
func precedes(other:Number) -> Bool {
return self.value < other.value
}
}
이진탐색 함수를 정의합니다.
func binarySearch<T:Ordered>(sortedKeys:[T], forKey k: T) -> Int {
var lo = 0
var hi = sortedKeys.count
while hi > lo {
let mid = lo + (hi-lo)/2
if sortedKeys[mid].precedes(k) { lo = mid + 1 }
else { hi = mid }
}
return lo
}
Int 배열에 이진탐색 함수를 적용해 보겠습니다.
- 먼저 Int가 프로토콜 Ordered를 구현해야합니다.
// Int형 Ordered 프로토콜 구현하기
extension Int:Ordered {
func precedes(other: Int) -> Bool {
return self < other
}
}
- Int 배열에 이진탐색을 적용합니다.
// 1. 키 정렬
var keys = [10, 30, 1, 4, 5, 6, 7, 8, 55, 20]
var sortedKeys = keys.sorted { $0 < $1 }
// sortedKeys: [1, 4, 5, 6, 7, 8, 10, 20, 30, 55]
// 2. 찾을 키
var searchKey = 30
// 키 30의 index는 8.
// 3. 이진탐색
var searchIndex = binarySearch(sortedKeys, forkey: searchKey)
// searchIndex: 8
Number 배열에도 이진탐색을 적용해보겠습니다.
// 1. 정렬된 Number 배열 생성
var numbers = sortedKeys.map { return Number(value: Double($0)) }
// numbers: [1.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 20.0, 30.0, 55.0]
// 2. 찾을 키
var keyToSearch = 5.0
// 3. 이진탐색
var index = binarySearch(numbers, forkey: Number(value: keyToSearch))
// index: 2
프로토콜을 사용하면, 커스텀 Number 구조체 뿐만 아니라 기존 타입에도 이진탐색을 쉽게 적용할 수 있음을 알 수 있습니다.
'Swift' 카테고리의 다른 글
| [swift2] Xcode7 beta6 Swift 언어 변경사항 (0) | 2015.08.27 |
|---|---|
| [swift2] Xcode7 beta5 Swift 언어 변경사항 (0) | 2015.08.14 |
| [swift1.2] Swift 프로토콜 지향 프로그래밍 (0) | 2015.08.06 |
| [swift] 문자열과 문자 -1 (Strings and Characters) (0) | 2015.08.01 |
| [swift2] Xcode7 beta4 Swift 언어 변경사항 (0) | 2015.07.30 |
| [swift] 성능향상 시키기 - 다이나믹 디스패치를 최소화 (0) | 2015.07.16 |
설정
트랙백
댓글
글
[swift] 문자열과 문자 -1 (Strings and Characters)
프래그램밍에서 기본은 문자열 다루기! Swift에서는 문자열과 문자를 어떻게 다룰까요?
문자열은 "hello" 같은 문자들의 순서집합
Swift 문자열은 String 타입으로 표현되며, String 타입은 Character타입 값들의 집합으로 표현됨.
String과 Character 타입은 코드에서 텍스트를 다룰 때 빠르고 유니코드 호환되는 방식을 제공.
문자열 생성과 조작 문법은 간단하고 가독성이 좋으며, C와 유사한 문자열 리터럴 문법을 가짐.
+ 연산자를 사용하여 두 문자열을 쉽게 연결가능.
문자열의 변경가능 유무는 Swift의 다른 값들처럼 var,let 에 따라 관리.
문법이 단순함에 더해 Swift의 문자열 타입은 빠르고 현대적은 구현을 갖음.
모든 문자열은 인코딩에 독립적인 유니코드 문자로 구성.
다양한 유니코드 표현방식으로 문자들 접근을 지원.
문자열 보간을 사용하여 문자열에 상수, 변수, 리터럴, 표현식 삽입가능.
1. 문자열 리터럴
문자열 리터럴은 쌍따옴표 쌍으로 감싸진 고정된 순서의 문자들입니다. 상수나 변수에 초기값으로 문자열 리터럴을 사용할수 있습니다.
let someString = "Some string literal value"
Swift는 someString 상수가 문자열 리터럴로 초기화 되었기 때문에 String 타입임을 추론합니다.
2. 빈 문자열 생성
var emptyString = "" // 문자열 리터럴 사용
var anotherEmptyString = String() // 문자열 생성자 사용
// 두 문자열은 비어있으면 두 표현은 동일함
isEmpty 속성을 사용해서 String 값이 비어있는지 검사할 수 있습니다.
if emptyString.isEmpty {
print("Nothing to see here")
}
3. 문자열의 수정가능 유무(Mutability)
문자열을 변수(var) 또는 상수(let)에 할당하느냐에 따라 String의 수정가능 유무를 가리킬수 있습니다.
var variableString = "Horse"
variableString += " and carriage"
// variableString은 "Horse and carriage"
let constantString = "Highlander"
costantString += " and another Highlander"
// 문자열 상수는 변경할수 없다는 컴파일 에러가 발생
문자열의 수정가능 유무를 NSString 클래스와 NSMutableString 클래스로 결정하는 Objective-C 와는 접근방식이 다릅니다.
4. 문자열은 Value타입!
Swift의 String타입은 value타입입니다. 새 문자열을 생성하면 문자열은 함수나 메소드에 전달되거나, 변수 또는 상수에 할당될 때마다 복사됩니다. 각 경우에 기존 문자열의 복사본이 생성되고 이 복사본이 전달되거나 할당됩니다.
Swift의 이런 특성(copy-by-default)은 함수나 메소드가 문자열을 전달받으면 어디에서 왔는지에 상관없이 완전히 문자열을 소유한다는 것을 보장해줍니다. 즉 스스로 문자열을 변경하지 않으면 전달받은 문자열은 결코 수정되지 않을 것이라 확실할 수 있습니다.
사실 Swift 컴파일러가 반드시 필요한 경우에만 복사가 일어나도록 문자열 사용을 최적화합니다. value 타입으로 문자열을 사용하면 항상 좋은 성능을 얻을 수 있습니다.
5. 문자 다루기
for-in 루프에서 character 속성을 사용해서 문자열의 개별 문자들에 접근할 수 있습니다.
for character in "Dog!".character {
print(character)
}
// D
// o
// g
// !
한문자만을 갖는 문자열 리터럴을 사용해서 Character 상수를 생성할수 있습니다.
let exclamationMar:Character = "!"
문자열은 Character의 배열을 생성자의 인자로 전달하여 생성할 수도 있습니다.
let catCharacters:[Character] = ["C", "a", "t", "!"]
let catString = String(catCharacters)
print(catString)
// Cat!
6. 문자열과 문자 접합
- 연산자를 사용하여 두 문자열을 접합한 새로운 문자열을 생성할 수 있습니다.
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome은 "hello there"
문자열 변수에 += 연산자를 사용하여 문자열을 추가할 수도 있습니다.
var instruction = "look over"
instruction += string2
// instruction은 "look over there"
문자열 변수에 append() 메소드를 사용하여 문자를 추가할 수 있습니다.
let exclamationMark:Character = "!"
welcome.append(exclamationMark)
// welcome은 "hello there!"
Character 변수는 하나의 문자만 포함하기 때문에 다른 문자열이나 문자를 추가할 수 없습니다.
7. 문자열 보간(Interpolation)
문자열 보간은 문자열 리터럴 안에 상수, 변수, 리터럴, 표현식을 혼합하여 새로운 문자열을 생성하는 방식입니다. 각 항목은 백슬러시와 소괄호 안에 감싸여진 문자열 리터럴에 삽입됩니다.
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
위 예에서 multipiler값은 문자열 리터럴 (multiplier)에 삽입됩니다. 새 문자열을 생성하기 위해 문자열 보간이 평가될때 placeholder는 multiplier의 실제값으로 대치됩니다.
표현식 Double(multiplier) * 2.5는 계산된 결과 7.5가 문자열에 삽입됩니다.
'Swift' 카테고리의 다른 글
| [swift2] Xcode7 beta5 Swift 언어 변경사항 (0) | 2015.08.14 |
|---|---|
| [swift1.2] Swift 프로토콜 지향 프로그래밍 (0) | 2015.08.06 |
| [swift] 문자열과 문자 -1 (Strings and Characters) (0) | 2015.08.01 |
| [swift2] Xcode7 beta4 Swift 언어 변경사항 (0) | 2015.07.30 |
| [swift] 성능향상 시키기 - 다이나믹 디스패치를 최소화 (0) | 2015.07.16 |
| [swift2] Xcode7 beta3 Swift 언어 변경사항 (0) | 2015.07.11 |
설정
트랙백
댓글
글
[swift2] Xcode7 beta4 Swift 언어 변경사항
드디어 Xcode7 beta4가 공개되었네요! beta4 에서 Swift 언어 변경사항에 대해 알아볼까요?
Objective-C Language Changes
1. 더블 언더스코어 nullability 한정자들 이름이 변경되었습니다.
- as is: __nullable, __nonnull, __null_unspecified
- to be: _Nullable, _Nonnull, _Null_unspecified
- 소스 호환성을 위해 컴파일러가더블 언더스코어 이름을 새로운 이름으로 맵핑하는 매크로를 정의해줍니다.(predefine)
Swift Language Changes
1. Enum과 Case에 indirect 키워드를 사용할 수 있습니다.
- indirect 키워드를 사용해서 재귀적인 데이터 구조를 정의할 수 있음.
- 재귀적인 데이터 구조 정의시 enum의 연관값은 간접적으로 저장됨
enum List<T> {
case Nil
indirect case Cons(head: T, tail: List<T>)
}
indirect enum Tree<T> {
case Leaf<T>
case Branch(left: Tree<T>, right: Tree<T>)
}
2. class 객체를 참조하는 AnyObject, NSObject 변수를 class Object 타입으로 복원이 가능합니다.
let x:AnyObject = NSObject.self // NSObject 클래스 객체를 AnyObject로 캐스팅
let y = x as! NSObject.Type // AnyObject를 NSObject 클래스 객체로 복원
3. class 객체를 포함하는 Array,Dictionary,Set 을 NSArray,NSDictionary,NSSet로 브리징할 수 있습니다.
- [NSURLSessionConfiguration protocolClasses]과 같이 NSArray * 객체를 반환하는 Objective-C API도 이제 Swift에서 정상동작합니다.
4. 클래스에 적용한 @objc 속성은 Objective-C 헤더에 생성된 클래스의 컴파일타임 이름 뿐만 아니라 런타임 이름도 변경합니다.
- 프로토콜에도 적용됨
// Swift
@objc(MyAppDelegate)
class AppDelegate : NSObject, UIApplicationDelegate {
//...
}
// Objective-C
@interface MyAppDelegate : NSObject <UIApplcationDelegate>
// ...
@end
5. 스칼라값의 0 엘리먼트를 참조하는 기능은 제거되었습니다.
6. 타입검사 제약시스템이 생성한 에러 진단메시지가 beta4에서 개선되었습니다. 이후 베타버전에서 더 많은 부분들이 개선될 예정입니다.
7. SinkType 프로토콜과 SinkOf 구조체가 표준 라이브러리에서 제거되고 대신 (T) -> () 클로져를 사용합니다.
8. ExtensibleCollectionType 부모프로토콜이 서브 프로토콜 RangeReplaceableCollectionType로 통함되었습니다.
- RangeReplaceableCollectionType 은 subRange를 다른 컬렉션의 엘리먼트들로 교체를 지원하는 컬렉션 타입.
- 기본구현을 위한 메소드들이 추가됨.
- 이 프로토콜들과 연관된 (free) Swift 모듈 함수들 대신 이 메서드들을 사용할 수 있습니다.
9. Unmanaged를 사용한 속성과 메서드들도 Objective-C에 노출가능합니다.
- Unmanaged는 unmananged 객체 레퍼런스를 전달하기 위한 타입.
- 이 타입을 사용하면 객체가 살아있도록 유지할 책임이 있음.
10. performSelector 류의 API 들 Swift 코드에서 사용가능합니다.
11. __unsafe_unretained로 마크된 C 구조체 필드는 Swift에 Unmanaged 로 표시됩니다.
- Swift 컴파일러는 이 참조들이 실제로 strong(+1) 또는 unretained(+0)로 의도되었는지는 알수 없음.
12. Swift 문서 주석들은 최상위 목록아이템을 인식합니다.
- Throws: ... 구문은 어떤 에러가 왜 던져질수 있는지 문서화하기 위해 사용합니다.
- Xcode QuickHelp의 파라미터 및 반환값 설명 옆에 표시됩니다.
13. 타입은 그 타입보다 더 낮은 버전에서 가용한 프로토콜을 구현할 수 있습니다.
@available (iOS 9.0, *)
protocol P { ... }
@available (iOS 7.0, *)
class MyController : UIViewController, P {
...
}
'Swift' 카테고리의 다른 글
| [swift1.2] Swift 프로토콜 지향 프로그래밍 (0) | 2015.08.06 |
|---|---|
| [swift] 문자열과 문자 -1 (Strings and Characters) (0) | 2015.08.01 |
| [swift2] Xcode7 beta4 Swift 언어 변경사항 (0) | 2015.07.30 |
| [swift] 성능향상 시키기 - 다이나믹 디스패치를 최소화 (0) | 2015.07.16 |
| [swift2] Xcode7 beta3 Swift 언어 변경사항 (0) | 2015.07.11 |
| [swift2] Swift에서 에러 처리 (Error Handling) (0) | 2015.07.10 |
설정
트랙백
댓글
글
[swift] 성능향상 시키기 - 다이나믹 디스패치를 최소화
애플 Swift 블로그의 [Increasing Performance by Reducing Dynamic Dispatch] 를 번역한 글입니다.
다른 언어들처럼 Swift도 수퍼클래스에 선언된 메서드와 속성을 오버라이드 할수 있습니다.
이말은 곧 프로그램이 런타임에 어떤 메서드와 프로퍼티를 참조할 것인지 결정해야하고, 간접호출 또는 간접접근을
수행해야 한다는 것을 의미합니다. 다이나믹 디스패치(dynamic dispatch)라고 불리는 이 기술은,
간접 호출/접근 횟수마다 일정량의 런타임 오버헤드 비용을 증가시킵니다. 성능에 민감한 코드에서는 그와같은 오버헤드
종종 바람직하지 않습니다. 이 포스트는 다이나믹함을 제거함으로써 성능을 향상시키는 3가지 방법에 대해 알려드립니다.
: final, private, 모듈 최적화.
다음 예를 살펴보겠습니다.
class ParticleModel {
var point = ( 0.0, 0.0 )
var velocity = 100.0
func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
point = newPoint
velocity = newVelocity
}
func update(newP: (Double, Double), newV: Double) {
updatePoint(newP, newVelocity: newV)
}
}
var p = ParticleModel()
for i in stride(from: 0.0, through: 360, by: 1.0) {
p.update( (i * sin(i), i), newV: i*1000 )
}
작성된데로, 컴파일러는 동적으로 호출을 dispatch 할 것입니다.
1. p의 upodate 호출
2. p의 uodatePoint 호출
3. p의 point 튜플 속성에 접근한다
4. p의 velocity 속성에 접근한다
이것은 코드를 보면서 기대했던 것이 아닐수 있습니다. 동적 호출은 ParticleModel의 서브클래스들이 point 또는 velocity 를
계산속성이나 새롭게 구현된 updatePoint() 또는 update()로 오버라이딩 할수 있기 때문에 필수적입니다.
Swift에서 동적 디스패치콜은 메서드 테이블에서 함수를 찾고 간적호출을 수행하는 방식으로 구현되어집니다. 이것은 직접호출로
수행하는 것보다 더 느립니다. 게다가 간접호출은 많은 컴파일러 최적화를 막아 간접호출이 훨씬 더 많은 비용이 들도록 합니다.
성능 크리티컬한 코드에서 성능을 향샹시킬 필요가 있을때 다이나믹 행동을 제한하기 위해 사용할 수 있는 기술들이 있습니다.
1. 오버라이딩 할 필요가 없는 속성 선언에는 final을 사용하세요.
final은 클래스, 메서드, 속성이 오버라이드 할 수 없도록 제약하는 키워드입니다. 이렇게 하면 컴파일러가 다이나믹 디스패치의
간접호출/접근을 생략할 수 있게 합니다. 아래 예제의 point, velocity는 객체의 저장속성으로부터 직접적으로 액세스되고, updatePoint()는 direct 함수콜을 통해 호출됩니다. 반면 udpate()는 여전히 동적 디스패치를 통해 호출되며 서브클래스가 update()를 오버라이 할 수 있습니다.
class ParticleModel {
final var point = ( x:0.0, y:0.0 )
final var velocity = 100.0
final func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
point = newPoint
velocity = newVelocity
}
func update(newP: (Double, Double), newV: Double) {
updatePoint(newP, newVelocity: newV)
}
}
var p = ParticleModel()
for i in stride(from: 0.0, through: 360, by: 1.0) {
p.update( (i * sin(i), i), newV: i*1000 )
}
final를 사용하여 전체 클래스 자체를 final로 만들수 있습니다. 이렇게 하면 서브클래싱이 불가능해지며 클래스의 모든 함수와 속성들이 final이 됩니다.
final class ParticleModel {
var point = ( x: 0.0, y: 0.0 )
var velocity = 100.0
// ...
}
2. private 키워드를 사용하면 한 파일에서만 참조되는 final 선언임을 추론할수 있습니다.
private 키워드를 선언부에 적용하면 현재파일에만 선언이 노출되도록 가시성을 제한합니다. 이것은 컴파일러가 모든 잠재적인 오버라이딩 선언을
찾을 수 있도록 합니다. 오버라이딩 선언이 없으면 컴파일러는 자동으로 final 키워드를 추론하고 메서드와 속성 접근에 대해 간접호출
(indirect calls)들을 제거합니다.
현재 파일에 ParticleModel 클래스에 대한 오버라이딩이 없다고 판단되면, 컴파일러는 private으로 선언된 모든 dynamic dispatch call을
직접호출로 대체합니다.
class ParticleModel {
private var point = ( x:0.0, y:0.0 )
private var velocity = 100.0
private func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
point = newPoint
velocity = newVelocity
}
func update(newP: (Double, Double), newV: Double) {
updatePoint(newP, newVelocity: newV)
}
}
var p = ParticleModel()
for i in stride(from: 0.0, through: 360, by: 1.0) {
p.update( (i * sin(i), i), newV: i*1000 )
}
이전 예제에서처럼, point, velocity는 직접접근되며 updatePoint()는 직접호출 됩니다. 하지만 update()는 private이 아니기
때문에 간접적으로 호출됩니다.
final과 마찬가지로 클래스 선언부에 private을 사용하여 클래스 자체를 private로 만들고 그에 따라 모든 속성과 메서드를 private하게 만들
있습니다.
private class ParticleModel {
var point = ( x: 0.0, y: 0.0 )
var velocity = 100.0
}
3. internal 선언을 final로 추론할수 있는 전체 모듈 최적화를 사용하세요.
internal 접근자를 갖는 선언(디플트값)은 그들이 선언된 모듈 내에서만 볼수 접급될 수 있습니다. swift는 일반적으로 모듈을 구성하는
파일들을 개별적으로 컴파일하기 때문에 컴파일러는 internal 선언이 다른 파일에서 오버라이딩 됐는지 알수 없습니다. 그러나 전체 모듈최적
옵션을 활성화하면 모든 모듈이 동시에 한번에 컴파일 됩니다. 이렇게 하면 전체 모듈에 대해 컴파일러가 추론할수 있게되어 오버라이딩 되지
않은 internal 선언을 final로 추론할 수 있게됩니다.
원래 코드로 되돌아가서 이번에는 ParticleModel에 몇몇 public 키워드를 추가해보겠습니다.
public class ParticleModel {
var point = ( x:0.0, y:0.0 )
var velocity = 100.0
func updatePoint(newPoint: (Double, Double), newVelocity: Double) {
point = newPoint
velocity = newVelocity
}
public func update(newP: (Double, Double), newV: Double) {
updatePoint(newP, newVelocity: newV)
}
}
var p = ParticleModel()
for i in stride(from: 0.0, through: 360, by: 1.0) {
p.update( (i * sin(i), i), newV: i*1000 )
}
모듈 최적화(Module Optimization) 옵션을 활성화하고 이 코드를 컴파일하면, 컴파일러는 point, velocity,
updatePoint() 함수를 final로 추론할수 있습니다. 반면 udpate()는 public 접근자를 갖기 때문에 final로 추론
될 수 없습니다.
'Swift' 카테고리의 다른 글
| [swift] 문자열과 문자 -1 (Strings and Characters) (0) | 2015.08.01 |
|---|---|
| [swift2] Xcode7 beta4 Swift 언어 변경사항 (0) | 2015.07.30 |
| [swift] 성능향상 시키기 - 다이나믹 디스패치를 최소화 (0) | 2015.07.16 |
| [swift2] Xcode7 beta3 Swift 언어 변경사항 (0) | 2015.07.11 |
| [swift2] Swift에서 에러 처리 (Error Handling) (0) | 2015.07.10 |
| [swift2] 타입의 텍스트적인 표현 커스터마이징하기 (0) | 2015.07.01 |
