티스토리 뷰
[Swift 4] Swift 3 -> Swift 4 Migration (Limiting @objc inference)
beankhan 2017. 9. 21. 09:00출처
소개
변경 이유
1) Swift 의 @objc 에 대한 추론 규칙은 단순하며,
@objc 가 유추되는 이유가 사용자에게 불명확할 수 있습니다.
2) 클래스가 많아질경우 실수로 Objective-C 충돌을 발생시키는
Swift 클래스를 작성하기 쉽습니다.
3) Swift 코드 디자인 지침을 따랐지만
Objective-C 코드 작성 규칙을 위반하는 경우가 있습니다.
아래와 같은 경우 명시적인 @objc 주석이 필요합니다.
class MyNumber : NSObject {
init(_ int: Int) { }
init(_ double: Double) { } // error: initializer 'init' with Objective-C selector 'init:'
// conflicts with previous declaration with the same Objective-C selector
}
class MyNumber : NSObject {
@objc(initWithInteger:) init(_ int: Int) { }
@objc(initWithDouble:) init(_ double: Double) { }
}
4) 각각의 Objective-C entry point 에 cost 가 있다는 점입니다.
Swift 컴파일러는 Objective-C 호출 규칙에서 Swift 호출 규칙으로 변경하기 위한
map 의 "thunk" method 를 만들어야합니다.
이런 "thunk" method 는 는 Objective-C metadata 에 기록되기 때문에
binary 크기가 증가됩니다.
또한 dynamic linker 는 이런 thunk method 를 위해
Objective-C metadata 를 정렬해야하기 때문에
로드 시간에 약간의 영향을 줄 수 있습니다.
해결 방안
dynamic, NSObject -derived classes no longer infers @objc
class MyClass : NSObject {
func foo() { }
func bar() { }
}
class UnrelatedClass : NSObject {
@objc func bar() { }
}
func test(object: AnyObject) {
object.foo?()
// Swift 3: can call method MyClass.foo()
// Swift 4: compiler error, no @objc method "foo()"
object.bar?()
// Swift 3: can call MyClass.bar() or UnrelatedClass.bar()
// Swift 4: can only call UnrelatedClass.bar()
}
class MySuperclass : NSObject { }
extension MySuperclass {
func extMethod() { }
// implicitly @objc in Swift 3, not in Swift 4
}
class MySubclass : MySuperclass {
override func extMethod() { }
// Swift 3: okay
// Swift 4: error "declarations in extensions cannot override yet"
}
Re-enabling @objc inference within a class hierarchy
@objcMembers
class MyClass : NSObject {
func foo() { } // implicitly @objc
func bar() -> (Int, Int) { } // not @objc, because tuple returns
// aren't representable in Objective-C
}
extension MyClass {
func baz() { } // implicitly @objc
}
class MySubClass : MyClass {
func wibble() { } // implicitly @objc
}
extension MySubClass {
func wobble() { } // implicitly @objc
}
Enabling/Disabling @objc inference within an extension
class SwiftClass: NSObject { }
@objc extension SwiftClass {
func foo() { } // implicitly @objc
@nonobjc func bar() -> (Int, Int) { return (0, 0) } // error: tuple type (Int, Int) not
// expressible in @objc. add @nonobjc or move this method to fix the issue
}
@objcMembers
class MyClass : NSObject {
func wibble() { } // implicitly @objc
}
@nonobjc extension MyClass {
func wobble() { } // not @objc, despite @objcMembers
}
Constructs that (still) infer @objc
class Super {
@objc func foo() { }
}
class Sub : Super {
/* inferred @objc */
override func foo() { }
}
@objc protocol MyDelegate {
func bar()
}
class MyClass : MyDelegate {
/* inferred @objc */
func bar() { }
}
Side benefit: more reasonable expectations
@objc protocol P { }
extension P {
func bar() { }
}
class C : NSObject, P { }
let c = C()
print(c.responds(to: Selector("bar"))) // prints "false"
Limitation Activate Setting
'iOS 개발 > Swift' 카테고리의 다른 글
[Swift4] Swift 4 에서 변경된점 (0) | 2017.09.19 |
---|---|
[Swift 3] DispatchSemaphore 사용하기 (0) | 2017.06.11 |
[Swift 3] DispatchGroup 사용하기 (0) | 2017.06.09 |
[Swift] Objective C 프로젝트에서 Swift 를, Swift 프로젝트에서 Objective C 를 사용하기 (1) | 2017.06.08 |
[Swift 3.0] Dispatch Queue 사용하기 (0) | 2017.06.06 |
- Total
- Today
- Yesterday
- thread
- Swift 3.0
- Block
- Swift 3
- Swift
- ios
- coredata
- NSManagedObjectContext
- optional
- CIImage
- docker
- NSManagedObject
- workerThread
- delegate
- Arc
- CGImage
- Swift3
- EffectiveObjectiveC
- dictionary
- 꺼내먹어요
- RunLoop
- applicationWillResignActive
- UIView
- NSManagedObjectModel
- set
- string
- Swfit
- 읽기 좋은 코드가 좋은 코드다
- AWS
- HTTP
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |