0

CXCallDirectoryProvider I block a number when that number call he can not reach me everything is ok.But next time that number calls it is already not in block list and he can call me.How to fix it . CXCallDirectoryManager.sharedInstance.reloadExtension works currectly.

I want that it stays in block list until I manualy remove it from there.

enum LockAndUnlockType {
    case lock
    case unlock
}

class CallDirectoryHandler: CXCallDirectoryProvider {

    static var lockType: LockAndUnlockType = .lock
    static var isBlockingAction = MutableProperty<Bool?>(nil)
    
    override func beginRequest(with context: CXCallDirectoryExtensionContext) {
        context.delegate = self
        // Check whether this is an "incremental" data request. If so, only provide the set of phone number blocking
        // and identification entries which have been added or removed since the last time this extension's data was loaded.
        // But the extension must still be prepared to provide the full set of data at any time, so add all blocking
        // and identification phone numbers if the request is not incremental.
        CallDirectoryHandler.isBlockingAction.value = true
        if context.isIncremental {
            addOrRemoveIncrementalBlockingPhoneNumbers(to: context)
            addOrRemoveIncrementalIdentificationPhoneNumbers(to: context)
        } else {
            addAllBlockingPhoneNumbers(to: context)

            addAllIdentificationPhoneNumbers(to: context)
        }

        context.completeRequest()
    }

    private func addAllBlockingPhoneNumbers(to context: CXCallDirectoryExtensionContext) {
        // Retrieve all phone numbers to block from data store. For optimal performance and memory usage when there are many phone numbers,
        // consider only loading a subset of numbers at a given time and using autorelease pool(s) to release objects allocated during each batch of numbers which are loaded.
        //
        // Numbers must be provided in numerically ascending order.
        let numbers = RealmDataBase.shered.fetchAllObjectsAt(Number.self).uniqued().sorted(by: { $0.phone > $1.phone})
        for phoneNumber in numbers {
            context.addBlockingEntry(withNextSequentialPhoneNumber: CXCallDirectoryPhoneNumber(phoneNumber.phone))
            do {
                try? Realm().write {
                    phoneNumber.isBlocked = true
                }
            }
        }
    }

    private func addOrRemoveIncrementalBlockingPhoneNumbers(to context: CXCallDirectoryExtensionContext) {
        // Retrieve any changes to the set of phone numbers to block from data store. For optimal performance and memory usage when there are many phone numbers,
        // consider only loading a subset of numbers at a given time and using autorelease pool(s) to release objects allocated during each batch of numbers which are loaded.
        switch CallDirectoryHandler.lockType {
        case .lock:
//            guard let number = UserDefaults.standard.string(forKey: "phoneNumber") else { return }
            let numbers = RealmDataBase.shered.fetchAllObjectsAt(Number.self).uniqued().sorted(by: { $0.phone > $1.phone})
            for number in numbers {
                context.addBlockingEntry(withNextSequentialPhoneNumber: CXCallDirectoryPhoneNumber(number.phone))
                do {
                    try? Realm().write {
                        number.isBlocked = true
                    }
                }
            }
        case .unlock:
            let numbers = RealmDataBase.shered.fetchAllObjectsAt(Number.self).uniqued().sorted(by: { $0.phone > $1.phone})
            for number in numbers {
                context.removeBlockingEntry(withPhoneNumber: CXCallDirectoryPhoneNumber(number.phone))
                do {
                    try? Realm().write {
                        number.isBlocked = false
                    }
                }
            }
        }
        // Record the most-recently loaded set of blocking entries in data store for the next incremental load...
    }

    private func addAllIdentificationPhoneNumbers(to context: CXCallDirectoryExtensionContext) {
        // Retrieve phone numbers to identify and their identification labels from data store. For optimal performance and memory usage when there are many phone numbers,
        // consider only loading a subset of numbers at a given time and using autorelease pool(s) to release objects allocated during each batch of numbers which are loaded.
        //
        // Numbers must be provided in numerically ascending order.
        let allPhoneNumbers: [CXCallDirectoryPhoneNumber] = [ 1_877_555_5555, 1_888_555_5555 ]
        let labels = [ "Telemarketer", "Local business" ]

        for (phoneNumber, label) in zip(allPhoneNumbers, labels) {
            context.addIdentificationEntry(withNextSequentialPhoneNumber: phoneNumber, label: label)
        }
    }

