programing

Swift UI에서 Object Object와 State Object의 차이점은 무엇입니까?

subpage 2023. 8. 27. 09:18
반응형

Swift UI에서 Object Object와 State Object의 차이점은 무엇입니까?

가 만약에 만약에가가 요.ObservableObject스위프트에서는 UI라고 할 수 .@ObservedObject:

class ViewModel: ObservableObject {
    @Published var someText = "Hello World!"
}

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()
    
    var body: some View {
        Text(viewModel.someText)
    }
}

또로는서로.@StateObject:

class ViewModel: ObservableObject {
    @Published var someText = "Hello World!"
}

struct ContentView: View {
    @StateObject var viewModel = ViewModel()

    var body: some View {
        Text(viewModel.someText)
    }
}

하지만 그 둘 사이의 실질적인 차이점은 무엇입니까?둘 중 하나가 다른 것보다 더 낫거나 둘이 완전히 다른 상황이 있습니까?

@관측된 개체

되는 @ObservedObject인스턴스 뷰를 삭제하고 다시 그릴 때마다 다시 생성됩니다.

struct ContentView: View {
  @ObservedObject var viewModel = ViewModel()
}

로 대반로.@Statevariable은 가 다시 그려질 때 값을 유지합니다.

@상태 객체

A @StateObject는 의조니다입의 입니다.@ObservedObject그리고.@State의 예ViewModel보기를 삭제하고 다시 그린 후에도 유지되고 재사용됩니다.

struct ContentView: View {
  @StateObject var viewModel = ViewModel()
}

성능

록비이지만.@ObservedObject 재생성하도록 을 줄 수 . 이 가 되지 . 이는 다음과 같은 경우에 크게 중요하지 않습니다.@ObservedObject복잡하지 않습니다.

@ObservedObject를 사용해야 하는 경우

이제 사용할 이유가 없는 것처럼 보일 수 있습니다.@ObservedObject그래서 그것은 언제 사용되어야 합니까?

@StateObject를 사용하는 보기에서 초기화하는 모든 관찰 가능한 속성에 대해 @StateObject를 사용해야 합니다.ObservableObject 인스턴스가 외부에서 생성되어 이 인스턴스를 사용하는 뷰로 전달되는 경우 @ObservedObject로 속성을 표시합니다.

사용 사례가 너무 많아서 보기에서 관찰 가능한 속성을 다시 만드는 이 좋을 수도 있습니다.그런 경우에는 다음을 사용하는 것이 좋습니다.@ObservedObject.

유용한 링크:

Apple 문서는 초기화하는 이유를 설명했습니다.ObservedObject안전하지 않습니다.

SwiftUI는 언제든지 보기를 만들거나 다시 만들 수 있으므로 지정된 입력 집합으로 보기를 초기화하는 것이 항상 동일한 보기가 되도록 하는 것이 중요합니다.따라서 보기 내에 관찰된 개체를 만드는 것은 안전하지 않습니다.

은 해책은입니다.StateObject.

이와 동시에 문서는 데이터 모델이 진실을 유지할 수 있을 때 뷰(또는 앱/씬)에서 데이터 모델을 생성하여 다른 뷰로 전달하는 방법을 보여주었습니다.

struct LibraryView: View {
    @StateObject var book = Book() // Hold on to the 1 truth
    var body: some View {
        BookView(book: book) // Pass it to another view
    }
}

struct BookView: View {
    @ObservedObject var book: Book // From external source
}

pawello2222의 답변은 뷰 자체가 뷰 모델을 만들 때의 차이점을 잘 설명했지만 뷰 모델이 뷰에 주입될 때의 차이점을 주목하는 것이 중요합니다.

뷰 모델을 뷰에 삽입할 때 뷰 모델이 참조 유형인 한 다음 사이에 차이가 없습니다.@ObservedObject그리고.@StateObject뷰 모델을 뷰에 삽입한 객체는 뷰 모델에 대한 참조도 포함해야 하므로 하위 뷰가 다시 그려질 때 뷰 모델이 삭제되지 않습니다.

class ViewModel: ObservableObject {}

