1

I am making an app like TrueCaller. I am able to block a number at first but whenever I am updating/adding more number then I need to manually disable and enable call directory plugin in Settings -> Phone -> Call Blocking & Identification to get list updated. I have seen many answers on StackOverflow where people say to call CXCallDirectoryManager.reloadExtension to reload extension via code. But I don't know where to write this code or from where should I call this reloadExtension from my project.

Update -1 Here is how I approached. Below is my code of view controller.

@IBAction func add(_ sender: Any) {
    //let defaults = UserDefaults.standard
    let userDefaults = UserDefaults(suiteName: "group.com.number1")
    var finArray = userDefaults!.object(forKey: "attribute") as? [Int64] ?? [Int64]()
    let number1 = number.text!
    finArray.append(Int64(number1)!)
    print("from main add")
    print(finArray)

    //let userDefaults = UserDefaults(suiteName: "group.com.number1")
    userDefaults!.set(finArray, forKey: "attribute")
    CXCallDirectoryManager.sharedInstance.reloadExtension(withIdentifier: "com.akshat.Blocking-array.Callblockarray", completionHandler: {(error) -> Void in if let error = error {
        print("akshat"+error.localizedDescription)
        }})

}

Here is my code of callkit extension

//  CallDirectoryHandler.swift
import Foundation

import CallKit
import CoreData
class CallDirectoryHandler: CXCallDirectoryProvider {

    override func beginRequest(with context: CXCallDirectoryExtensionContext) {
        context.delegate = self
        print("inside beginrequest")

//        let defaults = UserDefaults(suiteName: "group.com.number1")
//        //(suiteName: "group.tag.number")
//        let array = defaults!.object(forKey: "attribute") as? [Int64] ?? [Int64]()
//        print(array)
        // 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.
        if context.isIncremental {
            print("insideif")
            addOrRemoveIncrementalBlockingPhoneNumbers(to: context)
            print("insideif")
            addOrRemoveIncrementalIdentificationPhoneNumbers(to: context)
        } else {
            addAllBlockingPhoneNumbers(to: context)
            print("inside else")
            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.
        print("func addAllBlockingPhoneNumbers")
        let defaults = UserDefaults(suiteName: "group.com.number1")
        //(suiteName: "group.tag.number")
        var array = defaults!.object(forKey: "attribute") as? [Int64] ?? [Int64]()
        array.sort()
        print(array)
        let allPhoneNumbers: [CXCallDirectoryPhoneNumber] = array
        for phoneNumber in allPhoneNumbers {
            context.addBlockingEntry(withNextSequentialPhoneNumber: phoneNumber)
        }
    }

    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.
        print("addOrRemoveIncrementalBlockingPhoneNumbers")
        let defaults = UserDefaults(suiteName: "group.com.number1")
        //(suiteName: "group.tag.number")
        var array = defaults!.object(forKey: "attribute") as? [Int64] ?? [Int64]()
        array.sort()
        print(array)
        let phoneNumbersToAdd: [CXCallDirectoryPhoneNumber] = array
        for phoneNumber in phoneNumbersToAdd {
            print(phoneNumber)
            context.addBlockingEntry(withNextSequentialPhoneNumber: phoneNumber)
        }

        let phoneNumbersToRemove: [CXCallDirectoryPhoneNumber] = [ 1_877_555_5555 ]
        for phoneNumber in phoneNumbersToRemove {
            context.removeBlockingEntry(withPhoneNumber: phoneNumber)
        }

        // 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.
        print("addAllIdentificationPhoneNumbers")
        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) {
        print(addOrRemoveIncrementalIdentificationPhoneNumbers)
        // 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)
        }

        // 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) {
        print("CXCallDirectoryExtensionContext")
        // 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 occured while loading data even if the request to load data was initiated by
        // the user in Settings instead of via the app itself.
    }

}

But still, this is only working sometimes. Call Directory Extension is taking too long to update new numbers whenever I add them. For eg: If I write number 'A' and press add button then this add function will be called and number 'A' will get blocked. Now if I add one more number let say 'B' then call directory extension is not able to add it and B will not get blocked. And now if add one more number 'C' then all will get blocked. I am really not getting this. I hope someone could help me.

  • Check this it may help :- https://www.raywenderlich.com/701-callkit-tutorial-for-ios :) –  Feb 25 '19 at 06:36
  • You would call it from your main app, not from the extension; You would either call it when you have new data or maybe provide a button to have the user reload it. See https://stackoverflow.com/questions/51461423/how-does-the-call-directory-extension-in-ios-get-updated/51461447#51461447 – Paulw11 Feb 25 '19 at 06:48
  • @iOSTeam I have already read this post. They have not mentioned anything about reloading extension. – Archit Sanghvi Feb 25 '19 at 07:25
  • @Paulw11 It would be a great help if you could provide me exact code and its proper place as I am new to IOS development and don't know how to deal with it. – Archit Sanghvi Feb 25 '19 at 07:28
  • 1
    I can't really tell you the proper place, as that depends on your app; Do the new numbers come from users? From a server? Whenever you have new numbers you should reload the extension. The code is just `CXCallDirectoryManager.sharedInstance.reloadExtension(withIdentifier:"your.extension.bundle.identifier")` – Paulw11 Feb 25 '19 at 07:31
  • @Paulw11 Can you please go through my edits in question and help me about it. – Archit Sanghvi Feb 25 '19 at 17:55
  • Your code looks generally OK. Do you get an error on the console? It may be that you are trying to reload while a reload is already happening. – Paulw11 Feb 25 '19 at 20:04
  • @Paulw11 yes coding is working properly but only sometimes. What we are facing is sometime every numbers are getting blocked and sometimes not. In particular, on every odd number of insertion, all numbers will get blocked and for even number of insertion, it is not. I am really new to IOS development and i got this as my master's project. It would be great if you could help me. – Archit Sanghvi Feb 26 '19 at 17:02
  • You can attach the debugger to your CallKit extension code to see what it is doing. You can set breakpoints and step through to see if you get any errors and what data you have. – Paulw11 Feb 26 '19 at 19:25

0 Answers0