0

我正在开发一个适用于 ANCS 外部设备的应用程序。简而言之,设备会检测短信何时进入并将其告知应用程序。然后应用程序将能够通过网络服务 (Twilio) 将消息发送回 SMS 发送者。

当发送 SMS 的人在联系人中时,ANCS 设备只能看到此联系人的姓名,而不是电话号码本身。所以它只向应用程序提供这个可读的名称。如果联系人只有一个姓名(例如:“John”),则搜索联系人及其电话号码非常简单,如下所示:

let title = "John"
let contactStore = CNContactStore()
let predicate = CNContact.predicateForContacts(matchingName: title)
let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactMiddleNameKey, CNContactNicknameKey, CNContactOrganizationNameKey, CNContactPhoneNumbersKey]
var contacts = [CNContact]()
do {
    contacts = try contactStore.unifiedContacts(matching: predicate, keysToFetch: keys as [CNKeyDescriptor])
    if contacts.count == 0 {
        print("No contacts were found matching the given name.")
    }
    else
    {
        print("found \(contacts.count) matches !")
        // from there find the best possible bet and the numbers for this contact
    }
} catch {
    print("Unable to fetch contacts.")
}

但有时人们会为同一个人存储多个不同名字的联系人,例如当一条短信进来时,它可能会说它来自:“约翰或爸爸”——因为它对应于通讯录中的那 2 个联系人。 . (我们都必须在地址簿中处理此类重复)。有时在最坏的情况下可能有 3 个或更多的名字!

这就是我想来的地方:我们如何区分/制作谓词来检查这些联系人。简单的解决方案是将名称拆分为“或”字,但如果这是一个朝鲜语、德语、瑞典语等字怎么办?如果这个词属于一个联系人的名字,比如说:“屋顶上的约翰办公桌”,该怎么办?在最坏的情况下,iOS 会提供本地化的分隔符“或”吗?

有人遇到过这样的问题吗?

4

1 回答 1

0

我终于设法做到了:

  • 1st,我得到了Apple在这个地址上给出的每个翻译单词的列表,对每种语言使用在文件 TelephonyUtilities.lg 中找到的单词

  • 第二,我创建了一个 plist 文件,其中包含每个首选语言键(en、es 等)的所有单词

  • 3、当我有联系人姓名时,我根据手机首选语言抓取正确的字符串,并尝试拆分它...如果找到超过1个拆分结果,则意味着这很可能是两个联系人姓名相同的联系人,因此我获取这些联系人以查找常用电话号码。到目前为止它工作得很好。

一些示例代码来说明(swift 3):

plist 文件是什么样的(完成一个,对谁有帮助):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>en</key>
<string> or </string>
<key>fr</key>
<string> ou </string>
<key>vi</key>
<string> hoặc </string>
<key>hr</key>
<string> ili </string>
<key>hu</key>
<string> vagy </string>
<key>id</key>
<string> atau </string>
<key>it</key>
<string> o </string>
<key>es</key>
<string> o </string>
<key>ar</key>
<string> أو </string>
<key>zh-CN</key>
<string>还是</string>
<key>zh-TW</key>
<string> 或 </string>
<key>sk</key>
<string> alebo </string>
<key>pt</key>
<string> ou </string>
<key>pl</key>
<string> lub </string>
<key>cs</key>
<string> nebo </string>
<key>ca</key>
<string> o </string>
<key>nl</key>
<string> of </string>
<key>fi</key>
<string> tai </string>
<key>da</key>
<string> eller </string>
<key>de</key>
<string> oder </string>
<key>el</key>
<string> ή </string>
<key>he</key>
<string> או </string>
<key>ja</key>
<string>または&lt;/string>
<key>ko</key>
<string> 또는 </string>
<key>ms</key>
<string> atau </string>
<key>no</key>
<string> eller </string>
<key>th</key>
<string> หรือ </string>
<key>uk</key>
<string> чи </string>
<key>tr</key>
<string> veya </string>
<key>ro</key>
<string> sau </string>
<key>ru</key>
<string> или </string>
<key>sv</key>
<string> eller </string>
</dict>
</plist>

获取 or 字串:

private func getOrWord() -> String
{
    var orWord:String = ""

    var languageCode:String = ""
    if (NSLocale.current.languageCode != nil) { languageCode = NSLocale.current.languageCode! }
    var countryCode:String = ""
    if (NSLocale.current.regionCode != nil) { countryCode = NSLocale.current.regionCode! }
    let bothCodes:String = "\(languageCode)-\(countryCode)"

    var propertyListForamt =  PropertyListSerialization.PropertyListFormat.xml //Format of the Property List.
    var plistData: [String: AnyObject] = [:] 
    let plistPath: String? = Bundle.main.path(forResource: "separator", ofType: "plist")! //the path of the data
    let plistXML = FileManager.default.contents(atPath: plistPath!)!
    do { 
        plistData = try PropertyListSerialization.propertyList(from: plistXML, options: .mutableContainersAndLeaves, format: &propertyListForamt) as! [String:AnyObject]

        if (languageCode != "")
        {
            if (plistData[languageCode] != nil)
            {
                orWord = plistData[languageCode] as! String
            }
            else if (plistData[bothCodes] != nil)
            {
                orWord = plistData[bothCodes] as! String
            }
        }

    } catch {
        print("Error reading plist: \(error), format: \(propertyListForamt)")
    }

    return orWord
}

最后得到可能的联系人:

private func searchForContacts(name:String) -> Array<CNContact>
{
    var namesToSearch:Array<String> = []
    var contactsFound:Array<CNContact> = []

    let orWord:String = getOrWord()

    if (orWord == "")
    {
        namesToSearch.append(name)
    }
    else
    {
        namesToSearch = name.components(separatedBy: orWord)
    }

    if (namesToSearch.count > 0)
    {
        let contactStore = CNContactStore()

        for nameSearch in namesToSearch
        {
            let predicateName = CNContact.predicateForContacts(matchingName: nameSearch)

            let keys = [CNContactPhoneNumbersKey]
            var contacts = [CNContact]()
            do {
                contacts = try contactStore.unifiedContacts(matching: predicateName, keysToFetch: keys as [CNKeyDescriptor])
                if (contacts.count > 0)
                {
                    // keep only the ones that have at least 1 phone number
                    for contact in contacts
                    {
                        if (contact.phoneNumbers.count > 0)
                        {
                            contactsFound.append(contact)
                        }
                    }

                }
            } catch {
                // not possible to fetch
            }
        }
    }

    return contactsFound
}
于 2016-10-23T22:14:31.153 回答