簡體   English   中英

SwiftUI 視圖不會在單獨的視圖中更新

[英]SwiftUI View doesn't update in a seperate View

我正在使用List來顯示消息的復選標記。 問題是,如果我將復選標記視圖分離到視圖不會更新的子視圖中。 如果我將完全相同的代碼直接放入List它會按預期工作。 我在多個地方使用那個復選標記視圖,所以它需要在一個子視圖中。

例子:

不起作用

List(filteredMessages, id: \.content.uniqueIdentifier) { message in
     DoubleCheckmark(message: message)
}

但這確實有效

List(filteredMessages, id: \.content.uniqueIdentifier) { message in
    HStack(spacing: 0) {
        if message.content.readStatus == .loading {
            Text("loading")
        } else if message.content.readStatus == .sent {
            Image(systemName: "checkmark")
                .resizable()
                .scaledToFit()
                .foregroundColor(message.content.readStatus == .read ? .blue : .gray)
        } else if message.content.readStatus == .received {
            Image(systemName: "checkmark")
                .resizable()
                .scaledToFit()
                .foregroundColor( .gray)

            Image(systemName: "checkmark")
                .resizable()
                .scaledToFit()
                .padding(.leading, -7)
                .foregroundColor(.gray)
        } else if message.content.readStatus == .read {
            Image(systemName: "checkmark")
                .resizable()
                .scaledToFit()
                .foregroundColor(.blue)

            Image(systemName: "checkmark")
                .resizable()
                .scaledToFit()
                .padding(.leading, -7)
                .foregroundColor(.blue)
        } else {

            Text("error")
        }
    }
    .height(11)
    .width(15)
    .yOffset(-1)
}

這是我的DoubleCheckmark視圖:

struct DoubleCheckmark: View {
    var message: Message

    var body: some View {
        HStack(spacing: 0) {
            if message.content.readStatus == .loading {
                Text("loading")
            } else if message.content.readStatus == .sent {
                Image(systemName: "checkmark")
                    .resizable()
                    .scaledToFit()
                    .foregroundColor(message.content.readStatus == .read ? .blue : .gray)
            } else if message.content.readStatus == .received {
                Image(systemName: "checkmark")
                    .resizable()
                    .scaledToFit()
                    .foregroundColor( .gray)

                Image(systemName: "checkmark")
                    .resizable()
                    .scaledToFit()
                    .padding(.leading, -7)
                    .foregroundColor(.gray)
            } else if message.content.readStatus == .read {
                Image(systemName: "checkmark")
                    .resizable()
                    .scaledToFit()
                    .foregroundColor(.blue)

                Image(systemName: "checkmark")
                    .resizable()
                    .scaledToFit()
                    .padding(.leading, -7)
                    .foregroundColor(.blue)
            } else {

                Text("error")
            }
        }
        .height(11)
        .width(15)
        .yOffset(-1)
    }
}

這是我的Message類:

public class Message: NSObject, Codable, NSCoding {
    public var content: MessageContent
    public var fromUser: User
    public var toUser: User

    public init(content: MessageContent, fromUser: User, toUser: User) {
        self.content = content
        self.fromUser = fromUser
        self.toUser = toUser
    }

    enum Keys: String {
        case content, fromUser, toUser
    }

    public func encode(with aCoder: NSCoder) {

        aCoder.encode(content, forKey: Keys.content.rawValue)
        aCoder.encode(fromUser, forKey: Keys.fromUser.rawValue)
        aCoder.encode(toUser, forKey: Keys.toUser.rawValue)
    }

    public required convenience init?(coder aDecoder: NSCoder) {

        let content = aDecoder.decodeObject(forKey: Keys.content.rawValue) as! MessageContent
        let fromUser = aDecoder.decodeObject(forKey: Keys.fromUser.rawValue) as! User
        let toUser = aDecoder.decodeObject(forKey: Keys.toUser.rawValue) as! User

        self.init(content: content, fromUser: fromUser, toUser: toUser)
    }

    public override func isEqual(_ object: Any?) -> Bool {
        if let object = object as? Message {
            return self.content.uniqueIdentifier == object.content.uniqueIdentifier
        } else {
            return false
        }
    }
}

如果您的Message是一個類,那么由於message屬性的相等引用, List很可能不會更新相同消息的行。 嘗試使您的視圖明確符合Equatable並在Message覆蓋相同以進行深入比較

struct DoubleCheckmark: View, Equatable {
    static func == (lhs: DoubleCheckmark, rhs: DoubleCheckmark) -> Bool {
        lhs.message == rhs.message
    }
    ...

class Message: ObservableObject, Equatable {
    static func == (lhs: Message, rhs: Message) -> Bool {
        // compare here all important properties
    }
    ...    

改變這一點,可能還需要明確提到您的自定義視圖是自定義的

List(filteredMessages, id: \.content.uniqueIdentifier) { message in
     DoubleCheckmark(message: message).equatable() // try with & w/o
}

我將 Message class更改為struct並在CoreData 中使用binary data作為數據類型,而不是需要模型符合NSCodingTransformable

它不會更新,因為 Message 不是 ObservableObject。 如果傳遞類實例,則需要將 @ObservedObject 添加到視圖屬性。 否則,SwiftUI 不知道發生了變化。 此外,該類必須使用 @Published 包裝器標記更改的屬性,或者手動調用 objectWillChange.send()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM