You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Firebase(Objective-C)中实现输入状态指示器?

Got it, let's break down how to implement a typing indicator for your Firebase-powered chat app using Objective-C. This will show when User 1 is composing a message to User 2, and automatically clear the status when they stop typing.

1. Firebase Realtime Database Structure

First, let's define a clean structure to store typing statuses. We'll use a top-level node typingStatuses, where each child is keyed by senderId_recipientId (to avoid duplicate entries for the same sender-recipient pair). Each status entry will track if the user is typing, their ID, and a timestamp for cleanup:

{
  "typingStatuses": {
    "userA_userB": {
      "isTyping": true,
      "senderId": "userA",
      "recipientId": "userB",
      "timestamp": 1700000000
    }
  }
}

2. Send Typing Status (Sender's Side)

On the sender's chat screen, we'll update the typing status as the user types, and set a timer to clear the status if they stop typing for a few seconds.

Step 1: Declare Properties

Add these properties to your chat view controller:

@property (strong, nonatomic) FIRDatabaseReference *typingStatusRef;
@property (strong, nonatomic) NSTimer *typingTimeoutTimer;
@property (copy, nonatomic) NSString *currentSenderId; // Logged-in user's UID
@property (copy, nonatomic) NSString *currentRecipientId; // Chat partner's UID

Step 2: Initialize Firebase Reference

Set up the database reference in viewDidLoad:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Initialize Firebase Realtime Database reference
    self.typingStatusRef = [[FIRDatabase database] referenceWithPath:@"typingStatuses"];
    
    // Replace these with actual user IDs (fetch from Firebase Auth or your user system)
    self.currentSenderId = [[FIRAuth auth].currentUser.uid copy];
    self.currentRecipientId = @"userB"; // Example recipient UID
}

Step 3: Handle Text Input Changes

Link your text field's editing events to update the typing status:

- (void)textFieldDidChangeSelection:(UITextField *)textField {
    // Cancel any existing timeout timer
    [self.typingTimeoutTimer invalidate];
    
    // Generate unique key for the sender-recipient pair
    NSString *statusKey = [self typingStatusKeyForSender:self.currentSenderId recipient:self.currentRecipientId];
    
    // Send "is typing" status to Firebase
    NSDictionary *typingData = @{
        @"isTyping": @YES,
        @"senderId": self.currentSenderId,
        @"recipientId": self.currentRecipientId,
        @"timestamp": @([[NSDate date] timeIntervalSince1970])
    };
    
    [self.typingStatusRef child:statusKey setValue:typingData withCompletionBlock:^(NSError * _Nullable error, FIRDatabaseReference * _Nonnull ref) {
        if (error) {
            NSLog(@"Failed to update typing status: %@", error.localizedDescription);
        }
    }];
    
    // Set timer to clear status after 3 seconds of inactivity
    self.typingTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 
                                                               target:self 
                                                             selector:@selector(clearTypingStatus) 
                                                             userInfo:nil 
                                                              repeats:NO];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    // Clear status immediately when user finishes editing
    [self clearTypingStatus];
    [self.typingTimeoutTimer invalidate];
}

// Helper method to generate unique status key
- (NSString *)typingStatusKeyForSender:(NSString *)senderId recipient:(NSString *)recipientId {
    return [NSString stringWithFormat:@"%@_%@", senderId, recipientId];
}

// Method to clear typing status
- (void)clearTypingStatus {
    NSString *statusKey = [self typingStatusKeyForSender:self.currentSenderId recipient:self.currentRecipientId];
    [self.typingStatusRef child:statusKey removeValueWithCompletionBlock:^(NSError * _Nullable error, FIRDatabaseReference * _Nonnull ref) {
        if (error) {
            NSLog(@"Failed to clear typing status: %@", error.localizedDescription);
        }
    }];
}

3. Listen for Typing Status (Receiver's Side)

On the receiver's chat screen, we'll listen for updates to the typing statuses directed at them, and update the UI accordingly.

Step 1: Declare Listener Property

Add this property to the receiver's chat view controller:

@property (strong, nonatomic) FIRDatabaseQuery *typingStatusQuery;
@property (copy, nonatomic) NSString *currentReceiverId; // Logged-in user's UID
@property (weak, nonatomic) UILabel *typingIndicatorLabel; // Connect this to your UI

Step 2: Start Listening for Status Updates

Add this method to start monitoring typing statuses:

- (void)startListeningForTypingStatus {
    self.currentReceiverId = [[FIRAuth auth].currentUser.uid copy];
    
    // Query all typing statuses where the recipient is the current user
    self.typingStatusQuery = [[self.typingStatusRef queryOrderedByChild:@"recipientId"] queryEqualToValue:self.currentReceiverId];
    
    [self.typingStatusQuery observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
        BOOL isSomeoneTyping = NO;
        NSString *typingSenderId = nil;
        
        // Check all matching status entries
        for (FIRDataSnapshot *childSnapshot in snapshot.children) {
            NSDictionary *statusData = childSnapshot.value;
            if ([statusData[@"isTyping"] boolValue]) {
                isSomeoneTyping = YES;
                typingSenderId = statusData[@"senderId"];
                break; // Handle first typing user (extend for multiple users if needed)
            }
        }
        
        // Update UI to show/hide typing indicator
        if (isSomeoneTyping) {
            // Replace with username fetch if you store user profiles
            self.typingIndicatorLabel.text = [NSString stringWithFormat:@"%@ is typing...", typingSenderId];
            self.typingIndicatorLabel.hidden = NO;
        } else {
            self.typingIndicatorLabel.hidden = YES;
        }
    } withCancelBlock:^(NSError * _Nonnull error) {
        NSLog(@"Failed to listen for typing status: %@", error.localizedDescription);
    }];
}

// Stop listening when the view disappears
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.typingStatusQuery removeAllObservers];
}

Edge Cases to Handle

  • Adjust the timeout timer duration (currently 3 seconds) to match your app's behavior.
  • Clear typing status when the user logs out or closes the chat screen.
  • For group chats, modify the query to listen for all statuses in the group and display multiple typing users.
  • Fetch and display the sender's username instead of their UID by linking to a users node in Firebase.
  • Add error handling for network failures (e.g., retry logic if updating status fails).

内容的提问来源于stack exchange,提问作者Dishant Rajput

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:46:16