gpt4 book ai didi

ios - 在 TableView 上显示具有特殊字符的联系人时遇到问题

转载 作者:行者123 更新时间:2023-11-28 07:55:45 25 4
gpt4 key购买 nike

我在填充表格 View 时遇到问题。目前,我正在创建电话簿。此电话簿将仅包含在联系人框架的帮助下获取的联系人。这些联系人按字母顺序分成多个部分。

遗憾的是,虽然我的联系人在表格 View 中按字母顺序很好地显示,但我的应用程序崩溃了,因为我没有考虑联系人在他的名字和姓氏中可能具有的所有可能性。 (假设使用标准英语字母表,没有变音符号、符号、数字或任何其他内容)

我一直在尝试实现如何确保考虑到表情符号、不同语言和特殊字符的方法。我还没有找到任何好的解决方案。

让我向您介绍我的代码以加强我的解释:

首先,我创建了一个 ExpandableNames 结构:

struct ExpandableNames{
var isExpanded: Bool
var contacts: [Contact]
}

struct Contact {
let contact: CNContact
}

isExpanded 只是一个状态,表示该联系人所在的部分是已展开还是已关闭。

现在,我创建了这两个数组来填充我的行和部分:

var array2d = Array<[Contact]>(repeating: [Contact](), count: 27)
var twoDimensionalArray = [ExpandableNames]()

注意:27 是字母表中字母的数量加上数字、表情符号和其他特殊字符的部分。

完成此设置后,我创建了一个函数来获取联系人。这是一切开始变得有点复杂的地方。

在下面的代码中,我已经尽可能具体地注释了所有内容。我已经考虑了所有的 ASCII 字符以及联系人姓名信息的所有可能可能性。

 private func fetchContacts(){

let store = CNContactStore()

store.requestAccess(for: (.contacts)) { (granted, err) in
if let err = err{
print("Failed to request access",err)
return
}

if granted {
print("Access granted")

let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]
let request = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
var contacts = [Contact]()

do{

//var favoritableContacts = [FavoritableContact]()
try store.enumerateContacts(with: request, usingBlock: { (contact, stopPointerIfYouWantToStopEnumerating) in

contacts.append(Contact(contact: contact))

})

//Find the ascii value for "A" to use as your base
let aAscii = Int("A".unicodeScalars.filter({ $0.isASCII }).map({ $0.value })[0]) //This returns 65, btw, so you could also just hardcode

//MARK: Checking every possibility that the user can Input for the names.

//Go through your original array, find the first letter of each contact's family name, and append to the correct array
contacts.forEach { (contact) in

//FAMILY NAMES ONLY WITH GIVEN NAMES
if contact.contact.familyName != "" && contact.contact.givenName != ""{

//Get the ascii value for the first letter of the family name
let firstCharacterFamilyName = Int(contact.contact.familyName.prefix(1).uppercased().unicodeScalars.filter({ $0.isASCII }).map({ $0.value })[0])
// - prefix(1) means take the first character of the family name
// - Uppercase makes sure even that even if the chracter is lowercased, it will be compared to A since the lowercased will become Upper cased.
// - A view of a string’s contents as a collection of Unicode scalar values
// - filter all the characters that arent ASCII.
// - map will loop over the collection and returns an array containing the results of applying a mapping or transform function to each item.
// - [0] will get the first value of the array


//Making sure it is between A and Z
if (firstCharacterFamilyName >= 65 && firstCharacterFamilyName <= 90){
//Append to the array for this letter by subtracting the ascii value for "A" from the ascii value for the uppercased version of this letter.
self.array2d[firstCharacterFamilyName - aAscii].append(contact)

//Checking for space ! " # $ % & ' ( ) * + , - . /
//Checking for numbers
//Checking for : ; < = > ? @
}else if(firstCharacterFamilyName >= 32 && firstCharacterFamilyName <= 64){
self.array2d[26].append(contact)
//Checking for space [ \ ] ^ _ `
}else if(firstCharacterFamilyName >= 91 && firstCharacterFamilyName <= 96){
self.array2d[26].append(contact)
//Checking for space { | } ~
}else if(firstCharacterFamilyName >= 123 && firstCharacterFamilyName <= 126){
self.array2d[26].append(contact)
}

//GIVEN NAMES ONLY WITHOUT FAMILY NAMES
}else if contact.contact.givenName != "" && contact.contact.familyName == ""{

//Get the ascii value for the first letter of the given name
let firstCharacterGivenName = Int(contact.contact.givenName.prefix(1).uppercased().unicodeScalars.filter({ $0.isASCII }).map({ $0.value })[0])

//Making sure it is between A and Z
if (firstCharacterGivenName >= 65 && firstCharacterGivenName <= 90){
//Append to the array for this letter by subtracting the ascii value for "A" from the ascii value for the uppercased version of this letter.
self.array2d[firstCharacterGivenName - aAscii].append(contact)

//Checking for space ! " # $ % & ' ( ) * + , - . /
//Checking for numbers
//Checking for : ; < = > ? @
}else if(firstCharacterGivenName >= 32 && firstCharacterGivenName <= 64){
self.array2d[26].append(contact)
//Checking for space [ \ ] ^ _ `
}else if(firstCharacterGivenName >= 91 && firstCharacterGivenName <= 96){
self.array2d[26].append(contact)
//Checking for space { | } ~
}else if(firstCharacterGivenName >= 123 && firstCharacterGivenName <= 126){
self.array2d[26].append(contact)
}

//GIVEN NAMES ONLY WITHOUT FAMILY NAMES
}else if contact.contact.familyName != "" && contact.contact.givenName == ""{

//Get the ascii value for the first letter of the given name
let firstCharacterFamilyName = Int(contact.contact.familyName.prefix(1).uppercased().unicodeScalars.filter({ $0.isASCII }).map({ $0.value })[0])

//Making sure it is between A and Z
if (firstCharacterFamilyName >= 65 && firstCharacterFamilyName <= 90){
//Append to the array for this letter by subtracting the ascii value for "A" from the ascii value for the uppercased version of this letter.
self.array2d[firstCharacterFamilyName - aAscii].append(contact)

//Checking for space ! " # $ % & ' ( ) * + , - . /
//Checking for numbers
//Checking for : ; < = > ? @
}else if(firstCharacterFamilyName >= 32 && firstCharacterFamilyName <= 64){
self.array2d[26].append(contact)
//Checking for space [ \ ] ^ _ `
}else if(firstCharacterFamilyName >= 91 && firstCharacterFamilyName <= 96){
self.array2d[26].append(contact)
//Checking for space { | } ~
}else if(firstCharacterFamilyName >= 123 && firstCharacterFamilyName <= 126){
self.array2d[26].append(contact)
}

}

}

for index in self.array2d.indices{

//For console visual
let startingValue = Int(("A" as UnicodeScalar).value) // 65
print(Character(UnicodeScalar(index + startingValue)!))
print("Number of items at \(index): \(self.array2d[index].count)")


let names = ExpandableNames(isExpanded: true, contacts: self.array2d[index])

//If there is no element in that index then dont do anything. If there is then append names to twoDimensionalArray
if self.array2d[index].count != 0{
self.twoDimensionalArray.append(names)
}

}

DispatchQueue.main.async {
self.tableView.reloadData()
}



} catch let err{
print("Failed to enumerate contacts", err)
}


}else{
print("Access denied")
}
}

}

