import Combine
import StreamFeeds
class MyViewController: UIViewController {
@State private var cancellables = Set<AnyCancellable>()
let feedsClient: FeedsClient
override func viewDidLoad() {
super.viewDidLoad()
setupEventListening()
}
private func setupEventListening() {
feedsClient.eventPublisher
.sink { event in
self.handleEvent(event)
}
.store(in: &cancellables)
}
private func handleEvent(_ event: Event) {
switch event {
case let activityEvent as ActivityAddedEvent:
print("π New activity: \(activityEvent.activity.id)")
updateFeedUI()
case let pollEvent as PollClosedFeedEvent:
print("π Poll closed: \(pollEvent.poll.id)")
refreshPollData()
case let commentEvent as CommentAddedEvent:
print("π¬ New comment: \(commentEvent.comment.id)")
updateCommentsUI()
case let reactionEvent as ActivityReactionAddedEvent:
print("π Reaction added: \(reactionEvent.reaction.kind)")
updateReactionsUI()
case let followEvent as FollowCreatedEvent:
print("π₯ New follow: \(followEvent.follow.target)")
updateFollowCount()
case let bookmarkEvent as BookmarkAddedEvent:
print("π Bookmark added: \(bookmarkEvent.bookmark.id)")
updateBookmarksUI()
case let feedEvent as FeedCreatedEvent:
print("π Feed created: \(feedEvent.fid)")
refreshFeedList()
case let connectedEvent as ConnectedEvent:
print("π Connected to Stream with ID: \(connectedEvent.connectionId)")
case let errorEvent as ConnectionErrorEvent:
print("β Connection error: \(errorEvent.error)")
handleConnectionError()
default:
print("π‘ Received event: \(type(of: event))")
}
}
}
Activity Feeds V3 is in closed alpha β do not use it in production (just yet).
Event Handling
This document explains how to listen to real-time events from Stream Feeds using the FeedsClient
event publisher.
Overview
The FeedsClient
provides two ways to listen to events:
- All Events: Listen to all events and handle them with type checking
- Specific Event Types: Listen to only specific event types for type-safe handling
Listening to All Events
Use the main eventPublisher
to receive all events and handle them with type checking:
Listening to Specific Event Types
For type-safe event handling, use the generic eventPublisher(for:)
method:
class ActivityHandler {
private var cancellables = Set<AnyCancellable>()
let feedsClient: FeedsClient
init(feedsClient: FeedsClient) {
self.feedsClient = feedsClient
setupActivityListeners()
}
private func setupActivityListeners() {
// Listen only to activity added events
feedsClient.eventPublisher(for: ActivityAddedEvent.self)
.sink { activityEvent in
print("New activity: \(activityEvent.activity.id)")
self.handleNewActivity(activityEvent)
}
.store(in: &cancellables)
// Listen only to activity updated events
feedsClient.eventPublisher(for: ActivityUpdatedEvent.self)
.sink { activityEvent in
print("Activity updated: \(activityEvent.activity.id)")
self.handleActivityUpdate(activityEvent)
}
.store(in: &cancellables)
// Listen only to activity deleted events
feedsClient.eventPublisher(for: ActivityDeletedEvent.self)
.sink { activityEvent in
print("Activity deleted: \(activityEvent.activity.id)")
self.handleActivityDeletion(activityEvent)
}
.store(in: &cancellables)
}
private func handleNewActivity(_ event: ActivityAddedEvent) {
// Handle new activity
}
private func handleActivityUpdate(_ event: ActivityUpdatedEvent) {
// Handle activity update
}
private func handleActivityDeletion(_ event: ActivityDeletedEvent) {
// Handle activity deletion
}
}
Multiple Event Type Listeners
You can set up multiple listeners for different event types:
class FeedManager {
private var cancellables = Set<AnyCancellable>()
let feedsClient: FeedsClient
init(feedsClient: FeedsClient) {
self.feedsClient = feedsClient
setupEventListeners()
}
private func setupEventListeners() {
// Activity events
feedsClient.eventPublisher(for: ActivityAddedEvent.self)
.sink { [weak self] event in
self?.handleActivityAdded(event)
}
.store(in: &cancellables)
// Comment events
feedsClient.eventPublisher(for: CommentAddedEvent.self)
.sink { [weak self] event in
self?.handleCommentAdded(event)
}
.store(in: &cancellables)
// Poll events
feedsClient.eventPublisher(for: PollVoteCastedFeedEvent.self)
.sink { [weak self] event in
self?.handlePollVote(event)
}
.store(in: &cancellables)
// Connection events
feedsClient.eventPublisher(for: ConnectedEvent.self)
.sink { [weak self] event in
self?.handleConnection(event)
}
.store(in: &cancellables)
}
}
SwiftUI Integration
Hereβs how to listen to events in SwiftUI:
struct FeedView: View {
@StateObject private var viewModel: FeedViewModel
@State private var cancellables = Set<AnyCancellable>()
var body: some View {
List(viewModel.activities) { activity in
ActivityRow(activity: activity)
}
.onAppear {
setupEventListening()
}
.onDisappear {
cancellables.removeAll()
}
}
private func setupEventListening() {
viewModel.feedsClient.eventPublisher(for: ActivityAddedEvent.self)
.receive(on: DispatchQueue.main)
.sink { event in
viewModel.addActivity(event.activity)
}
.store(in: &cancellables)
viewModel.feedsClient.eventPublisher(for: ActivityUpdatedEvent.self)
.receive(on: DispatchQueue.main)
.sink { event in
viewModel.updateActivity(event.activity)
}
.store(in: &cancellables)
}
}
Available Event Types
Below is a comprehensive table of all available event types and their descriptions:
Event Name | Description |
---|---|
Activity Events | |
ActivityAddedEvent | Fired when a new activity is added to a feed |
ActivityUpdatedEvent | Fired when an activity is modified |
ActivityDeletedEvent | Fired when an activity is removed |
ActivityRemovedFromFeedEvent | Fired when an activity is removed from a specific feed |
ActivityMarkEvent | Fired when activities are marked as read/seen |
ActivityPinnedEvent | Fired when an activity is pinned to the top |
ActivityUnpinnedEvent | Fired when an activity is unpinned |
Comment Events | |
CommentAddedEvent | Fired when a new comment is added to an activity |
CommentUpdatedEvent | Fired when a comment is modified |
CommentDeletedEvent | Fired when a comment is removed |
Reaction Events | |
ActivityReactionAddedEvent | Fired when a reaction is added to an activity |
ActivityReactionDeletedEvent | Fired when a reaction is removed from an activity |
CommentReactionAddedEvent | Fired when a reaction is added to a comment |
CommentReactionDeletedEvent | Fired when a reaction is removed from a comment |
Poll Events | |
PollClosedFeedEvent | Fired when a poll is closed |
PollDeletedFeedEvent | Fired when a poll is deleted |
PollUpdatedFeedEvent | Fired when a poll is modified |
PollVoteCastedFeedEvent | Fired when a vote is cast |
PollVoteChangedFeedEvent | Fired when a vote is changed |
PollVoteRemovedFeedEvent | Fired when a vote is removed |
Feed Events | |
FeedCreatedEvent | Fired when a new feed is created |
FeedUpdatedEvent | Fired when a feed is modified |
FeedDeletedEvent | Fired when a feed is deleted |
FeedGroupChangedEvent | Fired when a feed group is modified |
FeedGroupDeletedEvent | Fired when a feed group is deleted |
Member Events | |
FeedMemberAddedEvent | Fired when a member is added to a feed |
FeedMemberRemovedEvent | Fired when a member is removed from a feed |
FeedMemberUpdatedEvent | Fired when a memberβs role/permissions change |
Follow Events | |
FollowCreatedEvent | Fired when a follow relationship is created |
FollowDeletedEvent | Fired when a follow relationship is removed |
FollowUpdatedEvent | Fired when follow settings are modified |
Bookmark Events | |
BookmarkAddedEvent | Fired when an activity is bookmarked |
BookmarkDeletedEvent | Fired when a bookmark is removed |
BookmarkUpdatedEvent | Fired when bookmark metadata is modified |
Connection Events | |
ConnectedEvent | Fired when successfully connected to WebSocket |
ConnectionErrorEvent | Fired when connection fails or errors occur |
HealthCheckEvent | Fired when health check is received |