SwiftUI에서 @StateObject를 사용할 때 생길 수 있는 오류이다.
@StateObject는 객체가 뷰의 생애주기 동안 한 번만 생성된다는 특징이 있다.
뷰가 갱신되거나 재구성될 때 해당 객체가 계속 유지되도록 보장하는 속성 래퍼이다.
@StateObject를 뷰 안 에서 직접 사용하지 않고, 다른 곳에서 객체에 접근하려고 할 때 문제가 생긴다.
뷰 외부에서 접근하려고 할 때, SwiftUI는 그 객체가 뷰에 제대로 설치되지 않았다는 메시지를 띄운다.
@StateObject가 제대로 선언되지 않거나, 다른 곳에서 @StateObject에 접근하려고 할 때 나는 문제이다.
// 잘못된 예시 (뷰 외부에서 @StateObject에 접근)
@StateObject var myObject = MyObject()
// 올바른 예시 (뷰 내부에서만 사용)
@StateObject private var myObject = MyObject()
객체를 다른 뷰로 전달하고 싶다면 -> @ObservedObject나 @EnvironmentObject
속성래퍼 한번 더 정리하기.
@StateObject
객체를 생성, 소유할 때
선언 된 뷰가 해당 객체의 생명주기를 관리한다.
@StateObject로 만든 객체가 뷰의 LifeCycle 에서 딱 한번만 생성되도록 한다.
= 처음 객체를 만들 때 씀.
다른 곳에서 전달받은 객체를 쓰면 안됨!!!!
@ObservedObject
다른 뷰에서 생성되어 이미 존재하는 객체를 전달받음
전달받은(선언된 뷰)는 이 객체의 LifeCycle 에 관여하지 않는다.
객체의 값이 바뀌면 -> 이 뷰도 갱신됨
예시로는 부모 뷰 하위의 자식 뷰에서 부모뷰로부터 @ObservedObject 로 선언된 객체를 받아서 사용.
@EnvironmentObject
앱 전역에서 공유하는 전역 객체 사용 시
주입 방법 -> .environmentObject()
여러 뷰에서 쉽게 가져다 쓸 수 있음. (접근 가넝)
복잡한 뷰 계층에서 유용함.
주입 안하면 앱 실행하다가 충돌남.
class UserSettings: ObservableObject {
@Published var username: String = "Guest"
}
struct ContentView: View {
@StateObject var settings = UserSettings()
var body: some View {
ChildView()
.environmentObject(settings)
}
}
struct ChildView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
Text("Username: \(settings.username)")
}
}
@Published
ObservedObject 클래스에서 속성을 감지할 때 사용한다.
= 값이 바뀌었을 때 이를 ObservableObject 로 구독 중인 뷰가 자동으로 감지하고 갱신한다.
@Published는 속성 감지, @StateObject/@ObservedObject는 뷰에서 객체 관리
@State 는
해당 뷰 안에서 로컬 상태 관리
SwiftUI 는 이 값을 감시하고 있다가 값이 바뀌면 뷰를 갱신시킴
뷰 내부에서 직접 소유하고 있음.
@Binding 은
외부에서 @State 받은 값으 참조만 함.
값 소유 X 그냥
@State 를 가지고 있던 뷰로부터 상태를 받아 양방향 연결
상위 뷰에서 @State 를 받아서 가지고 있다가
그 값을 바꿔서 상위 뷰에게 값을 넘기고 싶을 때
@Binding 은
단일 값을 바인딩 할 때 사용.
(sheet 열래 말래, modal창 열래 말래 하는 bool 값 때 많이 쓴듯)
이 래퍼의 단점은 여러 개의 바인딩을 넘겨야 할 때 코드가 복잡해지는 것.
iOS 17 부터 도입된
@Bindable 는
Observable 하는 객체 전체를 바인딩해주는 속성래퍼임
Observable 프로토콜 채택이 필수 (예전의 ObservableObject와는 다름!)
@Bindable은 내부 프로퍼티들에 바인딩을 직접 걸 수 있음
객체 전체를 넘기고, 내부 프로퍼티만 바인딩하고 싶을 때
import SwiftUI
import Observation // iOS 17 이상
@Observable
class Profile {
var name = "Jane"
var age = 28
}
struct EditProfileView: View {
@Bindable var profile: Profile
var body: some View {
TextField("Name", text: $profile.name)
Stepper("Age: \(profile.age)", value: $profile.age)
}
}
적재적소에 속성래퍼를 써야한다.
'iOS > ErrorDictionary' 카테고리의 다른 글
Missing package product '패키지이름' (0) | 2025.04.01 |
---|