Có đúng không khi mong đợi các bản cập nhật nội bộ của trình bao bọc thuộc tính SwiftUI DynamicProperty để kích hoạt cập nhật chế độ xem?


10

Tôi đang cố gắng tạo một trình bao bọc thuộc tính tùy chỉnh được SwiftUI hỗ trợ, có nghĩa là những thay đổi đối với các giá trị thuộc tính tương ứng sẽ gây ra cập nhật cho chế độ xem SwiftUI. Đây là phiên bản đơn giản hóa của những gì tôi có:

@propertyWrapper
public struct Foo: DynamicProperty {
    @ObservedObject var observed: SomeObservedObject

    public var wrappedValue: [SomeValue] {
        return observed.value
    }
}

Tôi thấy rằng ngay cả khi tôi ObservedObjectđược chứa trong trình bao bọc thuộc tính tùy chỉnh của mình, SwiftUI vẫn nắm bắt được các thay đổi SomeObservedObjectmiễn là:

  • Bao bọc tài sản của tôi là một cấu trúc
  • Bao bọc tài sản của tôi phù hợp với DynamicProperty

Thật không may, các tài liệu rất thưa thớt và tôi có một thời gian khó khăn để nói nếu điều này chỉ làm việc không may mắn với việc triển khai SwiftUI hiện tại.

Các tài liệu của DynamicProperty(trong Xcode, không trực tuyến) dường như chỉ ra rằng một thuộc tính đó là một thuộc tính được thay đổi từ bên ngoài khiến chế độ xem được vẽ lại, nhưng không có gì đảm bảo về những gì xảy ra khi bạn tuân thủ các loại của riêng mình với giao thức này.

Tôi có thể mong đợi điều này sẽ tiếp tục hoạt động trong các bản phát hành SwiftUI trong tương lai không?


4
Không rõ những gì mong đợi của chủ đề này ... trả lời cho câu hỏi cuối cùng? Bạn có thực sự tin nếu ai đó trả lời "có, chắc chắn, bạn có thể mong đợi"? ))
Asperi

Câu trả lời:


6

Ok ... đây là cách tiếp cận thay thế để có được điều tương tự ... nhưng vì struct chỉ DynamicPropertyquấn quanh @State(để buộc làm mới lượt xem).

Nó là trình bao bọc đơn giản nhưng cung cấp khả năng bao gồm mọi tính toán tùy chỉnh với làm mới chế độ xem sau ... và như đã nói bằng cách sử dụng các loại chỉ có giá trị.

Đây là bản demo (được thử nghiệm với Xcode 11.2 / iOS 13.2):

DynamicProperty là trình bao bọc trên @State

Đây là mã:

import SwiftUI

@propertyWrapper
struct Refreshing<Value> : DynamicProperty {
    let storage: State<Value>

    init(wrappedValue value: Value) {
        self.storage = State<Value>(initialValue: value)
    }

    public var wrappedValue: Value {
        get { storage.wrappedValue }

        nonmutating set { self.process(newValue) }
    }

    public var projectedValue: Binding<Value> {
        storage.projectedValue
    }

    private func process(_ value: Value) {
        // do some something here or in background queue
        DispatchQueue.main.async {
            self.storage.wrappedValue = value
        }
    }

}


struct TestPropertyWrapper: View {

    @Refreshing var counter: Int = 1
    var body: some View {
        VStack {
            Text("Value: \(counter)")
            Divider()
            Button("Increase") {
                self.counter += 1
            }
        }
    }
}

struct TestPropertyWrapper_Previews: PreviewProvider {
    static var previews: some View {
        TestPropertyWrapper()
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.