剩下的就是简单的 UI 配置,并确保我将正确的部分和行添加到 TableView 中。当我运行我的代码时,它看起来像这样:

Populated tableview from contacts

一旦我将表情符号添加到联系人的名字或姓氏,应用程序就会崩溃:

let firstCharacterFamilyName = Int(contact.contact.familyName.prefix(1).uppercased().unicodeScalars.filter({ $0.isASCII }).map({ $0.value })[0])

这是有道理的。现在这意味着我在检查名字和姓氏首字母的过程中可能过于复杂化了。我尝试过不同的方法,但这是最接近成功的方法。

最佳答案

假设您的目标是按字母顺序对所有联系人进行排序,并将所有不可按字母顺序排序的联系人放入“第 26 部分”,

我提供以下解决方案...显然,可能不是最好的,因为您的问题也与整体设计有关。但也许它会让您以新的方式思考……并摆脱崩溃。

你代码中的主要问题是

let firstCharacterFamilyName = Int(contact.contact.familyName.prefix(1).uppercased().unicodeScalars.filter({ $0.isASCII }).map({ $0.value })[0])

仅检查“prefix(1)”为 ASCII 的条件...并且不检查或不知道如何处理不是 ASCII 的情况。

所以...在我们允许执行该行代码之前,我们需要确保我们正在处理可排序的联系人(以 a-z 或 A-Z 开头)。

首先...将以下函数添加到您的代码中:

func charIsALetter(input: Character) -> Bool {


if (!(input >= "a" && input <= "z") && !(input >= "A" && input <= "Z") ) {
return false
}
else
{
return true}
}

这将允许您检查任何单个字符是否为字母 a-z 或 A-Z。

然后...您可以像这样在代码中使用该函数:

    // get the first letter like you normally do
let firstCharacter = contact.contact.givenName.prefix(1)

//
let result = charIsALetter(input: Character(String(firstCharacter)))

if result == true {
let firstCharacterGivenName = Int(firstCharacter.uppercased().unicodeScalars.filter({ $0.isASCII }).map({ $0.value })[0])

// do all your normal ASCII sorting here
}

else {

// put this contact into SECTION 26

}

现在你不需要这一切了:

//Checking for space ! " # $ % & ' ( ) * + , - . /
//Checking for numbers
//Checking for : ; < = > ? @
}else if(firstCharacterFamilyName >= 32 && firstCharacterFamilyName <= 64){
self.array2d[26].append(contact)
//Checking for space [ \ ] ^ _ `
}else if(firstCharacterFamilyName >= 91 && firstCharacterFamilyName <= 96){
self.array2d[26].append(contact)
//Checking for space { | } ~
}else if(firstCharacterFamilyName >= 123 && firstCharacterFamilyName <= 126){
self.array2d[26].append(contact)
}

希望对您有所帮助。

关于ios - 在 TableView 上显示具有特殊字符的联系人时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48109904/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com