struct ParentView: View {
    @StateObject var viewModel = ViewModel()

    var body: some View {
        ChildView(viewModel: viewModel) // Inject view model into child view
    }
}

// Even if `ChildView` is discarded/redrawn, `ViewModel` is kept
// in memory, since `ParentView` still holds a reference to it.
// `ViewModel` is only released, and hence destroyed, when
// `ParentView` is destroyed/redrawn.
struct ChildView: View {
    @ObservedObject var viewModel: ViewModel
}

다음은 차이점을 설명하는 예입니다.

클릭할 때마다Refresh단추를 채우다StateObjectClass에 대해서만 처음부터 다시 생성됩니다.CountViewObserved이것은 그것을 것을 의미합니다.@Published count속성이 기본값을 가져옵니다.0이럴 때는.

사이의 차이@StateObject그리고.@ObservedObject이상 없습니다.@StateObject관찰된 버전StateObjectClass그것은 결코 정의되지 않기 때문에 그것의 상태를 보존합니다.@ObservedObject버전이 재생성되지 않습니다.그래서 당신은 사용해야 합니다.@StateObject소유자를 위하여ObservableObject.

import SwiftUI

class StateObjectClass: ObservableObject {
    enum ObserverType: String {
        case stateObject
        case observedObject
    }
    
    @Published var count = 0
    let type: ObserverType
    let id = UUID()
    init(type: ObserverType) {
        self.type = type
    }
    deinit {
        print(#function, "type: \(type.rawValue) id: \(id)")
    }
}

struct CountViewState: View {
    @StateObject var state = StateObjectClass(type: .stateObject)
    var body: some View {
        VStack {
            Text("@StateObject's count: \(state.count)")
            Button("ADD 1"){
                state.count += 1
            }
        }
    }
}

struct CountViewObserved: View {
    @ObservedObject var state = StateObjectClass(type: .observedObject)
    var body: some View {
        VStack {
            Text("@ObservedObject's count: \(state.count)")
            Button("Add 1") {
                state.count += 1
            }
        }
    }
}

struct ContentView: View {
    @State private var count = 0
    var body: some View {
        VStack {

            Text("Refresh CounterView's count: \(count)")
            
            Button("Refresh") {
                count += 1
            }

            CountViewState()
                .padding()

            CountViewObserved()
                .padding()

        }
    }
}

@StateObject는 주어진 뷰의 상태이므로 Swift에 의해 인스턴스가 유지됩니다.UI 전체body업데이트합니다.그러나 미리 보기에서 실행할 때는 유지되지 않습니다.

@ObservedObject반면에 단지 주어진 것에 의해 관찰되는 물체입니다.View따라서 Swift에 의해 유지되지 않습니다.UI(외부에서 유지해야 함)View).

다른 말로 하면 - 스위프트처럼 보입니다.UI는 다음을 유지합니다.strong의 언급.@StateObject그리고.unowned의 언급.@ObservedObject.

보존 소스 대 보존되지 않은 소스, 미리 보기 동작 소스, 약 8:30.

다음과 같은 차이점이 있습니다.

@ObservedObject var book: BookModel

그리고.

@StateObject var book: BookModel

@ObservedObject인스턴스를 소유하지 않음book인스턴스의 수명 주기를 관리하는 것은 사용자의 책임입니다.

하지만 관찰 가능한 물체의 수명 주기를 묶고 싶을 때book와 같이 당신의 견해로는.@State사용할 수 있습니다.@StateObject.

이 경우 SwiftUI가 관찰 가능한 개체를 소유하고 생성 및 삭제는 보기의 수명 주기와 연결됩니다.

Swift UI는 보기의 전체 수명 주기 동안 개체를 활성 상태로 유지합니다.

이는 고가의 리소스에 매우 적합하며, 사용자는 이를 만지작거릴 필요가 없습니다.onDisappear더 이상 자원을 방출하지 않습니다.

이 설명은 Swift UI의 WWDC2020 Data Essentials에서 가져온 것입니다.

언급URL : https://stackoverflow.com/questions/62544115/what-is-the-difference-between-observedobject-and-stateobject-in-swiftui

반응형