iOS/ErrorDictionary

Accessing StateObject's object without being installed on a View. This will create a new instance each time

태애니 2025. 4. 22. 01:15
728x90

 

 

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)
    }
}

 

 

 

 

 

적재적소에 속성래퍼를 써야한다.

728x90

'iOS > ErrorDictionary' 카테고리의 다른 글

Missing package product '패키지이름'  (0) 2025.04.01