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:

  1. All Events: Listen to all events and handle them with type checking
  2. 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:

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))")
        }
    }
}

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
ActivityRestoredEvent Fired when an activity is restored
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

Server-side webhooks

Webhooks are configured with your API secret, so they belong on your backend rather than in the app you ship. Setting up an endpoint, verifying signatures, retries and event failover are covered under Event handling in the server-side docs, with the full transport reference in the platform webhooks guide.

Add Chat to my app: getstream.io/SKILL.md

The fastest way to build with Stream. Start a new project or improve an existing one. Full CLI and documentation integration out of the box.


Ask your agent:

/stream Build me a Social App with Feeds and Moderation.
/stream Any livestream calls running?
/stream Feeds iOS v3: <Your Question>