Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
P
PhoneManager
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Yang
PhoneManager
Commits
401a24cd
Commit
401a24cd
authored
May 09, 2025
by
CZ1004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【优化】1、优化流程,修改
parent
c19fadbf
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
739 additions
and
111 deletions
+739
-111
AppDelegate.swift
PhoneManager/AppDelegate.swift
+20
-0
ContactAllViewController.swift
...Session/Contact/Controller/ContactAllViewController.swift
+45
-0
ContactBackupDetailViewController.swift
...ontact/Controller/ContactBackupDetailViewController.swift
+3
-3
ContactBackupViewController.swift
...sion/Contact/Controller/ContactBackupViewController.swift
+25
-11
ContactIncompleteViewController.swift
.../Contact/Controller/ContactIncompleteViewController.swift
+53
-0
ContactViewController.swift
...ss/Session/Contact/Controller/ContactViewController.swift
+14
-18
ContactsDupPreViewController.swift
...ion/Contact/Controller/ContactsDupPreViewController.swift
+77
-0
ContactsDupViewController.swift
...ession/Contact/Controller/ContactsDupViewController.swift
+21
-25
CustomContactViewController.swift
...sion/Contact/Controller/CustomContactViewController.swift
+7
-0
ContactModuleModel.swift
...ager/Class/Session/Contact/Model/ContactModuleModel.swift
+20
-7
ContactManager.swift
PhoneManager/Class/Session/Contact/Tool/ContactManager.swift
+25
-1
ContactAllView.swift
...nager/Class/Session/Contact/View/All/ContactAllView.swift
+67
-7
ContactBackUpNormalView.swift
...ss/Session/Contact/View/Bac/ContactBackUpNormalView.swift
+30
-5
CustomContactDupPreTableViewCell.swift
.../Contact/View/Cell/CustomContactDupPreTableViewCell.swift
+1
-1
CustomContactDupTableViewCell.swift
...ion/Contact/View/Cell/CustomContactDupTableViewCell.swift
+1
-1
ContactBackUpNoDataAlertView.swift
.../View/Common/AlertView/ContactBackUpNoDataAlertView.swift
+83
-0
ContactMergeAlertView.swift
...Contact/View/Common/AlertView/ContactMergeAlertView.swift
+165
-0
ContactDupNormalView.swift
...Class/Session/Contact/View/Dup/ContactDupNormalView.swift
+35
-18
ContactDupPreNormalView.swift
...ss/Session/Contact/View/Dup/ContactDupPreNormalView.swift
+4
-0
MergeButtonView.swift
...ager/Class/Session/Contact/View/Dup/MergeButtonView.swift
+16
-10
ContactNormalIncomView.swift
...ass/Session/Contact/View/Inc/ContactNormalIncomView.swift
+26
-3
ContactModuleView.swift
...ass/Session/Contact/View/MenuView/ContactModuleView.swift
+1
-1
No files found.
PhoneManager/AppDelegate.swift
View file @
401a24cd
...
@@ -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
)
}
}
...
...
PhoneManager/Class/Session/Contact/Controller/ContactAllViewController.swift
View file @
401a24cd
...
@@ -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
)
"
)
}
}
}
}
}
PhoneManager/Class/Session/Contact/Controller/ContactBackupDetailViewController.swift
View file @
401a24cd
...
@@ -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
?
.
n
ame
cell
.
nameLabel
.
text
=
contact
?
.
fullN
ame
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
.
n
ame
)
.
uppercased
()
let
firstLetter
=
pinyinFirstLetter
(
contact
.
fullN
ame
)
.
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
.
n
ame
)
.
uppercased
()
return
pinyinFirstLetter
(
$0
.
fullName
)
.
uppercased
()
<
pinyinFirstLetter
(
$1
.
fullN
ame
)
.
uppercased
()
}
}
}
}
}
}
...
...
PhoneManager/Class/Session/Contact/Controller/ContactBackupViewController.swift
View file @
401a24cd
...
@@ -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
()
}
}
}
}
}
}
...
...
PhoneManager/Class/Session/Contact/Controller/ContactIncompleteViewController.swift
View file @
401a24cd
...
@@ -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
)
"
)
}
}
}
}
}
PhoneManager/Class/Session/Contact/Controller/ContactViewController.swift
View file @
401a24cd
...
@@ -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
{
...
...
PhoneManager/Class/Session/Contact/Controller/ContactsDupPreViewController.swift
View file @
401a24cd
...
@@ -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
()
}
}
}
PhoneManager/Class/Session/Contact/Controller/ContactsDupViewController.swift
View file @
401a24cd
...
@@ -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
()
}
}
}
}
}
PhoneManager/Class/Session/Contact/Controller/CustomContactViewController.swift
View file @
401a24cd
...
@@ -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
)
}
}
...
...
PhoneManager/Class/Session/Contact/Model/ContactModuleModel.swift
View file @
401a24cd
...
@@ -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
}
}
...
...
PhoneManager/Class/Session/Contact/Tool/ContactManager.swift
View file @
401a24cd
...
@@ -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: 其他方法
...
...
PhoneManager/Class/Session/Contact/View/All/ContactAllView.swift
View file @
401a24cd
...
@@ -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
?
.
n
ame
cell
.
nameLabel
.
text
=
contact
?
.
fullN
ame
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
.
n
ame
)
.
uppercased
()
let
firstLetter
=
pinyinFirstLetter
(
contact
.
fullN
ame
)
.
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
.
n
ame
)
.
uppercased
()
return
pinyinFirstLetter
(
$0
.
fullName
)
.
uppercased
()
<
pinyinFirstLetter
(
$1
.
fullN
ame
)
.
uppercased
()
}
}
}
}
}
}
...
...
PhoneManager/Class/Session/Contact/View/Bac/ContactBackUpNormalView.swift
View file @
401a24cd
...
@@ -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
()
}
}
}
}
}
}
...
...
PhoneManager/Class/Session/Contact/View/Cell/CustomContactDupPreTableViewCell.swift
View file @
401a24cd
...
@@ -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
?
.
n
ame
self
.
nameLabel
.
text
=
self
.
model
.
first
?
.
fullN
ame
self
.
numberLabel
.
text
=
self
.
getPhoneNumberString
(
contacts
:
self
.
model
)
self
.
numberLabel
.
text
=
self
.
getPhoneNumberString
(
contacts
:
self
.
model
)
}
else
{
}
else
{
self
.
nameLabel
.
text
=
""
self
.
nameLabel
.
text
=
""
...
...
PhoneManager/Class/Session/Contact/View/Cell/CustomContactDupTableViewCell.swift
View file @
401a24cd
...
@@ -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
?
.
n
ame
self
.
nameLabel
.
text
=
model
?
.
fullN
ame
if
let
numbers
=
model
?
.
phoneNumber
{
if
let
numbers
=
model
?
.
phoneNumber
{
self
.
numberLabel
.
text
=
getPhoneNumberString
(
photoNumbers
:
numbers
)
self
.
numberLabel
.
text
=
getPhoneNumberString
(
photoNumbers
:
numbers
)
}
else
{
}
else
{
...
...
PhoneManager/Class/Session/Contact/View/Common/AlertView/ContactBackUpNoDataAlertView.swift
0 → 100644
View file @
401a24cd
//
// 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
)
}
}
}
PhoneManager/Class/Session/Contact/View/Common/AlertView/ContactMergeAlertView.swift
0 → 100644
View file @
401a24cd
//
// 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
()
}
}
PhoneManager/Class/Session/Contact/View/Dup/ContactDupNormalView.swift
View file @
401a24cd
...
@@ -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
}
}
}
PhoneManager/Class/Session/Contact/View/Dup/ContactDupPreNormalView.swift
View file @
401a24cd
...
@@ -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
):
...
...
PhoneManager/Class/Session/Contact/View/Dup/MergeButtonView.swift
View file @
401a24cd
...
@@ -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
{
...
...
PhoneManager/Class/Session/Contact/View/Inc/ContactNormalIncomView.swift
View file @
401a24cd
...
@@ -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
.
n
ame
cell
.
nameLabel
.
text
=
contact
.
fullN
ame
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
)
}
}
}
}
PhoneManager/Class/Session/Contact/View/MenuView/ContactModuleView.swift
View file @
401a24cd
...
@@ -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
)
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment