우리는 iOS 개발에서 특정 Control에 target-action을 적용할 때 자연스럽게 Selector라는 타입의 객체(#selector(@objc method)
)를 사용합니다.
그런데 이것이 정확히 무엇일까요...? 오늘은 이 Selector가 무엇인지, 왜 필요한지 알아보고 정리했습니다!
Objective-C에서의 Selector
사실 Selector는 원래 Objective-C에서 사용하던 기능입니다. 이는 특정 메서드를 컴파일타임에 동적으로 식별하고 참조하는 역할을 했습니다. 이러한 특징을 기반으로 Objective-C에서 동적으로 메서드를 동작시키려할 때 Selector를 사용했습니다. 반면 Swift에서는 이런 별도의 객체를 사용하지 않아도 메서드를 동적으로 동작시킬 수 있기 때문에 직접적으로 Selector를 필요로 하지는 않습니다.
Swift에서의 Selector
최근에는 주로 Swift로 iOS 개발을 진행하지만 여전히 많은 iOS의 API들이 Objective-C를 기반으로 동작하고 있습니다. 대표적인 예로 앞서 언급한 target-action 메커니즘이 내부적으로 Objective-C에 의존적으로 돌아갑니다. 따라서 Objective-C 기반 API에서 Selector 타입을 요구하는 경우, 이를 대체할 수 있는 타입을 Swift에서 제공할 수 있어야합니다.
그렇기 때문에 Swift에서 직접적으로 Selector를 사용하지는 않지만 Objective-C의 Selector와 유사한 기능을 하는 Selector를 필요로 했던 것입니다.
@objc의 필요성
컴파일 타임에 메서드를 바인딩하는 Swift와는 다르게 Objective-C는 런타임에 메서드를 바인딩합니다. 따라서 Swift에서 Objective-C에 의존적인 메서드에 사용할 때는 해당 메서드가 Objective-C와 유사한 방식으로 컴파일 되어야함을 컴파일러에게 알려주어야 합니다.
이를 의미하는 것이 @objc
입니다. 이를 메서드 앞에 붙여주면 Swift로 작성된 코드를 Objective-C 런타임에서도 사용할 수 있게됩니다. (cf. 만약 class가 NSObject를 상속하고 있는 경우 해당 키워드가 필요하지 않습니다.)
Summary
- Selector는 Objective-C에서 특정 메서드를 식별할 수 있는 고유 식별자의 역할을 하며, 동적으로 함수를 동작시키기위해 사용하던 기능입니다.
- Swift는 이런 기능이 직접적으로 필요하지는 않지만 Objective-C에 의존적인 API가 많아 이를 원활하게 사용하기 위해 유사한 기능의 Selector 타입을 구현하고 있습니다.
- Swift의 Selector가 전달하는 메서드는 Objective-C와 유사한 방식으로 컴파일되어야하므로, 전달하려는 Swift 메서드에 @objc 키워드를 붙여 컴파일러가 이를 확인할 수 있도록 합니다.
참고
- https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html
- https://developer.apple.com/documentation/swift/using_objective-c_runtime_features_in_swift
- https://xodhks0113.blogspot.com/2019/09/ios-objc-vs-objcmembers.html
- https://wnstkdyu.github.io/2020/01/06/Objective-C%EC%9D%98-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%8B%A4%ED%96%89/
- https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocSelectors.html
'🍎 Apple > Question' 카테고리의 다른 글
[iOS] Remote data를 가져올 때 Data(contentsOf:)를 사용하면 안되는 이유 (1) | 2022.05.17 |
---|---|
[UIKit] dequeueReusableCell (withIdentifier:for:) vs (withIdentifier:) (2) | 2022.04.18 |
[iOS] 왜 오토 레이아웃을 사용할 때는 translatesAutoresizingMaskIntoConstraints = false를 할까? (0) | 2022.01.21 |
[iOS] 왜 UI는 메인 스레드에서 다룰까? (2) | 2022.01.14 |