    private func addOrRemoveIncrementalIdentificationPhoneNumbers(to context: CXCallDirectoryExtensionContext) {
        // Retrieve any changes to the set of phone numbers to identify (and their identification labels) from data store. For optimal performance and memory usage when there are many phone numbers,
        // consider only loading a subset of numbers at a given time and using autorelease pool(s) to release objects allocated during each batch of numbers which are loaded.
//        let phoneNumbersToAdd: [CXCallDirectoryPhoneNumber] = [ 1_408_555_5678 ]
//        let labelsToAdd = [ "New local business" ]
//
//        for (phoneNumber, label) in zip(phoneNumbersToAdd, labelsToAdd) {
//            context.addIdentificationEntry(withNextSequentialPhoneNumber: phoneNumber, label: label)
//        }
//
//        let phoneNumbersToRemove: [CXCallDirectoryPhoneNumber] = [ 1_888_555_5555 ]
//
//        for phoneNumber in phoneNumbersToRemove {
//            context.removeIdentificationEntry(withPhoneNumber: phoneNumber)
//        }
        switch CallDirectoryHandler.lockType {
        case .lock:
            let numbers = RealmDataBase.shered.fetchAllObjectsAt(Number.self).uniqued().sorted(by: { $0.phone > $1.phone})
            for number in numbers {
                context.addBlockingEntry(withNextSequentialPhoneNumber: CXCallDirectoryPhoneNumber(number.phone))
            }
        case .unlock:
            let numbers = RealmDataBase.shered.fetchAllObjectsAt(Number.self).uniqued().sorted(by: { $0.phone > $1.phone})
            for number in numbers {
                context.removeBlockingEntry(withPhoneNumber: CXCallDirectoryPhoneNumber(number.phone))
            }
        }
        // Record the most-recently loaded set of identification entries in data store for the next incremental load...
    }

}

extension CallDirectoryHandler: CXCallDirectoryExtensionContextDelegate {

    func requestFailed(for extensionContext: CXCallDirectoryExtensionContext, withError error: Error) {
        // An error occurred while adding blocking or identification entries, check the NSError for details.
        // For Call Directory error codes, see the CXErrorCodeCallDirectoryManagerError enum in <CallKit/CXError.h>.
        //
        // This may be used to store the error details in a location accessible by the extension's containing app, so that the
        // app may be notified about errors which occurred while loading data even if the request to load data was initiated by
        // the user in Settings instead of via the app itself.
    }

}
  • hello Tigran! would it be possible to edit your question to show your code, specifically how you add the number to block to the block list? – Michael Dautermann Mar 21 '23 at 13:04
  • Numbers you have registered into the block list stay there until you either perform a delta update to the block list or perform a complete replacement of the block list and do not supply it. As Michael says, please show how your extension performs updates. – Paulw11 Mar 21 '23 at 22:35
  • I added code I do not clearly understand how it works. I understand that every time when you need to add new number into block list you need to reload extention. And onther problem is you can not debug CallDirectoryHandler class – Tigran Vilasyan Mar 22 '23 at 06:58

1 Answers1

0

Because you have to block contact everytime you reload the Extention

Follow the following steps

  • create group of your app and your extension

  • then using that bundle id create new user default and save the numbers that you want to block

    let sharedDefaults = UserDefaults(suiteName: "YOUR GROUP'S BUNDLE ID") sharedDefaults?.set(encodedData, forKey: "blockedList")

  • then using same user default you can get contacts in extension

  • then in beginRequest method block the all number that you get from user default

  • if there is an array of number it must be in ascending order

  • if still facing issue

  • refer following my answer CallKit doesn't block numbers from array