Commit 401a24cd authored by CZ1004's avatar CZ1004

【优化】1、优化流程,修改

parent c19fadbf
...@@ -51,6 +51,26 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -51,6 +51,26 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func applicationDidBecomeActive(_ application: UIApplication) { func applicationDidBecomeActive(_ application: UIApplication) {
NotificationCenter.default.post(name: Notification.Name("applicationDidBecomeActive"), object: nil) NotificationCenter.default.post(name: Notification.Name("applicationDidBecomeActive"), object: nil)
postContactNotification()
}
func postContactNotification(){
// 通知联系人重复项改变
let dataUpdated = Notification.Name(ContactDupPreNormalView.CONTACT_MERGED)
NotificationCenter.default.post(name: dataUpdated, object: nil, userInfo: nil)
// 发起通知刷新重复联系人预览页面数据
let dataUpdatePre = Notification.Name(ContactDupPreNormalView.CONTACT_MERGED_PRE)
NotificationCenter.default.post(name: dataUpdatePre, object: nil, userInfo: nil)
// 发起通知刷新所有联系人页面数据
let dataUpdateAll = Notification.Name(ContactAllView.CONTACT_ALL)
NotificationCenter.default.post(name: dataUpdateAll, object: nil, userInfo: nil)
// 发起通知刷新不完整联系人页面数据
let dataUpdateInc = Notification.Name(ContactNormalIncomView.CONTACT_INCOM)
NotificationCenter.default.post(name: dataUpdateInc, object: nil, userInfo: nil)
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
// //
import Foundation import Foundation
import Contacts
class ContactAllViewController : BaseViewController { class ContactAllViewController : BaseViewController {
...@@ -63,6 +64,14 @@ class ContactAllViewController : BaseViewController { ...@@ -63,6 +64,14 @@ class ContactAllViewController : BaseViewController {
make.top.left.right.equalToSuperview() make.top.left.right.equalToSuperview()
make.height.equalTo(statusBarHeight + 44) make.height.equalTo(statusBarHeight + 44)
} }
self.normalView.dataClearCallBack = {
self.setDefaultPage()
}
// 发起通知刷新重复联系人预览页面数据
let dataUpdateAll = Notification.Name(ContactAllView.CONTACT_ALL)
NotificationCenter.default.addObserver(self, selector: #selector(handleDataUpdated(_:)), name: dataUpdateAll, object: nil)
} }
} }
...@@ -90,4 +99,40 @@ extension ContactAllViewController { ...@@ -90,4 +99,40 @@ extension ContactAllViewController {
} }
} }
@objc func handleDataUpdated(_ notification: Notification) {
let store = CNContactStore()
let keysToFetch = [
CNContactGivenNameKey as CNKeyDescriptor,
CNContactFamilyNameKey as CNKeyDescriptor,
CNContactPhoneNumbersKey as CNKeyDescriptor
]
do {
let request = CNContactFetchRequest(keysToFetch: keysToFetch)
var allContacts : [ContactModel] = []
try store.enumerateContacts(with: request) { contact, stop in
if let model = ContactModel.init(contact: contact) {
allContacts.append(model)
}
}
DispatchQueue.main.async {
self.normalView.dataSourceModel = allContacts
if allContacts.count > 0 {
self.setNormalPage()
self.normalView.subTitleLabel.text = "\(allContacts.count) Contacts"
self.normalView.sortContacts()
self.normalView.tableView.reloadData()
self.normalView.setupCustomIndexView()
}else{
self.setDefaultPage()
}
}
} catch {
DispatchQueue.main.async {
print("获取全部联系人信息时发生错误: \(error)")
}
}
}
} }
...@@ -137,7 +137,7 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS ...@@ -137,7 +137,7 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS
let sectionTitle = sectionTitles[indexPath.section] let sectionTitle = sectionTitles[indexPath.section]
let contact = sectionedContacts[sectionTitle]?[indexPath.row] let contact = sectionedContacts[sectionTitle]?[indexPath.row]
cell.model = contact cell.model = contact
cell.nameLabel.text = contact?.name cell.nameLabel.text = contact?.fullName
return cell return cell
} }
...@@ -250,7 +250,7 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS ...@@ -250,7 +250,7 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS
func sortContacts() { func sortContacts() {
sectionedContacts.removeAll() sectionedContacts.removeAll()
for contact in self.dataSourceModel { for contact in self.dataSourceModel {
let firstLetter = pinyinFirstLetter(contact.name).uppercased() let firstLetter = pinyinFirstLetter(contact.fullName).uppercased()
if sectionedContacts[firstLetter] == nil { if sectionedContacts[firstLetter] == nil {
sectionedContacts[firstLetter] = [] sectionedContacts[firstLetter] = []
} }
...@@ -260,7 +260,7 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS ...@@ -260,7 +260,7 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS
sectionTitles = sectionedContacts.keys.sorted() sectionTitles = sectionedContacts.keys.sorted()
for key in sectionTitles { for key in sectionTitles {
sectionedContacts[key] = sectionedContacts[key]?.sorted { sectionedContacts[key] = sectionedContacts[key]?.sorted {
return pinyinFirstLetter($0.name).uppercased() < pinyinFirstLetter($1.name).uppercased() return pinyinFirstLetter($0.fullName).uppercased() < pinyinFirstLetter($1.fullName).uppercased()
} }
} }
} }
......
...@@ -75,23 +75,37 @@ class ContactBackupViewController : BaseViewController { ...@@ -75,23 +75,37 @@ class ContactBackupViewController : BaseViewController {
// 备份之前先看看是否有可用的联系人 // 备份之前先看看是否有可用的联系人
if let data = self.dataSourceAllModel { if let data = self.dataSourceAllModel {
vm.backupAllContacts(data.allContacts) { finished, error in if data.allContacts.count > 0 {
if let error = error { vm.backupAllContacts(data.allContacts) { finished, error in
Print("添加失败,\(error.localizedDescription)") if let error = error {
} Print("添加失败,\(error.localizedDescription)")
DispatchQueue.main.async { }
// 再次请求数据 重新刷新页面 DispatchQueue.main.async {
let buAlertVc = ContactBackUpCompletedAlertView(frame: self.view.bounds) // 再次请求数据 重新刷新页面
self.view.addSubview(buAlertVc) let buAlertVc = ContactBackUpCompletedAlertView(frame: self.view.bounds)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { self.view.addSubview(buAlertVc)
buAlertVc.removeFromSuperview() DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.updateCurrentPageData() buAlertVc.removeFromSuperview()
self.updateCurrentPageData()
}
} }
} }
}else {
let buAlertVc = ContactBackUpNoDataAlertView(frame: (cWindow?.bounds)!)
cWindow?.addSubview(buAlertVc)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
buAlertVc.removeFromSuperview()
}
} }
} }
} }
self.normalView.isClearAllCallBack = {
DispatchQueue.main.async {
self.updateCurrentPageData()
}
}
} }
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
import Foundation import Foundation
import SnapKit import SnapKit
import Contacts
class ContactIncompleteViewController : BaseViewController { class ContactIncompleteViewController : BaseViewController {
...@@ -100,7 +101,21 @@ class ContactIncompleteViewController : BaseViewController { ...@@ -100,7 +101,21 @@ class ContactIncompleteViewController : BaseViewController {
self.normalView.dataClearCallBack = { self.normalView.dataClearCallBack = {
self.setDefaultPage() self.setDefaultPage()
} }
self.normalView.selectDataChangeCallBack = {[weak self]show in
guard let self else {return}
if show {
self.selectAllButton.isSelected = false
}else {
self.selectAllButton.isSelected = true
}
}
self.setDefaultPage() self.setDefaultPage()
// 发起通知刷新重复联系人预览页面数据
let dataUpdateInc = Notification.Name(ContactNormalIncomView.CONTACT_INCOM)
NotificationCenter.default.addObserver(self, selector: #selector(handleDataUpdated(_:)), name: dataUpdateInc, object: nil)
} }
} }
...@@ -123,4 +138,42 @@ extension ContactIncompleteViewController { ...@@ -123,4 +138,42 @@ extension ContactIncompleteViewController {
self.setDefaultPage() self.setDefaultPage()
} }
} }
@objc func handleDataUpdated(_ notification: Notification) {
let store = CNContactStore()
let keysToFetch = [
CNContactGivenNameKey as CNKeyDescriptor,
CNContactFamilyNameKey as CNKeyDescriptor,
CNContactPhoneNumbersKey as CNKeyDescriptor
]
do {
let request = CNContactFetchRequest(keysToFetch: keysToFetch)
// 创建数组
var incompleteContacts : [ContactModel] = []
try store.enumerateContacts(with: request) { contact, stop in
if let model = ContactModel.init(contact: contact){
if model.fullName.isEmpty || model.phoneNumber?.count ?? 0 <= 0 {
incompleteContacts.append(model)
}
}
}
DispatchQueue.main.async {
self.normalView.dataSourceModel = incompleteContacts
if incompleteContacts.count > 0 {
self.setNormalPage()
self.normalView.subTitleLabel.text = "\(incompleteContacts.count) Contacts"
self.normalView.tableView.reloadData()
}else{
self.setDefaultPage()
}
}
} catch {
DispatchQueue.main.async {
print("获取不完整联系人信息时发生错误: \(error)")
}
}
}
} }
...@@ -118,26 +118,22 @@ extension ContactViewController{ ...@@ -118,26 +118,22 @@ extension ContactViewController{
var contactsByName: [String: [ContactModel]] = [:] var contactsByName: [String: [ContactModel]] = [:]
try store.enumerateContacts(with: request) { contact, stop in try store.enumerateContacts(with: request) { contact, stop in
let givenName = contact.givenName if let model = ContactModel.init(contact: contact) {
let familyName = contact.familyName
let fullName = "\(familyName)\(givenName)" if model.fullName.isEmpty || model.phoneNumber?.count ?? 0 <= 0 {
let phoneNumbers = contact.phoneNumbers.map { $0.value.stringValue } incompleteContacts.append(model)
let model = ContactModel.init(name: fullName, phoneNumber: phoneNumbers,identifier: contact.identifier) }
if fullName.isEmpty || phoneNumbers.count <= 0 { allContacts.append(model)
incompleteContacts.append(model) if !model.fullName.isEmpty {
} if contactsByName[model.fullName] == nil {
allContacts.append(model) contactsByName[model.fullName] = [model]
} else {
contactsByName[model.fullName]?.append(model)
if !fullName.isEmpty { }
if contactsByName[fullName] == nil {
contactsByName[fullName] = [model]
} else {
contactsByName[fullName]?.append(model)
} }
duplicates = contactsByName.values.filter { $0.count > 1 }
} }
duplicates = contactsByName.values.filter { $0.count > 1 }
} }
self.dataSourceModel = ContactModuleModel.init(duplicates: sortDupDataSource(orgData: duplicates), incompleteContacts: incompleteContacts, backups: [], allContacts: allContacts) self.dataSourceModel = ContactModuleModel.init(duplicates: sortDupDataSource(orgData: duplicates), incompleteContacts: incompleteContacts, backups: [], allContacts: allContacts)
DispatchQueue.main.async { DispatchQueue.main.async {
......
...@@ -48,6 +48,9 @@ class ContactsDupPreViewController : BaseViewController { ...@@ -48,6 +48,9 @@ class ContactsDupPreViewController : BaseViewController {
} }
} }
} }
let dataUpdatePre = Notification.Name(ContactDupPreNormalView.CONTACT_MERGED_PRE)
NotificationCenter.default.addObserver(self, selector: #selector(handleDataUpdated(_:)), name: dataUpdatePre, object: nil)
} }
...@@ -76,8 +79,77 @@ class ContactsDupPreViewController : BaseViewController { ...@@ -76,8 +79,77 @@ class ContactsDupPreViewController : BaseViewController {
} }
extension ContactsDupPreViewController { extension ContactsDupPreViewController {
fileprivate func dealWhenSystemDataUpdate() {
// 这里还需要处理下万一当前用户在外部修改了下联系人
var changed : Bool = false
for (_,value) in self.dataSourceModel {
// 看名字和电话号码是否全部能对上
for contact in value {
// 从系统取出联系人
if let sysContact = ContactManager.fetchContactFromStore(model: contact){
let fullName = "\(sysContact.familyName)\(sysContact.givenName)"
let phoneNumbers = sysContact.phoneNumbers.map { $0.value.stringValue}
if let numbers = contact.phoneNumber {
// 两个相等
if fullName != contact.fullName || phoneNumbers.sorted() != numbers.sorted(){
changed = true
break
}
}else {
changed = true
break
}
}else {
changed = true
break
}
}
if changed == true {
break
}
}
// 如果变了
if changed == true {
self.dataSourceModel = [:]
setDefaultPage()
}else{
var finallyData : [[ContactModel]] = []
for (_,value) in self.dataSourceModel {
finallyData.append(value)
}
self.normalView.dataSourceModel = finallyData
DispatchQueue.main.async {
self.normalView.subTitleLabel.text = "\(self.dataSourceModel.count) Contacts"
var count : Int = 0
for item in finallyData {
count += item.count
}
self.normalView.mergeButtonView.mergeButton.setTitle("Merge \(count) Contacts", for: .normal)
self.normalView.tableView.reloadData()
}
}
}
fileprivate func dealDataToNoEmpty() {
var tempArray : [String:[ContactModel]] = [:]
for (key,value) in self.dataSourceModel {
if value.count > 0 {
tempArray[key] = value
}
}
self.dataSourceModel = tempArray
}
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
dealDataToNoEmpty()
if self.dataSourceModel.count > 0 { if self.dataSourceModel.count > 0 {
self.setNormalPage() self.setNormalPage()
var finallyData : [[ContactModel]] = [] var finallyData : [[ContactModel]] = []
...@@ -99,4 +171,9 @@ extension ContactsDupPreViewController { ...@@ -99,4 +171,9 @@ extension ContactsDupPreViewController {
self.setDefaultPage() self.setDefaultPage()
} }
} }
@objc func handleDataUpdated(_ notification: Notification) {
dealWhenSystemDataUpdate()
}
} }
...@@ -126,9 +126,7 @@ class ContactsDupViewController : BaseViewController { ...@@ -126,9 +126,7 @@ class ContactsDupViewController : BaseViewController {
extension ContactsDupViewController { extension ContactsDupViewController {
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
// 重新获取下重复项的数据 // 重新获取下重复项的数据
super.viewWillAppear(animated) super.viewWillAppear(animated)
if let data = self.dataSourceModel { if let data = self.dataSourceModel {
if data.count > 0 { if data.count > 0 {
...@@ -145,11 +143,7 @@ extension ContactsDupViewController { ...@@ -145,11 +143,7 @@ extension ContactsDupViewController {
}else { }else {
self.setDefaultPage() self.setDefaultPage()
} }
} }
func getCountFromDataSource(data:[[ContactModel]]) -> Int{ func getCountFromDataSource(data:[[ContactModel]]) -> Int{
var totalElementCount = 0 var totalElementCount = 0
for subArray in data { for subArray in data {
...@@ -159,7 +153,7 @@ extension ContactsDupViewController { ...@@ -159,7 +153,7 @@ extension ContactsDupViewController {
} }
@objc func handleDataUpdated(_ notification: Notification) { func reGetCurrentPageData() {
// 重新获取下重复项的数据 // 重新获取下重复项的数据
let store = CNContactStore() let store = CNContactStore()
let keysToFetch = [ let keysToFetch = [
...@@ -176,23 +170,28 @@ extension ContactsDupViewController { ...@@ -176,23 +170,28 @@ extension ContactsDupViewController {
var contactsByName: [String: [ContactModel]] = [:] var contactsByName: [String: [ContactModel]] = [:]
try store.enumerateContacts(with: request) { contact, stop in try store.enumerateContacts(with: request) { contact, stop in
let givenName = contact.givenName if let model = ContactModel.init(contact: contact) {
let familyName = contact.familyName if !model.fullName.isEmpty {
let fullName = "\(familyName)\(givenName)" if contactsByName[model.fullName] == nil {
let phoneNumbers = contact.phoneNumbers.map { $0.value.stringValue } contactsByName[model.fullName] = [model]
let model = ContactModel.init(name: fullName, phoneNumber: phoneNumbers,identifier: contact.identifier) } else {
if !fullName.isEmpty { contactsByName[model.fullName]?.append(model)
if contactsByName[fullName] == nil { }
contactsByName[fullName] = [model]
} else {
contactsByName[fullName]?.append(model)
} }
duplicates = contactsByName.values.filter { $0.count > 1 }
} }
duplicates = contactsByName.values.filter { $0.count > 1 }
} }
DispatchQueue.main.async { DispatchQueue.main.async {
self.dataSourceModel = self.sortDupDataSource(orgData: duplicates) self.dataSourceModel = duplicates
self.normalView.tableView.reloadData() self.normalView.dataSourceModel = duplicates
self.normalView.subTitleLabel.text = "\(self.getCountFromDataSource(data:duplicates)) Contacts"
self.normalView.selectData = [:]
if duplicates.count > 0 {
self.setNormalPage()
self.normalView.tableView.reloadData()
}else{
self.setDefaultPage()
}
} }
} catch { } catch {
DispatchQueue.main.async { DispatchQueue.main.async {
...@@ -201,11 +200,8 @@ extension ContactsDupViewController { ...@@ -201,11 +200,8 @@ extension ContactsDupViewController {
} }
} }
/// 重复项排序-做一个反序操作,让最新添加的联系人显示在最前面 @objc func handleDataUpdated(_ notification: Notification) {
/// - Parameter orgData: 原始数据 reGetCurrentPageData()
/// - Returns: 排序后的数据
func sortDupDataSource(orgData:[[ContactModel]])->[[ContactModel]]{
return orgData.map { $0.reversed() }
} }
} }
...@@ -27,6 +27,13 @@ class CustomContactViewController: CNContactViewController { ...@@ -27,6 +27,13 @@ class CustomContactViewController: CNContactViewController {
extension CustomContactViewController { extension CustomContactViewController {
@objc private func dismissEditor() { @objc private func dismissEditor() {
// // 发起通知刷新重复联系人页面数据
// let dataUpdated = Notification.Name(ContactDupPreNormalView.CONTACT_MERGED)
// NotificationCenter.default.post(name: dataUpdated, object: nil, userInfo: nil)
//
// // 发起通知刷新重复联系人预览页面数据
// let dataUpdatePre = Notification.Name(ContactDupPreNormalView.CONTACT_MERGED_PRE)
// NotificationCenter.default.post(name: dataUpdatePre, object: nil, userInfo: nil)
dismiss(animated: true, completion: nil) dismiss(animated: true, completion: nil)
} }
......
...@@ -10,28 +10,41 @@ import Contacts ...@@ -10,28 +10,41 @@ import Contacts
struct ContactModel : Codable,Equatable { struct ContactModel : Codable,Equatable {
// 联系人名字 // 联系人名字
var name: String var fullName: String
var givenName : String
var familyName : String
// 联系人电话 // 联系人电话
var phoneNumber : [String]? var phoneNumber : [String]?
// 唯一id // 唯一id
var identifier : String var identifier : String
init(name: String, phoneNumber: [String]? = nil, identifier: String) { init(from decoder: any Decoder) throws {
self.name = name let container = try decoder.container(keyedBy: CodingKeys.self)
self.phoneNumber = phoneNumber self.fullName = try container.decode(String.self, forKey: .fullName)
self.identifier = identifier self.givenName = try container.decode(String.self, forKey: .givenName)
self.familyName = try container.decode(String.self, forKey: .familyName)
self.phoneNumber = try container.decodeIfPresent([String].self, forKey: .phoneNumber)
self.identifier = try container.decode(String.self, forKey: .identifier)
} }
} }
extension ContactModel { extension ContactModel {
init?(contact: CNContact) { init?(contact: CNContact) {
let fullName = "\(contact.givenName) \(contact.familyName)".trimmingCharacters(in: .whitespaces) let fullName = "\(contact.givenName) \(contact.familyName)".trimmingCharacters(in: .whitespaces)
let givenName = "\(contact.givenName)".trimmingCharacters(in: .whitespaces)
let familyName = "\(contact.familyName)".trimmingCharacters(in: .whitespaces)
let phoneNumbers = contact.phoneNumbers.map { $0.value.stringValue } let phoneNumbers = contact.phoneNumbers.map { $0.value.stringValue }
let uniqueID = contact.identifier let uniqueID = contact.identifier
if fullName.isEmpty || phoneNumbers.isEmpty || uniqueID.isEmpty { if uniqueID.isEmpty {
return nil return nil
} }
self.name = fullName self.fullName = fullName
self.givenName = givenName
self.familyName = familyName
self.phoneNumber = phoneNumbers self.phoneNumber = phoneNumbers
self.identifier = uniqueID self.identifier = uniqueID
} }
......
...@@ -316,7 +316,8 @@ class ContactManager { ...@@ -316,7 +316,8 @@ class ContactManager {
} }
private static func createCNContact(from model: ContactModel) -> CNMutableContact { private static func createCNContact(from model: ContactModel) -> CNMutableContact {
let contact = CNMutableContact() let contact = CNMutableContact()
contact.givenName = model.name contact.givenName = model.givenName
contact.familyName = model.familyName
if let numbers = model.phoneNumber { if let numbers = model.phoneNumber {
contact.phoneNumbers = numbers.map { number in contact.phoneNumbers = numbers.map { number in
CNLabeledValue(label: CNLabelPhoneNumberMain, value: CNPhoneNumber(stringValue: number)) CNLabeledValue(label: CNLabelPhoneNumberMain, value: CNPhoneNumber(stringValue: number))
...@@ -325,6 +326,29 @@ class ContactManager { ...@@ -325,6 +326,29 @@ class ContactManager {
return contact return contact
} }
// MARK: 根据id获取联系人
static func fetchContactFromStore(model: ContactModel)->CNContact? {
let contactStore = CNContactStore()
// 指定需要获取的联系人字段(示例包含姓名和电话)
let keysToFetch: [CNKeyDescriptor] = [
CNContactIdentifierKey as CNKeyDescriptor,
CNContactGivenNameKey as CNKeyDescriptor,
CNContactFamilyNameKey as CNKeyDescriptor,
CNContactPhoneNumbersKey as CNKeyDescriptor
]
// 创建谓词(根据 identifier)
let predicate = CNContact.predicateForContacts(withIdentifiers: [model.identifier])
do {
let contacts = try contactStore.unifiedContacts(matching: predicate, keysToFetch: keysToFetch)
// 返回第一个匹配的联系人
return contacts.first
} catch {
print("获取联系人失败:\(error)")
return nil
}
}
// MARK: 其他方法 // MARK: 其他方法
......
...@@ -9,10 +9,17 @@ import Foundation ...@@ -9,10 +9,17 @@ import Foundation
import SnapKit import SnapKit
class ContactAllView : UIView { class ContactAllView : UIView {
static let CONTACT_ALL = "contact_all"
private var bottomConstraint: Constraint? private var bottomConstraint: Constraint?
var dataSourceModel : [ContactModel] = [] var dataSourceModel : [ContactModel] = []
private var tabBottomConstraint: Constraint?
var dataClearCallBack : ()->Void = {}
/// 分组后的联系人 /// 分组后的联系人
private var sectionedContacts: [String: [ContactModel]] = [:] private var sectionedContacts: [String: [ContactModel]] = [:]
...@@ -90,7 +97,7 @@ class ContactAllView : UIView { ...@@ -90,7 +97,7 @@ class ContactAllView : UIView {
make.top.equalTo(self.subTitleLabel.snp.bottom).offset(16 * RScreenH()) make.top.equalTo(self.subTitleLabel.snp.bottom).offset(16 * RScreenH())
make.left.equalToSuperview().offset(15 * RScreenW()) make.left.equalToSuperview().offset(15 * RScreenW())
make.right.equalToSuperview().offset(-15 * RScreenW()) make.right.equalToSuperview().offset(-15 * RScreenW())
make.bottom.equalToSuperview().offset(-safeHeight) self.tabBottomConstraint = make.bottom.equalToSuperview().offset(-safeHeight).constraint
} }
self.deleteButton.snp.makeConstraints { make in self.deleteButton.snp.makeConstraints { make in
make.left.right.equalToSuperview() make.left.right.equalToSuperview()
...@@ -133,7 +140,7 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -133,7 +140,7 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
let sectionTitle = sectionTitles[indexPath.section] let sectionTitle = sectionTitles[indexPath.section]
let contact = sectionedContacts[sectionTitle]?[indexPath.row] let contact = sectionedContacts[sectionTitle]?[indexPath.row]
cell.model = contact cell.model = contact
cell.nameLabel.text = contact?.name cell.nameLabel.text = contact?.fullName
if self.selectedContacts.contains(where: { $0.identifier == contact!.identifier }) { if self.selectedContacts.contains(where: { $0.identifier == contact!.identifier }) {
cell.selectButton.isSelected = true cell.selectButton.isSelected = true
}else { }else {
...@@ -155,12 +162,14 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -155,12 +162,14 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
UIView.animate(withDuration: 0.1) { UIView.animate(withDuration: 0.1) {
// 更新约束 // 更新约束
self.bottomConstraint?.update(offset: -safeHeight) self.bottomConstraint?.update(offset: -safeHeight)
self.tabBottomConstraint?.update(offset: -safeHeight - 68)
self.layoutIfNeeded() self.layoutIfNeeded()
} }
}else{ }else{
UIView.animate(withDuration: 0.1) { UIView.animate(withDuration: 0.1) {
// 更新约束 // 更新约束
self.bottomConstraint?.update(offset: 68) self.bottomConstraint?.update(offset: 68)
self.tabBottomConstraint?.update(offset: -safeHeight)
self.layoutIfNeeded() self.layoutIfNeeded()
} }
} }
...@@ -186,6 +195,7 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -186,6 +195,7 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
return 20 return 20
} }
func setupCustomIndexView() { func setupCustomIndexView() {
customIndexView = nil
customIndexView = UIStackView() customIndexView = UIStackView()
customIndexView.axis = .vertical customIndexView.axis = .vertical
customIndexView.alignment = .center customIndexView.alignment = .center
...@@ -307,11 +317,61 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -307,11 +317,61 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
} }
} }
} }
selectedContacts.removeAll()
sortContacts()
self.tableView.reloadData()
// fixme: 需要从联系人列表中删除 // fixme: 需要从联系人列表中删除
ContactManager.batchDeleteContacts(self.selectedContacts) { result in
switch result {
case .success(let deletedContacts):
print("成功删除 \(deletedContacts.count) 个联系人")
self.selectedContacts.removeAll()
self.sortContacts()
self.subTitleLabel.text = "\(self.dataSourceModel.count) Contacts"
self.updateDeleteButtonStatus()
self.tableView.reloadData()
if self.dataSourceModel.count <= 0 {
self.dataClearCallBack()
}
// 删除完成 弹窗
let buAlertVc = ContactBackUpDeleteCompletedAlertView(frame: (cWindow?.bounds)!)
cWindow?.addSubview(buAlertVc)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
buAlertVc.removeFromSuperview()
}
break
case .failure(.contactNotFound(let missing)):
print("操作终止:未找到联系人 \(missing.identifier)")
case .failure(.unauthorized):
print("无通讯录访问权限")
case .failure(.executionFailed(let error)):
print("操作失败:\(error.localizedDescription)")
}
}
}
func updateDeleteButtonStatus() {
DispatchQueue.main.async {
// 判断button是否显示
if self.selectedContacts.count > 0 {
// 设置button的title
self.deleteButton.deleteButton.setTitle("Delete \(self.selectedContacts.count) Contact", for: .normal)
UIView.animate(withDuration: 0.1) {
// 更新约束
self.bottomConstraint?.update(offset: -safeHeight)
self.tabBottomConstraint?.update(offset: -safeHeight - 68)
self.layoutIfNeeded()
}
}else{
UIView.animate(withDuration: 0.1) {
// 更新约束
self.bottomConstraint?.update(offset: 68)
self.tabBottomConstraint?.update(offset: -safeHeight)
self.layoutIfNeeded()
}
}
}
} }
...@@ -319,7 +379,7 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -319,7 +379,7 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
func sortContacts() { func sortContacts() {
sectionedContacts.removeAll() sectionedContacts.removeAll()
for contact in self.dataSourceModel { for contact in self.dataSourceModel {
let firstLetter = pinyinFirstLetter(contact.name).uppercased() let firstLetter = pinyinFirstLetter(contact.fullName).uppercased()
if sectionedContacts[firstLetter] == nil { if sectionedContacts[firstLetter] == nil {
sectionedContacts[firstLetter] = [] sectionedContacts[firstLetter] = []
} }
...@@ -329,7 +389,7 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate { ...@@ -329,7 +389,7 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
sectionTitles = sectionedContacts.keys.sorted() sectionTitles = sectionedContacts.keys.sorted()
for key in sectionTitles { for key in sectionTitles {
sectionedContacts[key] = sectionedContacts[key]?.sorted { sectionedContacts[key] = sectionedContacts[key]?.sorted {
return pinyinFirstLetter($0.name).uppercased() < pinyinFirstLetter($1.name).uppercased() return pinyinFirstLetter($0.fullName).uppercased() < pinyinFirstLetter($1.fullName).uppercased()
} }
} }
} }
......
...@@ -9,6 +9,8 @@ import Foundation ...@@ -9,6 +9,8 @@ import Foundation
class ContactBackUpNormalView : UIView { class ContactBackUpNormalView : UIView {
var isClearAllCallBack : ()->Void = {}
var dataSourceModel : [BackupInfoModel] = [] var dataSourceModel : [BackupInfoModel] = []
var dataSourceAllModel : [ContactModel]? var dataSourceAllModel : [ContactModel]?
...@@ -130,6 +132,11 @@ extension ContactBackUpNormalView : UITableViewDelegate,UITableViewDataSource{ ...@@ -130,6 +132,11 @@ extension ContactBackUpNormalView : UITableViewDelegate,UITableViewDataSource{
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
buAlertVc.removeFromSuperview() buAlertVc.removeFromSuperview()
} }
// 成功之后给上游发消息
if self.dataSourceModel.count <= 0 {
self.isClearAllCallBack()
}
} }
} }
} }
...@@ -166,15 +173,33 @@ extension ContactBackUpNormalView : UITableViewDelegate,UITableViewDataSource{ ...@@ -166,15 +173,33 @@ extension ContactBackUpNormalView : UITableViewDelegate,UITableViewDataSource{
@objc func addBackupAction() { @objc func addBackupAction() {
let vm = BackupViewModel() let vm = BackupViewModel()
vm.backupAllContacts(self.dataSourceAllModel ?? []) { finished, error in
DispatchQueue.main.async { // 判断当前是否有可用的备份数据
let buAlertVc = ContactBackUpCompletedAlertView(frame: (cWindow?.bounds)!) if let data = self.dataSourceAllModel {
if data.count > 0 {
vm.backupAllContacts(self.dataSourceAllModel ?? []) { finished, error in
DispatchQueue.main.async {
let buAlertVc = ContactBackUpCompletedAlertView(frame: (cWindow?.bounds)!)
cWindow?.addSubview(buAlertVc)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
buAlertVc.removeFromSuperview()
}
// 再次请求数据 重新刷新页面
self.updateData()
}
}
}else {
let buAlertVc = ContactBackUpNoDataAlertView(frame: (cWindow?.bounds)!)
cWindow?.addSubview(buAlertVc) cWindow?.addSubview(buAlertVc)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
buAlertVc.removeFromSuperview() buAlertVc.removeFromSuperview()
} }
// 再次请求数据 重新刷新页面 }
self.updateData() }else {
let buAlertVc = ContactBackUpNoDataAlertView(frame: (cWindow?.bounds)!)
cWindow?.addSubview(buAlertVc)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
buAlertVc.removeFromSuperview()
} }
} }
} }
......
...@@ -18,7 +18,7 @@ class CustomContactDupPreTableViewCell : UITableViewCell { ...@@ -18,7 +18,7 @@ class CustomContactDupPreTableViewCell : UITableViewCell {
didSet{ didSet{
DispatchQueue.main.async { DispatchQueue.main.async {
if self.model.count > 0 { if self.model.count > 0 {
self.nameLabel.text = self.model.first?.name self.nameLabel.text = self.model.first?.fullName
self.numberLabel.text = self.getPhoneNumberString(contacts: self.model) self.numberLabel.text = self.getPhoneNumberString(contacts: self.model)
}else { }else {
self.nameLabel.text = "" self.nameLabel.text = ""
......
...@@ -16,7 +16,7 @@ class CustomContactDupTableViewCell : UITableViewCell { ...@@ -16,7 +16,7 @@ class CustomContactDupTableViewCell : UITableViewCell {
var model : ContactModel?{ var model : ContactModel?{
didSet{ didSet{
self.nameLabel.text = model?.name self.nameLabel.text = model?.fullName
if let numbers = model?.phoneNumber { if let numbers = model?.phoneNumber {
self.numberLabel.text = getPhoneNumberString(photoNumbers:numbers) self.numberLabel.text = getPhoneNumberString(photoNumbers:numbers)
}else { }else {
......
//
// ContactBackUpNoDataAlertView.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import Foundation
class ContactBackUpNoDataAlertView : UIView {
// 懒加载背景视图
private lazy var backgroundView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
return view
}()
// 懒加载卡片视图
private lazy var cardView: UIView = {
let view = UIView()
view.backgroundColor = .white
view.layer.cornerRadius = 10
view.clipsToBounds = true
return view
}()
private lazy var imageView: UIImageView = {
let view = UIImageView()
view.backgroundColor = .clear
view.image = UIImage(named: "ic_no_duolicates")
return view
}()
// 懒加载标题标签
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.text = "No backup data is available"
label.font = UIFont.systemFont(ofSize: 14, weight: .regular)
label.textColor = UIColor(red: 0.4, green: 0.4, blue: 0.4, alpha: 1)
label.textAlignment = .center
label.numberOfLines = 0
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5000)
setupViews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupViews() {
self.addSubview(backgroundView)
backgroundView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
self.addSubview(cardView)
cardView.snp.makeConstraints { make in
make.center.equalToSuperview()
make.width.equalTo(175)
make.height.equalTo(115)
}
cardView.addSubview(imageView)
imageView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(20)
make.width.height.equalTo(35)
make.centerX.equalToSuperview()
}
cardView.addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.top.equalTo(self.imageView.snp.bottom).offset(0)
make.left.right.equalToSuperview().inset(20)
make.height.equalTo(40)
}
}
}
//
// ContactMergeAlertView.swift
// PhoneManager
//
// Created by edy on 2025/5/9.
//
import Foundation
class ContactMergeAlertView : UIView {
var sureCallBack: ()->Void = {}
// 懒加载背景视图
private lazy var backgroundView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
return view
}()
// 懒加载卡片视图
private lazy var cardView: UIView = {
let view = UIView()
view.backgroundColor = .white
view.layer.cornerRadius = 10
view.clipsToBounds = true
return view
}()
// 懒加载标题标签
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.text = "Are you sure you want to merge duplicate contacts?"
label.font = UIFont.systemFont(ofSize: 17, weight: .bold)
label.textColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1)
label.textAlignment = .center
label.numberOfLines = 0
return label
}()
// 懒加载副标题标签
private lazy var subtitleLabel: UILabel = {
let label = UILabel()
label.text = "This process cannot be reversed"
label.font = UIFont.systemFont(ofSize: 13, weight: .regular)
label.textColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1)
label.textAlignment = .center
return label
}()
// 懒加载取消按钮
private lazy var cancelButton: UIButton = {
let button = UIButton()
button.setTitle("Cancel", for: .normal)
button.backgroundColor = .clear
button.setTitleColor(UIColor(red: 0, green: 0.48, blue: 1, alpha: 1), for: .normal)
button.layer.cornerRadius = 5
button.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .regular)
button.addTarget(self, action: #selector(dismissAlert), for: .touchUpInside)
return button
}()
// 懒加载确认按钮
private lazy var yesButton: UIButton = {
let button = UIButton()
button.setTitle("Yes", for: .normal)
button.backgroundColor = .clear
button.setTitleColor(UIColor(red: 0, green: 0.48, blue: 1, alpha: 1), for: .normal)
button.layer.cornerRadius = 5
button.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .regular)
button.addTarget(self, action: #selector(sureAlert), for: .touchUpInside)
return button
}()
// 懒加载顶部边线
private lazy var topBorder: UIView = {
let view = UIView()
view.backgroundColor = UIColor(red: 0.24, green: 0.24, blue: 0.26, alpha: 0.3600)
return view
}()
// 懒加载中间分割线
private lazy var middleBorder: UIView = {
let view = UIView()
view.backgroundColor = UIColor(red: 0.24, green: 0.24, blue: 0.26, alpha: 0.3600)
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5000)
setupViews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupViews() {
self.addSubview(backgroundView)
backgroundView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
self.addSubview(cardView)
cardView.snp.makeConstraints { make in
make.center.equalToSuperview()
make.width.equalTo(270)
make.height.equalTo(154)
}
cardView.addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.top.equalToSuperview().offset(16)
make.left.right.equalToSuperview().inset(16)
make.height.equalTo(44)
}
cardView.addSubview(subtitleLabel)
subtitleLabel.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(2)
make.left.right.equalToSuperview().inset(16)
make.height.equalTo(18)
}
cardView.addSubview(cancelButton)
cancelButton.snp.makeConstraints { make in
make.left.equalToSuperview()
make.bottom.equalToSuperview()
make.width.equalTo(cardView.snp.width).multipliedBy(0.5)
make.height.equalTo(44)
}
cardView.addSubview(yesButton)
yesButton.snp.makeConstraints { make in
make.right.equalToSuperview()
make.bottom.equalToSuperview()
make.width.equalTo(cardView.snp.width).multipliedBy(0.5)
make.height.equalTo(44)
}
cardView.addSubview(topBorder)
topBorder.snp.makeConstraints { make in
make.top.equalTo(cancelButton.snp.top)
make.left.right.equalTo(cardView)
make.height.equalTo(0.5)
}
cardView.addSubview(middleBorder)
middleBorder.snp.makeConstraints { make in
make.centerX.equalTo(cardView)
make.top.equalTo(cancelButton.snp.top)
make.bottom.equalTo(cancelButton.snp.bottom)
make.width.equalTo(0.5)
}
}
@objc private func dismissAlert() {
self.removeFromSuperview()
}
@objc private func sureAlert() {
self.removeFromSuperview()
sureCallBack()
}
}
...@@ -10,7 +10,7 @@ import SnapKit ...@@ -10,7 +10,7 @@ import SnapKit
class ContactDupNormalView : UIView { class ContactDupNormalView : UIView {
var dataSourceModel : [[ContactModel]] = [] var dataSourceModel : [[ContactModel]] = []
var preButtonShowStatus : Bool = false var preButtonShowStatus : Bool = false
...@@ -18,6 +18,7 @@ class ContactDupNormalView : UIView { ...@@ -18,6 +18,7 @@ class ContactDupNormalView : UIView {
didSet { didSet {
// 是否更新底部合并预览按钮 // 是否更新底部合并预览按钮
showPreMergeButton() showPreMergeButton()
self.dataChangeCallBack(isAllData())
} }
} }
...@@ -25,6 +26,8 @@ class ContactDupNormalView : UIView { ...@@ -25,6 +26,8 @@ class ContactDupNormalView : UIView {
private var bottomConstraint: Constraint? private var bottomConstraint: Constraint?
private var tabBottomConstraint: Constraint?
lazy var titleLabel: UILabel = { lazy var titleLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.text = "Duplicates" label.text = "Duplicates"
...@@ -88,7 +91,7 @@ class ContactDupNormalView : UIView { ...@@ -88,7 +91,7 @@ class ContactDupNormalView : UIView {
make.top.equalTo(self.subTitleLabel.snp.bottom).offset(16 * RScreenH()) make.top.equalTo(self.subTitleLabel.snp.bottom).offset(16 * RScreenH())
make.left.equalToSuperview().offset(15 * RScreenW()) make.left.equalToSuperview().offset(15 * RScreenW())
make.right.equalToSuperview().offset(-15 * RScreenW()) make.right.equalToSuperview().offset(-15 * RScreenW())
make.bottom.equalToSuperview().offset(-safeHeight) self.tabBottomConstraint = make.bottom.equalToSuperview().offset(-safeHeight).constraint
} }
self.preButtonView.snp.makeConstraints { make in self.preButtonView.snp.makeConstraints { make in
...@@ -99,7 +102,9 @@ class ContactDupNormalView : UIView { ...@@ -99,7 +102,9 @@ class ContactDupNormalView : UIView {
self.preButtonView.mergePreCallBack = { self.preButtonView.mergePreCallBack = {
let vc = ContactsDupPreViewController() let vc = ContactsDupPreViewController()
vc.dataSourceModel = self.selectData
// 对data 做下处理 当里面只有一个元素的时候实际是不能合并的
vc.dataSourceModel = self.removeSingalDataInDataSource()
self.responderViewController()?.navigationController?.pushViewController(vc, animated: true) self.responderViewController()?.navigationController?.pushViewController(vc, animated: true)
} }
} }
...@@ -107,7 +112,6 @@ class ContactDupNormalView : UIView { ...@@ -107,7 +112,6 @@ class ContactDupNormalView : UIView {
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
} }
extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
...@@ -133,20 +137,16 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{ ...@@ -133,20 +137,16 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
} }
} }
// 如果有选中的更新 // 如果有选中的更新
DispatchQueue.main.async { if let tempArray = self.selectData[String(indexPath.section)] {
if let tempArray = self.selectData[String(indexPath.section)] { if tempArray.contains(where: {$0.identifier == self.dataSourceModel[indexPath.section][indexPath.row].identifier}) {
if tempArray.contains(where: {$0.identifier == cell.model?.identifier}) { cell.selectButton.isSelected = true
cell.selectButton.isSelected = true }else{
}else{
cell.selectButton.isSelected = false
}
}else {
cell.selectButton.isSelected = false cell.selectButton.isSelected = false
} }
}else {
cell.selectButton.isSelected = false
} }
return cell return cell
} }
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
...@@ -162,7 +162,8 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{ ...@@ -162,7 +162,8 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
view.headerCallback = {[weak self]data in view.headerCallback = {[weak self]data in
guard let self else {return} guard let self else {return}
if let tempData = self.selectData[String(section)] { if let tempData = self.selectData[String(section)] {
if tempData.count > 0 { // 如果是数量和元数据数量一样表示已经是选择了全部的状态,则清空下
if tempData.count > 0 && tempData.count == self.dataSourceModel[section].count {
self.selectData[String(section)] = [] self.selectData[String(section)] = []
}else{ }else{
self.selectData[String(section)] = data self.selectData[String(section)] = data
...@@ -217,7 +218,10 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{ ...@@ -217,7 +218,10 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
}else{ }else{
self.selectData[String(index.section)] = [tempModel] self.selectData[String(index.section)] = [tempModel]
} }
changeHeaderSelectButton(section: index.section, view: self.tableView.headerView(forSection: index.section) as! CustomDupHeaderView)
if let header = self.tableView.headerView(forSection: index.section) {
changeHeaderSelectButton(section: index.section, view: header as! CustomDupHeaderView)
}
// 改变导航栏的选择按钮状态 // 改变导航栏的选择按钮状态
self.dataChangeCallBack(isAllData()) self.dataChangeCallBack(isAllData())
} }
...@@ -230,8 +234,9 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{ ...@@ -230,8 +234,9 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
} }
self.selectData[String(index.section)] = array self.selectData[String(index.section)] = array
} }
// 改变当前section的选择按钮 if let header = self.tableView.headerView(forSection: index.section) {
changeHeaderSelectButton(section: index.section, view: self.tableView.headerView(forSection: index.section) as! CustomDupHeaderView) changeHeaderSelectButton(section: index.section, view: header as! CustomDupHeaderView)
}
// 改变导航栏的选择按钮状态 // 改变导航栏的选择按钮状态
self.dataChangeCallBack(isAllData()) self.dataChangeCallBack(isAllData())
} }
...@@ -270,6 +275,7 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{ ...@@ -270,6 +275,7 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
UIView.animate(withDuration: 0.1) { UIView.animate(withDuration: 0.1) {
// 更新约束 // 更新约束
self.bottomConstraint?.update(offset: -safeHeight) self.bottomConstraint?.update(offset: -safeHeight)
self.tabBottomConstraint?.update(offset: -safeHeight - 68)
self.layoutIfNeeded() self.layoutIfNeeded()
} }
} }
...@@ -279,12 +285,23 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{ ...@@ -279,12 +285,23 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
UIView.animate(withDuration: 0.1) { UIView.animate(withDuration: 0.1) {
// 更新约束 // 更新约束
self.bottomConstraint?.update(offset: 68) self.bottomConstraint?.update(offset: 68)
self.tabBottomConstraint?.update(offset: -safeHeight)
self.layoutIfNeeded() self.layoutIfNeeded()
} }
} }
} }
} }
} }
private func removeSingalDataInDataSource()-> [String : [ContactModel]]{
var tempDic : [String : [ContactModel]] = [:]
for (key,value) in self.selectData {
if value.count >= 2{
tempDic[key] = value
}
}
return tempDic
}
} }
...@@ -10,6 +10,8 @@ class ContactDupPreNormalView : UIView { ...@@ -10,6 +10,8 @@ class ContactDupPreNormalView : UIView {
static let CONTACT_MERGED = "contact_merged" static let CONTACT_MERGED = "contact_merged"
static let CONTACT_MERGED_PRE = "contact_merged_pre"
var dataSourceModel : [[ContactModel]] = [] var dataSourceModel : [[ContactModel]] = []
var preButtonShowStatus : Bool = false var preButtonShowStatus : Bool = false
...@@ -104,7 +106,9 @@ class ContactDupPreNormalView : UIView { ...@@ -104,7 +106,9 @@ class ContactDupPreNormalView : UIView {
cWindow?.addSubview(buAlertVc) cWindow?.addSubview(buAlertVc)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
buAlertVc.removeFromSuperview() buAlertVc.removeFromSuperview()
// 返回重复项
} }
self.responderViewController()?.navigationController?.popViewController(animated: true)
} }
break break
case .failure(let error): case .failure(let error):
......
...@@ -63,6 +63,16 @@ extension MergeButtonView { ...@@ -63,6 +63,16 @@ extension MergeButtonView {
alertWhenMergeContact() alertWhenMergeContact()
} }
fileprivate func showMeegeAlert(_ self: MergeButtonView) {
// 直接合并
let mergeAlertView : ContactMergeAlertView = ContactMergeAlertView()
mergeAlertView.frame = (self.responderViewController()?.view.bounds)!
cWindow?.addSubview(mergeAlertView)
mergeAlertView.sureCallBack = {
self.mergeCallBack()
}
}
func alertWhenMergeContact() { func alertWhenMergeContact() {
// 删除之前弹出是否需要备份 // 删除之前弹出是否需要备份
let alertVc = ContactBackupAlertView() let alertVc = ContactBackupAlertView()
...@@ -74,11 +84,10 @@ extension MergeButtonView { ...@@ -74,11 +84,10 @@ extension MergeButtonView {
if isSure { if isSure {
backupContactsByselect { backupContactsByselect {
// 备份完成后开始合并 // 备份完成后开始合并
self.mergeCallBack() self.showMeegeAlert(self)
} }
}else{ }else{
// 直接合并 showMeegeAlert(self)
self.mergeCallBack()
} }
} }
} }
...@@ -98,22 +107,19 @@ extension MergeButtonView { ...@@ -98,22 +107,19 @@ extension MergeButtonView {
let request = CNContactFetchRequest(keysToFetch: keysToFetch) let request = CNContactFetchRequest(keysToFetch: keysToFetch)
var allContacts : [ContactModel] = [] var allContacts : [ContactModel] = []
try store.enumerateContacts(with: request) { contact, stop in try store.enumerateContacts(with: request) { contact, stop in
let givenName = contact.givenName if let model = ContactModel.init(contact: contact) {
let familyName = contact.familyName allContacts.append(model)
let fullName = "\(familyName)\(givenName)" }
let phoneNumbers = contact.phoneNumbers.map { $0.value.stringValue }
let model = ContactModel.init(name: fullName, phoneNumber: phoneNumbers,identifier: contact.identifier)
allContacts.append(model)
} }
vm.backupPartialContacts(allContacts) { finised, error in vm.backupPartialContacts(allContacts) { finised, error in
if finised { if finised {
// 备份成功 // 备份成功
success()
DispatchQueue.main.async { DispatchQueue.main.async {
let buAlertVc = ContactBackUpCompletedAlertView(frame: (cWindow?.bounds)!) let buAlertVc = ContactBackUpCompletedAlertView(frame: (cWindow?.bounds)!)
cWindow?.addSubview(buAlertVc) cWindow?.addSubview(buAlertVc)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
buAlertVc.removeFromSuperview() buAlertVc.removeFromSuperview()
success()
} }
} }
}else{ }else{
......
...@@ -10,16 +10,28 @@ import SnapKit ...@@ -10,16 +10,28 @@ import SnapKit
class ContactNormalIncomView : UIView { class ContactNormalIncomView : UIView {
static let CONTACT_INCOM = "contact_incom"
private var bottomConstraint: Constraint? private var bottomConstraint: Constraint?
private var tabBottomConstraint: Constraint?
var dataSourceModel : [ContactModel] = [] var dataSourceModel : [ContactModel] = []
var dataClearCallBack : ()->Void = {} var dataClearCallBack : ()->Void = {}
var selectDataChangeCallBack: (Bool)->Void = {show in}
/// 选择的联系人 /// 选择的联系人
var selectedContacts: [ContactModel] = [] var selectedContacts: [ContactModel] = [] {
didSet{
}
}
var selectedIndex = 0 var selectedIndex = 0
...@@ -85,7 +97,7 @@ class ContactNormalIncomView : UIView { ...@@ -85,7 +97,7 @@ class ContactNormalIncomView : UIView {
make.top.equalTo(self.subTitleLabel.snp.bottom).offset(16 * RScreenH()) make.top.equalTo(self.subTitleLabel.snp.bottom).offset(16 * RScreenH())
make.left.equalToSuperview().offset(15 * RScreenW()) make.left.equalToSuperview().offset(15 * RScreenW())
make.right.equalToSuperview().offset(-15 * RScreenW()) make.right.equalToSuperview().offset(-15 * RScreenW())
make.bottom.equalToSuperview().offset(-safeHeight) self.tabBottomConstraint = make.bottom.equalToSuperview().offset(-safeHeight).constraint
} }
self.deleteButton.snp.makeConstraints { make in self.deleteButton.snp.makeConstraints { make in
make.left.right.equalToSuperview() make.left.right.equalToSuperview()
...@@ -129,12 +141,14 @@ extension ContactNormalIncomView : UITableViewDataSource,UITableViewDelegate { ...@@ -129,12 +141,14 @@ extension ContactNormalIncomView : UITableViewDataSource,UITableViewDelegate {
UIView.animate(withDuration: 0.1) { UIView.animate(withDuration: 0.1) {
// 更新约束 // 更新约束
self.bottomConstraint?.update(offset: -safeHeight) self.bottomConstraint?.update(offset: -safeHeight)
self.tabBottomConstraint?.update(offset: -safeHeight - 68)
self.layoutIfNeeded() self.layoutIfNeeded()
} }
}else{ }else{
UIView.animate(withDuration: 0.1) { UIView.animate(withDuration: 0.1) {
// 更新约束 // 更新约束
self.bottomConstraint?.update(offset: 68) self.bottomConstraint?.update(offset: 68)
self.tabBottomConstraint?.update(offset: -safeHeight)
self.layoutIfNeeded() self.layoutIfNeeded()
} }
} }
...@@ -145,7 +159,7 @@ extension ContactNormalIncomView : UITableViewDataSource,UITableViewDelegate { ...@@ -145,7 +159,7 @@ extension ContactNormalIncomView : UITableViewDataSource,UITableViewDelegate {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomContactAllViewTableViewCell", for: indexPath) as! CustomContactAllViewTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: "CustomContactAllViewTableViewCell", for: indexPath) as! CustomContactAllViewTableViewCell
let contact = self.dataSourceModel[indexPath.row] let contact = self.dataSourceModel[indexPath.row]
cell.model = contact cell.model = contact
cell.nameLabel.text = contact.name cell.nameLabel.text = contact.fullName
if self.selectedContacts.contains(where: { $0.identifier == contact.identifier }) { if self.selectedContacts.contains(where: { $0.identifier == contact.identifier }) {
cell.selectButton.isSelected = true cell.selectButton.isSelected = true
}else { }else {
...@@ -159,6 +173,7 @@ extension ContactNormalIncomView : UITableViewDataSource,UITableViewDelegate { ...@@ -159,6 +173,7 @@ extension ContactNormalIncomView : UITableViewDataSource,UITableViewDelegate {
self.selectedContacts.removeAll(where: { $0.identifier == model.identifier }) self.selectedContacts.removeAll(where: { $0.identifier == model.identifier })
} }
updateDeleteButtonStatus() updateDeleteButtonStatus()
changeHeaderSelectButtonStatus()
} }
return cell return cell
...@@ -219,4 +234,12 @@ extension ContactNormalIncomView : UITableViewDataSource,UITableViewDelegate { ...@@ -219,4 +234,12 @@ extension ContactNormalIncomView : UITableViewDataSource,UITableViewDelegate {
} }
} }
func changeHeaderSelectButtonStatus(){
if self.dataSourceModel.count != self.selectedContacts.count {
self.selectDataChangeCallBack(true)
}else {
self.selectDataChangeCallBack(false)
}
}
} }
...@@ -67,7 +67,7 @@ class ContactModuleView : UIView { ...@@ -67,7 +67,7 @@ class ContactModuleView : UIView {
make.top.equalTo(self.titleLabel.snp.bottom).offset(18 * RScreenH()) make.top.equalTo(self.titleLabel.snp.bottom).offset(18 * RScreenH())
make.width.equalTo(345 * RScreenW()) make.width.equalTo(345 * RScreenW())
make.centerX.equalToSuperview() make.centerX.equalToSuperview()
make.bottom.equalToSuperview().offset(-34) make.bottom.equalToSuperview().offset(-safeHeight)
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment