iOS 프로그래밍을 하는 도중 ViewController
에 아래와 같은 메소드를 만들었습니다.
class ViewController: UIViewController {
private var button = UIButton()
@objc
func buttonDidTap() { ... }
}
그런데 동일한 이름을 ViewController 내부에 있는 UIView 서브클래스에도 추가했습니다.
class MyView: UIView {
@objc
func buttonDidTap() { ... }
}
이 상태에서 ViewController에 viewDidLoad
에 버튼 액션을 등록했습니다.
class ViewController: UIViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(
self,
action: #selector(myView.buttonDidTap),
for: .touchUpInside)
}
...
}
그런데 신기한 일이 발생했습니다. 저는 분명히 myView
의 액션메소드를 호출했는데, ViewController의 액션메소드가 호출되었습니다. 그래서 분명 셀렉터의 특정 속성때문이라고 생각했고 이렇게 글을 작성해봅니다^_^
공식문서에 가보면 정의가 적혀있지 않습니다…
링크 : Apple Developer Documentation
[image:9C16BDEF-C01A-4BE1-82AC-030112CEF00C-664-0000005B90F062BC/07EB4D08-DA9A-451D-81D7-FB8306190916.png]
그래서 다른 글을 통해서 Seletor를 유추해야합니다.
그 중에서 해당 공식문서에 내용이 적혀있습니다.
링크 : Apple Developer Documentation
옵젝-C 에서 셀렉터는 옵젝-C 메소드의 “이름”을 참조하는 타입입니다. 스위프트에서는 옵젝-C의 셀렉터를 셀렉터 구조체로 나타냅니다.(구조체라는 뜻이죠.) 그리고
#selector
를 붙여서 해당타입으로 생성합니다.
여기서 알아야 하는 정보는
#selector
라고 작성해야한다.이제 제가 겪었던 버그기 조금은 이해가 되네요. 어떤 파일에 위치하더라도, 결국은 “이름” 만 신경쓰기 때문에 이름이 같다면, 먼저 접근된 이름의 액션 메소드가 호출되었던 것이죠.
(ViewController의 buttonDidTap 메소드가 먼저 등록되어버린 것이죠.)
정리하겠습니다
셀렉터란, 함수를 선택하는 역할을 가진 (Swift에서) 구조체 이다.
오케이.
그러면 이친구는 언제사용하면 좋을가요?
UIKit에서 옵젝-C 런타임으로 실행되고 있는 경우, 셀렉터 인스턴스를 생성하기 위해서 사용합니다.
말이 조금 복잡한데,
이미 구현된 메소드가 셀렉터를 요구하면 그때! 사용하시면 됩니다.
우리가 코드로 액션을 추가하면 사용하는 그 메소드
addTarget(…)
이 메소드 말입니다. 이때 사용하면 됩니다.
그리고 제가 겪었던 문제는 정확히 말하면 셀렉터의 문제라기보다는, Function Notaition
에서 발생한 문제입니다.
쉽게말하면,
함수 표현법이 있는데, 그 규칙을 지키지 않다보니 런타임 에러로 발생한 겁니다.
해당 정보는 잘 설명해주신 글이 있어서 링크첨부할게요!
Swift Function Notation - Functions :: 우짱의 iOS 블로그