Как заставить CoreSpotlight предсказать, кто звонит

Я хочу, чтобы мое устройство прогнозировало, кто мне звонит, на основе индекса внимания людей. Я загрузил информацию о людях, чтобы выделить индекс, и система выдает информацию, когда я ищу, но не когда кто-то звонит. Код ниже делает все это, и я не могу понять, что не так

if people.count > 0 {
    var peopleArray = [CSSearchableItem]()
    var peopleGUIDs = [String]()
    for person in people {
        let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeText as String)

        // Basic AttributeSet setup
        attributeSet.title = person.nameForList
        attributeSet.contentDescription = person.division?.title

        // Add first phone number to AttributeSet
        var phoneNumber: NSString?
        let contacts = Array(person.contacts)
        for contact in contacts {
            if contact.type == "phone" {
                phoneNumber = contact.value as NSString
                break
            }
        }
        if phoneNumber != nil {
            if let preparedNumber = phoneNumber!.removingPercentEncoding {
                attributeSet.phoneNumbers = [preparedNumber]
                attributeSet.supportsPhoneCall = true
            }
        }

        attributeSet.displayName = person.name

        // Add photo number to AttributeSet
        if let photoPath = person.photo {
            let key = SDWebImageManager.shared().cacheKey(for: NSURL(string: photoPath) as URL!)
            let image = SDImageCache.shared().imageFromDiskCache(forKey: key)
            var data = Data()
            if let image = image {
                if let dataFromImage = UIImagePNGRepresentation(image) {
                    data = dataFromImage
                }
            } else {
                data = dataFromImage
            }
            attributeSet.thumbnailData = data
        }

        peoplesGUIDs.append(person.id)

        let item = CSSearchableItem(uniqueIdentifier: person.id, domainIdentifier: "com.it.companySpotlight", attributeSet: attributeSet)
        peopleArray.append(item)
    }

    CSSearchableIndex.default().indexSearchableItems(peopleArray) {  (error) in
        DispatchQueue.main.async(execute: {
            if let error =  error {
                print("Indexing error: \(error.localizedDescription)")
            } else {
                print("Search for people successfully indexed")
            }
        })
    }

}

Кто-нибудь знает, как решить эту проблему?

1 ответ

Решение

Через некоторое время Paulw11 сказал, что мне нужно пользовательское расширение CallKit, поэтому есть решение:

  1. Добавьте новую цель в ваш проект "Расширение CallKIt"
  2. Создайте группы приложений, чтобы предоставить текстовый файл с номером телефона для вашего добавочного номера, потому что там невозможно использовать базы данных
  3. Убедитесь, что ваши контакты в порядке возрастания номеров для лучшей производительности
  4. Записать контакты в файл

    if #available(iOS 10.0, *) {
        let numbers = ["79175870629"]
    
        let labels = ["Stranger name"]
    
        // Replace it with your id
        let groupId = "group.YOUR.ID"
        let container = FileManager.default
            .containerURL(forSecurityApplicationGroupIdentifier: groupId)
        guard let fileUrl = FileManager.default
            .containerURL(forSecurityApplicationGroupIdentifier: groupId)?
            .appendingPathComponent("contacts") else { return }
    
        var string = ""
        for (number, label) in zip(numbers, labels) {
            string += "\(number),\(label)\n"
        }
    
        try? string.write(to: fileUrl, atomically: true, encoding: .utf8)
    
        CXCallDirectoryManager.sharedInstance.reloadExtension(
            withIdentifier: groupId)
    } else {
        // Fallback on earlier versions
    }
    
  5. Затем добавьте класс LineReader к вашему расширению из этого поста.
  6. Этот метод будет вызываться при вызове reloadExtension

    override func beginRequest(with context: CXCallDirectoryExtensionContext) {
    context.delegate = self
    if #available(iOSApplicationExtension 11.0, *) {
        if context.isIncremental {
            addOrRemoveIncrementalBlockingPhoneNumbers(to: context)
            addOrRemoveIncrementalIdentificationPhoneNumbers(to: context)
        } else {
            addAllBlockingPhoneNumbers(to: context)
            addAllIdentificationPhoneNumbers(to: context)
        }
    } else {
        addAllBlockingPhoneNumbers(to: context)
        addAllIdentificationPhoneNumbers(to: context)
    }
    
    
    context.completeRequest()
    

    }

  7. В моем случае я реализовал только addAllIdentificationPhoneNumbers и прочитал там контакты из файла. Вам нужно добавить логику ко всем другим методам, которые были сгенерированы по умолчанию

    guard let fileUrl = FileManager.default
                .containerURL(forSecurityApplicationGroupIdentifier: "group.YOUR.ID")?
                .appendingPathComponent("contacts") else { return }
    
            guard let reader = CBLineReader(path: fileUrl.path) else { return }
            print("\(#function) \(fileUrl)")
            for line in reader {
                autoreleasepool {
                    let line = line.trimmingCharacters(in: .whitespacesAndNewlines)
    
                    var components = line.components(separatedBy: ",")
    
                    guard let phone = Int64(components[0]) else { return }
                    let name = components[1]
    
                    context.addIdentificationEntry(withNextSequentialPhoneNumber: phone, label: name)
                    print(#function + name)
                }
            }
    
  8. Зайдите в Настройки -> Телефон -> Блокировка звонков и идентификация -> включите swift напротив вашего приложения

  9. Протестируйте свое приложение:-) Надеюсь, оно кому-нибудь поможет

Другие вопросы по тегам