SwiftUI 从数组中返回不同类型的对象

Mat*_*son 1 list swift swiftui

我有一个包含不同类型消息的数组:

let chatMessagesArray = [
    TextMessage(direction: "Incoming", timestamp: 1589463871, senderID: "Bob", destinationID: "Sally", message: "I was sent this message", deliveryStatus: "Delivered", deliveryTimestamp: 1589463871),
    TextMessage(direction: "Outbound", timestamp: 1589467569, senderID: "Sally", destinationID: "Bob", message: "I sent this message", deliveryStatus: "Delivered", deliveryTimestamp: 1589467622),
    ImageMessage(direction: "Incoming", timestamp: 1589485467, senderID: "Bob", destinationID: "Sally", imageURL: "http://Image.Full.URL", thumbnailURL: "https://thumbnail.image.url", deliveryStatus: "Delivered", deliveryTimestamp:1589485467),
] as [Any] <-- Is Any the best choice?
Run Code Online (Sandbox Code Playgroud)

每种类型的消息都有自己的视图:

struct TextMessageView: View {
    var currentMessage: TextMessage
    var body: some View {
        HStack(alignment: .bottom, spacing: 15, content: {
            if(currentMessage.direction == "Incoming"){
                Text(currentMessage.message)
                .padding()
                    .background(Color.init(red: 0.8, green: 0.8, blue: 0.8))
                //.background(Color.gray)
                .cornerRadius(30)
            } else {
                Text(currentMessage.message)
                .foregroundColor(Color.white)
                .padding()
                .background(Color.green)
                .cornerRadius(30)

            }

        })
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的列表视图中,我希望能够根据消息类型调用正确的视图TextMessage || ImageMessage || ...

List{
    ForEach(chatMessagesArray){chatMessageRow in
        if(chatMessageRow  === TextMessage){ <-- What do I put here?
            TextMessageView(currentMessage: chatMessageRow)
        } else if(chatMessageRow === ImageMessage){
        ImageMessageView(currentMessage: chatMessageRow)
    }
}
Run Code Online (Sandbox Code Playgroud)

阅读消息类型并呈现正确视图的最佳方式是什么?有没有更好的方法来存储和检索数据?谢谢

Ale*_*kov 6

我认为最好的解决方案是使用枚举。像这样的东西。

enum Message {
   case Text(TextMessage)
   case Image(ImageMessage)

   var textMessage: TextMessage? {
       guard case let .text(message) = self else { return nil }
       return message
   }

   var imageMessage: ImageMessage? {
       guard case let .image(message) = self else { return nil }
       return message
   }
}

let chatMessageArray:[Message] = [.text(TextMessage(...)), .image(ImageMessage(...)), ...]

List{
    ForEach(Array(chatMessagesArray.enumerated()), id: \.offset) { _, message in
        self.view(for: message)
    }
}

func view(for message: Message) -> some View {
    return Group {
        if message.textMessage != nil {
            TextMessageView(textMessage: message.textMessage!)
        } else {
            ImageMessageView(imageMessage: message.imageMessage!)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)