iOS社交应用基于Firebase实现用户屏蔽功能的方法问询
Hey there, let’s walk through exactly how to build a solid user blocking system for your iOS social app—this will not only get you past Apple’s review but also cover all the scenarios you mentioned: hiding your profile from blocked users, filtering search results, blocking incoming messages, and more.
1. Data Layer Setup: Track Block Relationships
First, you need a way to store who’s blocked whom. Here are two common approaches depending on your backend:
Option 1: Core Data (Local/Backend Sync)
If you’re using Core Data, add a BlockedUser entity to your model with two string fields: blockerUserId (the user doing the blocking) and blockedUserId (the user being blocked). Add a unique constraint to avoid duplicate blocks.
// Core Data Entity Example class BlockedUser: NSManagedObject { @NSManaged var blockerUserId: String @NSManaged var blockedUserId: String }
Option 2: BaaS (Firebase, Supabase, etc.)
For backend-as-a-service tools like Firebase, create a blockedUsers collection. Each document uses the blocker’s user ID as the document key, and contains an array blockedIds of all users they’ve blocked. This makes querying fast.
// Firebase: Block a User func blockUser(blockedUserId: String, currentUserId: String) async throws { let db = Firestore.firestore() try await db.collection("blockedUsers") .document(currentUserId) .updateData([ "blockedIds": FieldValue.arrayUnion([blockedUserId]) ]) }
2. Core Logic: Block Access Across Key Features
Now let’s tackle the specific scenarios you care about:
Filter Search Results
When a user searches for other users, first fetch their blocked list, then exclude those users from the search results.
// Firebase: Filter Search Results to Exclude Blocked Users func searchUsers(query: String, currentUserId: String) async throws -> [User] { let db = Firestore.firestore() // Fetch current user's blocked list let blockedDoc = try await db.collection("blockedUsers").document(currentUserId).getDocument() let blockedIds = blockedDoc.data()?["blockedIds"] as? [String] ?? [] // Run search query, excluding blocked users let snapshot = try await db.collection("users") .whereField("username", isGreaterThanOrEqualTo: query) .whereField("username", isLessThanOrEqualTo: query + "\u{f8ff}") .whereField("userId", notIn: blockedIds) .getDocuments() return snapshot.documents.compactMap { try? $0.data(as: User.self) } }
Block Incoming Messages & Hide Threads
- Prevent blocked users from sending you messages: Check if the recipient has blocked the sender before allowing a message to send.
- Hide conversations with blocked users from your message list.
// Firebase: Block Messages from Blocked Users func sendMessage(to recipientId: String, content: String, currentUserId: String) async throws { // Check if recipient has blocked current user let recipientBlockedDoc = try await Firestore.firestore().collection("blockedUsers").document(recipientId).getDocument() let recipientBlockedIds = recipientBlockedDoc.data()?["blockedIds"] as? [String] ?? [] if recipientBlockedIds.contains(currentUserId) { throw NSError(domain: "AppError", code: 403, userInfo: [NSLocalizedDescriptionKey: "You've been blocked by this user and can't send messages."]) } // Proceed with normal message send logic... } // Fetch Message Threads, Excluding Blocked Users func getMessageThreads(currentUserId: String) async throws -> [MessageThread] { let blockedIds = try await getBlockedIds(for: currentUserId) let snapshot = try await Firestore.firestore().collection("messageThreads") .whereField("participantIds", arrayContains: currentUserId) .getDocuments() return snapshot.documents.compactMap { threadDoc in guard let thread = try? threadDoc.data(as: MessageThread.self) else { return nil } // Skip threads that include blocked users let hasBlockedUser = thread.participantIds.contains { blockedIds.contains($0) } return hasBlockedUser ? nil : thread } }
Hide Blocked Users’ Content & Profiles
- Filter out posts from blocked users in your feed.
- If a blocked user tries to view your profile (or vice versa), show a clear error message instead of content.
// Fetch Feed, Excluding Blocked Users' Posts func fetchFeed(currentUserId: String) async throws -> [Post] { let blockedIds = try await getBlockedIds(for: currentUserId) let snapshot = try await Firestore.firestore().collection("posts") .order(by: "createdAt", descending: true) .getDocuments() return snapshot.documents.compactMap { postDoc in guard let post = try? postDoc.data(as: Post.self) else { return nil } return blockedIds.contains(post.publisherId) ? nil : post } } // Handle Profile Visits for Blocked Users func handleProfileVisit(userId: String, currentUserId: String) async throws { let blockedIds = try await getBlockedIds(for: currentUserId) if blockedIds.contains(userId) { // Show a blocked message or navigate back throw NSError(domain: "AppError", code: 403, userInfo: [NSLocalizedDescriptionKey: "This user has been blocked."]) } // Load profile content normally... }
3. UI Touches: Make It User-Friendly
- Add a "Block User" button on user profiles and chat screens. After tapping, update the UI immediately (e.g., hide the chat thread, replace the profile with a blocked message).
- When a blocked user tries to interact with your content, show a clear, localized error message so they understand why they can’t proceed.
4. Edge Cases to Cover
- Mutual Blocks: If User A blocks User B and vice versa, ensure neither can see the other’s content or send messages.
- Unblock Functionality: Add an "Unblock" option that removes the user from the blocked list and restores access to their content.
- Performance: Cache the blocked list locally (e.g., in
UserDefaultsor Core Data) to avoid repeated backend calls, especially for frequent actions like scrolling the feed.
内容的提问来源于stack exchange,提问作者Edison Espinosa

