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

iOS应用开发:通讯录已知联系人拦截功能实现求助

Blocking Known Contacts in Your iOS App

Hey there! Let's work through how to block known contacts (from the user's phone book) in your iOS app—since you already have the unknown sender part sorted, let's focus on the known contact logic. Here's a step-by-step approach:

1. First, Get Contacts Access Permission

You need to request access to the user's contacts first, since you'll need to pull their existing contact list to match against incoming senders. Use the Contacts framework for this:

import Contacts

func requestContactsAccess() {
    let contactStore = CNContactStore()
    contactStore.requestAccess(for: .contacts) { granted, error in
        if granted {
            // Permission approved—fetch all contacts next
            DispatchQueue.main.async {
                self.fetchAllKnownContacts()
            }
        } else {
            // Handle permission denial (show an alert to the user, etc.)
            print("Contacts access denied: \(error?.localizedDescription ?? "Unknown error")")
        }
    }
}

2. Fetch & Store Known Contact Identifiers

Once you have permission, extract all phone numbers from the user's contacts, normalize them (to avoid issues with formatting like spaces or parentheses), and store them in a set for quick lookups.

// Store this in a shared location (like UserDefaults with App Groups, since extensions need access)
var knownContactNumbers: Set<String> = []

func fetchAllKnownContacts() {
    let contactStore = CNContactStore()
    let keysToFetch = [CNContactPhoneNumbersKey] as [CNKeyDescriptor]
    let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch)
    
    do {
        try contactStore.enumerateContacts(with: fetchRequest) { contact, _ in
            // Extract each phone number and normalize it
            for phoneNumber in contact.phoneNumbers {
                let rawNumber = phoneNumber.value.stringValue
                let normalizedNumber = self.normalizePhoneNumber(rawNumber)
                self.knownContactNumbers.insert(normalizedNumber)
            }
        }
        // Save the set to a shared store (for extension access)
        if let sharedDefaults = UserDefaults(suiteName: "com.yourcompany.yourapp.group") {
            sharedDefaults.set(Array(self.knownContactNumbers), forKey: "KnownContactNumbers")
        }
    } catch {
        print("Failed to fetch contacts: \(error.localizedDescription)")
    }
}

// Helper to normalize phone numbers (removes non-digit characters)
private func normalizePhoneNumber(_ number: String) -> String {
    return number.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
}

3. Integrate with Your Interception Logic

Now, depending on what you're intercepting (SMS, calls, etc.), you'll match the incoming sender against your stored known contacts. Let's use SMS interception as an example (using iOS's IdentityLookup framework for message filtering):

Set Up a Message Filter Extension

  1. Add a new "Message Filter Extension" target to your Xcode project.
  2. In the extension's main class, implement the query handler to check if the sender is a known contact:
import IdentityLookup

class MessageFilterHandler: ILMessageFilterExtension {
    override func handle(_ queryRequest: ILMessageFilterQueryRequest, context: ILMessageFilterExtensionContext, completion: @escaping (ILMessageFilterQueryResponse) -> Void) {
        guard let sender = queryRequest.sender else {
            completion(ILMessageFilterQueryResponse())
            return
        }
        
        // Normalize the sender's number to match our stored contacts
        let normalizedSender = normalizePhoneNumber(sender)
        
        // Fetch the known numbers from shared UserDefaults
        guard let sharedDefaults = UserDefaults(suiteName: "com.yourcompany.yourapp.group"),
              let savedNumbers = sharedDefaults.array(forKey: "KnownContactNumbers") as? [String],
              let knownNumbers = Set(savedNumbers) as? Set<String> else {
            completion(ILMessageFilterQueryResponse())
            return
        }
        
        // Decide action: block if it's a known contact
        let response = ILMessageFilterQueryResponse()
        response.action = knownNumbers.contains(normalizedSender) ? .block : .allow
        
        completion(response)
    }
    
    private func normalizePhoneNumber(_ number: String) -> String {
        return number.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
    }
}

Key Notes to Remember

  • App Groups: Since your main app and extension run in separate processes, use App Groups to share the known contact list. Enable this in your Xcode project's Signing & Capabilities tab for both targets.
  • Permissions: Don't forget to add the NSContactsUsageDescription to your Info.plist to explain why you need contacts access.
  • Testing: Message filtering extensions only work on real iOS devices, not simulators. You'll need to test on a physical phone.
  • For Call Interception: If you're blocking calls instead of SMS, use the CallKit framework similarly—fetch known contacts, match incoming callers, and use CXCallDirectoryManager to block them.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 08:33:12