SwiftUI View 구조체는 자동으로 @Binding
프로퍼티를 초기화 매개변수로 지정하는 생성자를 만든다. 바인딩은 당연하게도 외부에서 값을 전달받아야 하는 프로퍼티이기 때문이다.
그런데 이렇게 하나라도 바인딩 프로퍼티가 있으면 나만의 생성자를 작성하는 것에서 난관이 있을 수 있다.
예를 보자. 아래는 CustomView
라는 View에 바인딩 프로퍼티가 하나 선언된 예다.
struct CustomView: View {
@Binding var name: String
...
}
앞서 이야기했다시피 바인딩 프로퍼티는 자동으로 생성자에 매개변수로 값을 전달받는 인터페이스를 가진다. 그래서 위의 뷰는 아래와 같은 형태로 인스턴스를 생성해서 사용해야 한다.
struct ContentView: View {
@State private var name = "Noname"
var body: some View {
...
CustomView(name: name)
...
}
}
name
을 전달하는 모습이 보인다.
여기까진 별 문제가 없다. 아주 편하게 반응형 뷰 프로그래밍을 할 수 있다.
문제
이제 본격적으로 원하는 것을 해보자.
인스턴스 생성 도중 추가로 해야 할 일이 있다면 아래와 같이 생성자를 구현할 수 있을 것이다. 아래 예에서 단순하게 생성자에서 뭔가를 콘솔에 찍는 코드를 작성해봤다.
struct CustomView: View {
@Binding var name: String
...
init() {
print("Initializing CustomView...")
}
}
하지만 이 init
생성자의 인터페이스는 원하는 모습이 아니다. 왜냐하면 name
바인딩 프로퍼티의 값을 매개변수로 받아야 정상 동작을 하는 코드인데 그게 없다. 즉 이 생성자는 호출될 일이 없다는 말이다.
그렇다면 생성자에서 매개변수로 바인딩 프로퍼티를 받는 인터페이스로 바꾸면 될 것 같다. 그래서 init
을 아래와 같이 수정했다.
init(name: String) {
print("Initializing CustomView...")
}
그런데 여기서 약간 난관이 발생한다. 위와 같이 선언하면 컴파일 오류가 발생하기 때문이다. 아래 스크린샷처럼 여러 오류 문구를 볼 수 있다.
해결하기
위의 CustomView
의 name
프로퍼티는 @Binding
으로 선언되어 있다. 이 프로퍼티는 일반 프로퍼티와는 다르게 Binding
이라는 Wrapper로 감싸여있다.
그래서 init
생성자에서 Binding
을 이용해 아래와 같이 코드를 작성할 수 있다.
struct CustomView: View {
@Binding var name: String
...
init(name: Binding<String>) {
self.name = name
print("Initializing CustomView...")
}
}
이제 문제는 해결되었다 라고 생각했는데 아니다. 매개변수 인터페이스에서는 이제 오류가 발생하지 않는다. 다만 여기서 self.name = name
코드 부분이 문제가 된다. 아래와 같은 컴파일 오류가 발생한다.
Cannot assign value of type 'String' to type 'Binding<String>'
바인딩은 좀 독특하게 구현이 되어있나 보다. 하긴 Property Wrapper는 뭔가를 감싸서 추가로 해야 할 일을 생략하게 만드는 것이 목표일 테고 바인딩도 그럴 것이다.
다행히도 이 코드의 문제는 쉽게 바로잡을 수 있다. 초기화 하려는 바인딩 프로퍼티의 이름 앞에 밑줄(underscore)를 붙여주면 된다.
struct CustomView: View {
@Binding var name: String
...
init(name: Binding<String>) {
self._name = name
print("Initializing CustomView...")
}
}
self._name
으로 프로퍼티 앞에 밑줄을 붙여놓은 점에 주의해서 보자. 즉 @Binding
으로 선언된 프로퍼티는 내부적으로 동일한 이름 앞에 밑줄을 붙인 프로퍼티를 숨겨서 자동으로 선언한다는 것으로 추측해 볼 수 있다. 그래서 이런 식으로 바인딩 프로퍼티의 값을 초기화하려면 그 숨겨진 프로퍼티 자체를 초기화해야 한다는 말이 된다.
결과적으로 이 코드로 문제도 해결하였고 원하던 바를 이루었다.
이렇게 쓸 일이 과연 자주 있을지는 모르겠지만 의외로 모르니 삽질이 컸던 것 같다. 이렇게 또 삽질로 지식을 습득해간다.
관련된 링크들
'기술적인 이야기 > 애플 플랫폼 개발' 카테고리의 다른 글
아직은 절망스러운(?) Xcode 13 Beta의 Vim 모드 (261) | 2021.06.16 |
---|---|
SwiftUI - self is immutable??? (306) | 2021.05.18 |
앱스토어 업로드 시 ITMS-90034 문제 (381) | 2021.04.09 |
2021년 2월 1일자 앱스토어 리뷰 가이드라인 업데이트 (394) | 2021.02.02 |
iOS 시뮬레이터의 이상한 노란색(?) 문제 (377) | 2021.01.08 |
댓글