가급적이면 모든 내용을 다루고 싶지만 이해가 안되는 것도 많고 별로 몰라도 되는 것도 있어서 중요하다 싶은 내용만 다룬다. 이번 업데이트는 크게 Swift, Xcode 그리고 Objective-C 세 가지 파트로 나뉘어진다.
참고로 이 글은 Xcode 6.3 베타 릴리즈 노트를 기준으로 작성하였다. 기타 애플의 블로그의 내용에도 어느 정도 정리되어 있으니 원문을 간단히 보고 싶다면 아래 링크를 방문해보자.
https://developer.apple.com/swift/blog/?id=22
Swift 1.2
퍼포먼스
직접 대충 체크하는 것 보단 어느 정도 굴려보신 분의 글을 보는게 나을 것 같다.http://blog.sudeium.com/2015/02/10/swift-1-dot-2-performance-pretty-much-fine/
Set 타입 추가
Set
이라는 새로운 컬렉션 타입이 추가되었다. 기존 파운데이션의 경우 NSSet 이라는 클래스와 유사한 것으로 볼 수 있다.
참고로 Set은 유니크 밸류(즉 중복되지 않는 고유 값)를 보관할 수 있는 배열과 비슷하다. 제공되는 메소드 등은 Array나 Dictionary와 유사하다.
[관련글] Swift 1.2 - Set 타입
if 문의 조건절 기능 추가
기존if let
의 구문은 단 하나의 옵셔널 변수만 테스트 가능했는데 이것이 확장되었다. 거기다 새로운 조건 추가절(where)을 이용 할 수 있게 되었다.
일단 아래 코드를 보자.
if let a = foo() { if let b = bar() { if a < b { if let c = baz() { ... } } } }'이 불량한(?) 모습의 코드는 무엇이란 말인가!' 라는 생각이 든다면, 1.2에서는 아래처럼 바꿀 수도 있다는 사실에 환호활 지도 모르겠다.
if let a = foo(), b = bar() where a < b, let c = baz() { ... }이건 너무 편하다. 진작에 이런 기능이 있었어야 했다!
그 외에 예전 옵셔널 값 존재 여부로 기본값을 결정 하던 '??' 오퍼레이터를 if 문에서도 사용 할 수 있게 되었다. (Xcode 6.3 Beta 2)
if someObj?.value ?? 0 > 0 { ... }참고로 이 문법은 while 등등 조건문을 이용 가능한 곳에서도 동일하게 적용되는 듯 하다.
상수의 인스턴스화 시기
기존에는 클래스의 생성자를 제외하고let
으로 선언되는 상수는 선언 즉시 값을 지정해야만 했었다. 하지만 Swift 1.2 부터는 즉시가 아니라 참조되기 전에 인스턴스화 하면 되는 식으로 변경되었다.
let x: Something if condition { x = foo() } else { x = bar() } use(x)1.1 이전까지만 해도 위 같은 경우를 위해서
x
라는 녀석은 상수가 아닌 변수(var)로 선언했어야 했는데 좋은 변화이다.상수는 여러 면에서 유용하다. 예를 들어 immutable의 특징을 충족시켜서 thread-safe 등의 안정성도 가질 수 있다.
클래스와 static
static
은 기존의 경우 구조체(struct)에서만 사용이 가능했었는데 1.2 부터는 클래스(class)에서도 사용이 가능해진다. 그리고 이 class의 static은 class final
의 별칭 형태로 구현된다고 한다. 무슨 말일까? '-'??
어쨌거나 static이 가능해졌다는 점은 클래스를 인스턴스화 하지 않고도 lazy property를 사용 할 수 있게 해 준다. 이와 함께 프로토콜(Protocol)에서 class 대신 static을 요구하게 변경되었다. (class-only procotol의 경우를 의미하는 듯)
Objective-C와 호환되는 열거헝(enum)
Swift의 Enum은 C의 enum에 비해 상당히 많은 기능을 제공한다. 그래서 Objective-C와 호환이 되지 않는다는 단점이 있었다. 그런데 이제는@objc
키워드를 통해 Objective-C 에서도 쓸 수 있는 Enum을 만들 수 있게 되었다.
// Swift Code @objc enum Bear: Int { case Black, Grizzly, Polar } // 위 코드는 Objective-C 파트에서 이런 식으로 사용(Import)된다. typedef NS_ENUM(NSInteger, Bear) { BearBlack, BearGrizzly, BearPolar };자연스럽게 열거형 타입 이름이 각 요소 이름 앞에 자동으로 붙어주는게 Objective-C 답다. -_-;
as!
as?
같은걸 써서 옵셔널 타입으로 변환하는 방법이 있었지만 직접 값을 추출해 내지는 못 했었다. 1.2 에서는 여기에 as!
를 추가했다.
아마도 기존 !
같은 강제로 옵셔널을 벗기는 것과 의미는 비슷할거라 생각된다.[관련글] Swift - 'as!' 오퍼레이터 살펴보기
대충 형변환을 막아버리다
예를 들어, NSString 타입에서 Swift의 String로 별 다른 키워드 없이 대충 형변환(암시적 형변한)은 가능했었는데 이걸 막하버렸다는 이야기이다.형변환이 아주 막혔다는 의미는 아니다. 실제로
as
커맨드를 이용해 String과 NSString 사이의 형변환은 자유롭다. 그저, as
를 쓰지 않고 암시적 형변환(Implicit Conversions)을 했던 코드는 이제 오류가 발생한다는 이야기다.다만 Swift String을 NSString으로 암시적으로 형변환 하는 건 여전히 유효하다고 한다. 물론 위의 이야기는 String과 NSString 사이에 한정한 것인데 Array와 NSArray, Dictionary와 NSDictionary 사이도 동일한 룰이 적용될 것이다.
@noescape
속성 추가
클로져 속성 중 @noescape
가 추가되었다. noescape에 관한 글을 별도로 작성하였으니 이 글을 참고하자.
@autoclosure
@autoclosure
를 붙이는 위치가 바뀌었다. 이제는 아래와 같이 필드 이름 앞에 명시해야 한다.
// 기존 func assert(predicate: @autoclosure () -> Bool) { ... } // Swift 1.2 func assert(@autoclosure predicate: () -> Bool) { ... }모호함을 해소하려는 문법의 변화 같다. 이와 함께
@noescape
속성도 함께 지닌다고 한다. Xcode 6.3 Beta 2에서 autoclosure의 escaping 속성이 추가되었다. 아래는 공식 릴리즈 노트의 예제이다.
func lazyAssertion(@autoclosure(escaping) condition: () -> Bool, message: String = "") { lazyAssertions.append(condition) // escapes } lazyAssertion(1 == 2, message: "fail eventually")일단 좀 더 이해가 필요할 것 같다. 기회가 되면 이와 관련해 별도의 글을 써 볼 생각이다.
[관련글] Swift - @autoclosure 이야기
Xcode 6.3
Swift의 문법적인 변화 때문인지 마이그레이션 기능을 제공하기 시작했다. 메뉴에서 'Edit - Convert - To Swift 1.2' 를 선택하면 마이그레이션이 된다.Objective-C
널 가능성 문법
Swift과 Objective-C 사이의 호환성 문제가 걸리는 것 중 하나가 바로 옵셔널이다. Swift의 옵셔널은 별도의 타입이지만 Objective-C에서 NULL은 그저 NULL이라는 값이다. 그래서 이 둘 사이 브릿지 임포트 하는 경우 호환성에 문제가 생긴다. 특히, Objective-C 코드를 Swift에서 쓰는 경우 옵셔널이 명확하지가 않다. (포인터의 경우 전부 Implicit Unwrapped Optionals 투성이 -_-)그래서 Objective-C 언어 문법에도 특수한 문법이 추가되었다. 대충 널 가능성 표현(Nullability Annotations) 이라고 칭하자. 아래의 세 가지 키워드를 보자.
nonnull
or__nonnull
: Non-optionalnullable
or__nullable
: Optionalnull_unspecified
or__null_unspecified
: Implicitly-unwrapped optional
어쨌거나, 이들 키워드가 어떤 식으로 쓰여지고 어떻게 Swift에서 인식되는지를 보자.
// Objective-C - (void)registerNib:(nonnull UINib *)nib forCellReuseIdentifier:(nonnull NSString *)identifier; // Swift func registerNib(nib: UINib, forCellReuseIdentifier identifier: String) // Objective-C - (nullable UITableViewCell *)cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath; // Swift func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell? // Objective-C @property (nonatomic, readwrite, retain, nullable) UIView *backgroundView; // Swift var backgroundView: UIView?좋은 변화다.
[관련글] 스위프트(Swift) 가이드
정보 공유해 주셔서 감사합니다. ^^
답글삭제as! 에 대한 내용이 잘못되어서 좀 수정하였습니다. :-)
답글삭제