Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

View does not re-render as new messages arrive in SwiftUI #3519

Closed
vojtabohm opened this issue Dec 2, 2024 · 1 comment
Closed

View does not re-render as new messages arrive in SwiftUI #3519

vojtabohm opened this issue Dec 2, 2024 · 1 comment

Comments

@vojtabohm
Copy link

vojtabohm commented Dec 2, 2024

What did you do?

  1. Created a channel:
func createDirectChannel(with userIds: Set<String>) async throws {
        let chat = try chatClient.makeDirectMessageChat(with: Array(userIds), extraData: [:])
        
        try await chat.get(watch: true)
        chatChannels[userIds] = chat
    }
  1. Navigated to my custom view
struct ChatRoomView: View {
    
    let chat: Chat
    init(userIds: Set<String>) {
        chat = try! ChatService.shared.getDirectChannel(for: userIds)
    }
    ...
}

(the method for getting the channel (btw. why is there no get method for a channel in the state layer?)):

func getDirectChannel(for userIds: Set<String>) throws -> Chat {
        // Retrieve the chat from the dictionary
        if let chat = chatChannels[userIds] {
            return chat
        } else {
            throw ChatError.channelCreationFailed // or handle the error as needed
        }
    }
  1. Render the messages in ChatRoomView:
ForEach(chat.state.messages, id: \.id) {
                        Text($0.text)
                    }

What did you expect to happen?

The list re-renders as new messages arrive.

What happened instead?

The messages are not re-rendered. Even though they are marked as @Published (@Published public internal(set) var messages = StreamCollection<ChatMessage>([])) in the ChatState.swift file @MainActor public final class ChatState: ObservableObject

I also checked that the messages are received, both on the channel by subscribing to events and by placing a breakpoint on the internal observer the ChatState creates (line 207) messagesDidChange: { [weak self] in self?.messages = $0 }. I can confirm all events are received.

GetStream Environment

GetStream Chat version: 4.67.0
GetStream Chat frameworks: None, custom UI
iOS version: 18.0
Swift version: 5.9
Xcode version: 16.1
Device: iPhone 13 mini, iPhone 16 Pro (Simulator)

Additional context

I am aware the documentation available uses Combine but that is outdated and ugly. The @Published property hints that the view should automatically re-render, which would be awesome.

Could anyone point me to what I am doing wrong?

@vojtabohm
Copy link
Author

I realised my mistake. You need to have a @StateObject like this, otherwise the @Published won't work:

@StateObject private var chatState: ChatState

init(userIds: Set<String>) {
        let chat = try! ChatService.shared.getDirectChannel(for: userIds)
        _chatState = StateObject(wrappedValue: chat.state)
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant