Home > AI > IOS > SwiftUI >

ChatView example

  1. ChatViewModel needs to be @EnvironmentObject so that the combine effect can be reflected in multiple views. If set to @ObservedObject, then SwiftUI cannot capture the change.

Example

struct ChatModel: Hashable {
    var message: String
    var avator: String
    var sendByMe: Bool
}

import SwiftUI

struct ChatView: View {
    @EnvironmentObject var model: ChatViewModel
    
    var body: some View {

        VStack {
            
            List {
                ForEach(model.messages, id: \.self) { msg in
                    ChatRowView(msgModel: msg)
                }
            }
            .listStyle(SidebarListStyle())
            .frame(minHeight: 0, maxHeight: .infinity)
            

            ChatButtomView()
        }
    }
}



struct ChatRowView: View {
    @EnvironmentObject var home: HomeGlobal
    
    var msgModel: ChatModel
    
    
    @ViewBuilder
    var body: some View {
        if msgModel.sendByMe {
            HStack {
                Spacer()
                Text(msgModel.message)
                    .padding(home.defaultPadding/3)
                    .font(home.fontBody)
                    .background(Color.green)
                    .cornerRadius(6)
                Image(msgModel.avator)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: home.defaultPadding*2, height: home.defaultPadding*2)
            }
        } else {
            HStack {
                Image(msgModel.avator)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: home.defaultPadding*2, height: home.defaultPadding*2)
                Text(msgModel.message)
                    .padding(home.defaultPadding/3)
                    .font(home.fontBody)
                    .background(Color.white)
                    .cornerRadius(6)
                Spacer()
            }
        }
    }
}


struct ChatButtomView: View {
    @EnvironmentObject var home: HomeGlobal
    @EnvironmentObject var model: ChatViewModel
    @State var msgText: String = ""
    
    var body: some View {
        HStack {
            Image(systemName: "speaker.3")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: home.defaultPadding*1.5)
            
            TextField("Input message", text: $msgText)
                .frame(height: home.defaultPadding*2)
                .background(Color.white)
                .cornerRadius(home.cornerRadius)
                
            
            Image(systemName: "smiley")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: home.defaultPadding*1.5)
                .padding(.trailing, home.defaultPadding)
            
            Button(action: {
                if msgText != "" {
                    sendMsg(msg: msgText)
                }
               
            }, label: {
                Image(systemName: "plus.circle")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: home.defaultPadding*1.5)
            })
        }
        .padding(.top, home.defaultPadding/2)
        .padding(.horizontal)
        .padding(.bottom, home.defaultPadding*2)
        .background(Color.gray.opacity(0.2))
//        .offset(y: -home.defaultPadding/2)
    }
    
    
    func sendMsg(msg: String) {
        let newMsg = ChatModel(message: msg, avator: "avator6", sendByMe: true)
        model.sendMessage(msg: newMsg)
        msgText = ""
    }
}


import Foundation
import SwiftUI
import Combine

class ChatViewModel: ObservableObject {
    @Published var messages = [
        ChatModel(message: "Hello.", avator: "avator1", sendByMe: false),
        ChatModel(message: "I had breakfast.", avator: "avator2", sendByMe: false),
        ChatModel(message: "I slept very well.", avator: "avator3", sendByMe: false)
    ]
    
    var didChange = PassthroughSubject<Void, Never>()
    func sendMessage(msg: ChatModel) {
        messages.append(msg)
        didChange.send()
    }
}

Leave a Reply