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
c19fadbf
Commit
c19fadbf
authored
May 08, 2025
by
CZ1004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【新增】联系人主要功能逻辑代码
parent
6e41a98b
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
1539 additions
and
188 deletions
+1539
-188
AppDelegate.swift
PhoneManager/AppDelegate.swift
+1
-1
ContactBackupDetailViewController.swift
...ontact/Controller/ContactBackupDetailViewController.swift
+15
-1
ContactBackupViewController.swift
...sion/Contact/Controller/ContactBackupViewController.swift
+1
-0
ContactIncompleteViewController.swift
.../Contact/Controller/ContactIncompleteViewController.swift
+6
-1
ContactViewController.swift
...ss/Session/Contact/Controller/ContactViewController.swift
+1
-0
ContactsDupPreViewController.swift
...ion/Contact/Controller/ContactsDupPreViewController.swift
+102
-0
ContactsDupViewController.swift
...ession/Contact/Controller/ContactsDupViewController.swift
+67
-14
CustomContactViewController.swift
...sion/Contact/Controller/CustomContactViewController.swift
+56
-0
ContactManager.swift
PhoneManager/Class/Session/Contact/Tool/ContactManager.swift
+337
-0
ContactAllView.swift
...nager/Class/Session/Contact/View/All/ContactAllView.swift
+25
-15
ContactBackUpNormalView.swift
...ss/Session/Contact/View/Bac/ContactBackUpNormalView.swift
+5
-5
CustomContactAllViewTableViewCell.swift
...Contact/View/Cell/CustomContactAllViewTableViewCell.swift
+1
-1
CustomContactDupPreTableViewCell.swift
.../Contact/View/Cell/CustomContactDupPreTableViewCell.swift
+122
-0
CustomContactDupTableViewCell.swift
...ion/Contact/View/Cell/CustomContactDupTableViewCell.swift
+2
-2
CustomDupPreHeaderView.swift
...ss/Session/Contact/View/Cell/CustomDupPreHeaderView.swift
+77
-0
ContactBackUpCompletedAlertView.swift
...ew/Common/AlertView/ContactBackUpCompletedAlertView.swift
+0
-1
ContactRestoreSuccessView.swift
...act/View/Common/AlertView/ContactRestoreSuccessView.swift
+82
-0
DeleteButtonView.swift
.../Class/Session/Contact/View/Common/DeleteButtonView.swift
+30
-33
ContactDupNormalView.swift
...Class/Session/Contact/View/Dup/ContactDupNormalView.swift
+75
-5
ContactDupPreNormalView.swift
...ss/Session/Contact/View/Dup/ContactDupPreNormalView.swift
+189
-0
ContactNoDupPreView.swift
.../Class/Session/Contact/View/Dup/ContactNoDupPreView.swift
+88
-0
MergeButtonView.swift
...ager/Class/Session/Contact/View/Dup/MergeButtonView.swift
+129
-0
MergePreButtonView.swift
...r/Class/Session/Contact/View/Dup/MergePreButtonView.swift
+62
-0
ContactNormalIncomView.swift
...ass/Session/Contact/View/Inc/ContactNormalIncomView.swift
+65
-109
Singleton.swift
PhoneManager/Class/Tool/Singleton/Singleton.swift
+1
-0
No files found.
PhoneManager/AppDelegate.swift
View file @
c19fadbf
...
@@ -21,7 +21,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
...
@@ -21,7 +21,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
window
=
UIWindow
(
frame
:
UIScreen
.
main
.
bounds
)
window
=
UIWindow
(
frame
:
UIScreen
.
main
.
bounds
)
window
?
.
backgroundColor
=
UIColor
.
colorWithHex
(
hexStr
:
launchColor
)
window
?
.
backgroundColor
=
.
white
window
?
.
overrideUserInterfaceStyle
=
.
light
window
?
.
overrideUserInterfaceStyle
=
.
light
let
Ssoryboard
=
UIStoryboard
(
name
:
"LauchVC"
,
bundle
:
nil
)
let
Ssoryboard
=
UIStoryboard
(
name
:
"LauchVC"
,
bundle
:
nil
)
...
...
PhoneManager/Class/Session/Contact/Controller/ContactBackupDetailViewController.swift
View file @
c19fadbf
...
@@ -227,7 +227,21 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS
...
@@ -227,7 +227,21 @@ extension ContactBackupDetailViewController:UITableViewDelegate,UITableViewDataS
let
alertVc
=
ContactBacRestoreAlertView
(
frame
:
self
.
view
.
bounds
)
let
alertVc
=
ContactBacRestoreAlertView
(
frame
:
self
.
view
.
bounds
)
self
.
view
.
addSubview
(
alertVc
)
self
.
view
.
addSubview
(
alertVc
)
alertVc
.
sureCallBack
=
{
alertVc
.
sureCallBack
=
{
ContactManager
.
performAtomicRestore
(
self
.
dataSourceModel
)
{
success
,
error
in
if
success
{
print
(
"恢复成功!"
)
DispatchQueue
.
main
.
async
{
// 再次请求数据 重新刷新页面
let
buAlertVc
=
ContactRestoreSuccessView
(
frame
:
self
.
view
.
bounds
)
cWindow
?
.
addSubview
(
buAlertVc
)
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
1
)
{
buAlertVc
.
removeFromSuperview
()
}
}
}
else
{
print
(
"失败原因:
\(
error
?
.
localizedDescription
??
"未知错误"
)
"
)
}
}
}
}
}
}
...
...
PhoneManager/Class/Session/Contact/Controller/ContactBackupViewController.swift
View file @
c19fadbf
...
@@ -33,6 +33,7 @@ class ContactBackupViewController : BaseViewController {
...
@@ -33,6 +33,7 @@ class ContactBackupViewController : BaseViewController {
// 默认页面
// 默认页面
func
setDefaultPage
(){
func
setDefaultPage
(){
self
.
normalView
.
removeFromSuperview
()
self
.
view
.
addSubview
(
self
.
emptyView
)
self
.
view
.
addSubview
(
self
.
emptyView
)
self
.
emptyView
.
snp
.
makeConstraints
{
make
in
self
.
emptyView
.
snp
.
makeConstraints
{
make
in
...
...
PhoneManager/Class/Session/Contact/Controller/ContactIncompleteViewController.swift
View file @
c19fadbf
...
@@ -39,6 +39,8 @@ class ContactIncompleteViewController : BaseViewController {
...
@@ -39,6 +39,8 @@ class ContactIncompleteViewController : BaseViewController {
// 默认页面
// 默认页面
func
setDefaultPage
(){
func
setDefaultPage
(){
self
.
normalView
.
removeFromSuperview
()
self
.
selectAllButton
.
isHidden
=
true
self
.
view
.
addSubview
(
self
.
emptyView
)
self
.
view
.
addSubview
(
self
.
emptyView
)
self
.
emptyView
.
snp
.
makeConstraints
{
make
in
self
.
emptyView
.
snp
.
makeConstraints
{
make
in
...
@@ -49,6 +51,7 @@ class ContactIncompleteViewController : BaseViewController {
...
@@ -49,6 +51,7 @@ class ContactIncompleteViewController : BaseViewController {
}
}
func
setNormalPage
(){
func
setNormalPage
(){
self
.
emptyView
.
removeFromSuperview
()
self
.
emptyView
.
removeFromSuperview
()
self
.
selectAllButton
.
isHidden
=
false
self
.
view
.
addSubview
(
self
.
normalView
)
self
.
view
.
addSubview
(
self
.
normalView
)
self
.
normalView
.
snp
.
makeConstraints
{
make
in
self
.
normalView
.
snp
.
makeConstraints
{
make
in
...
@@ -94,6 +97,9 @@ class ContactIncompleteViewController : BaseViewController {
...
@@ -94,6 +97,9 @@ class ContactIncompleteViewController : BaseViewController {
}
}
self
.
normalView
.
tableView
.
reloadData
()
self
.
normalView
.
tableView
.
reloadData
()
}
}
self
.
normalView
.
dataClearCallBack
=
{
self
.
setDefaultPage
()
}
self
.
setDefaultPage
()
self
.
setDefaultPage
()
}
}
}
}
...
@@ -106,7 +112,6 @@ extension ContactIncompleteViewController {
...
@@ -106,7 +112,6 @@ extension ContactIncompleteViewController {
self
.
setNormalPage
()
self
.
setNormalPage
()
self
.
normalView
.
dataSourceModel
=
data
self
.
normalView
.
dataSourceModel
=
data
DispatchQueue
.
main
.
async
{
DispatchQueue
.
main
.
async
{
self
.
normalView
.
sortContacts
()
self
.
normalView
.
subTitleLabel
.
text
=
"
\(
data
.
count
)
Contacts"
self
.
normalView
.
subTitleLabel
.
text
=
"
\(
data
.
count
)
Contacts"
self
.
normalView
.
tableView
.
reloadData
()
self
.
normalView
.
tableView
.
reloadData
()
}
}
...
...
PhoneManager/Class/Session/Contact/Controller/ContactViewController.swift
View file @
c19fadbf
...
@@ -41,6 +41,7 @@ class ContactViewController : BaseViewController {
...
@@ -41,6 +41,7 @@ class ContactViewController : BaseViewController {
}
}
func
setDefaultPage
(){
func
setDefaultPage
(){
self
.
moduleView
.
removeFromSuperview
()
self
.
view
.
addSubview
(
self
.
emptyView
)
self
.
view
.
addSubview
(
self
.
emptyView
)
self
.
emptyView
.
snp
.
makeConstraints
{
make
in
self
.
emptyView
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
navView
.
snp
.
bottom
)
.
offset
(
0
)
make
.
top
.
equalTo
(
self
.
navView
.
snp
.
bottom
)
.
offset
(
0
)
...
...
PhoneManager/Class/Session/Contact/Controller/ContactsDupPreViewController.swift
0 → 100644
View file @
c19fadbf
//
// ContactsDupPreViewController.swift
// PhoneManager
//
// Created by edy on 2025/5/8.
//
import
Foundation
class
ContactsDupPreViewController
:
BaseViewController
{
var
dataSourceModel
:
[
String
:[
ContactModel
]]
=
[:]
lazy
var
navView
:
ContactNavView
=
{
let
view
=
ContactNavView
()
return
view
}()
lazy
var
emptyView
:
ContactNoDupPreView
=
{
let
view
=
ContactNoDupPreView
()
return
view
}()
lazy
var
normalView
:
ContactDupPreNormalView
=
{
let
view
=
ContactDupPreNormalView
()
return
view
}()
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
self
.
view
.
backgroundColor
=
.
white
self
.
view
.
addSubview
(
self
.
navView
)
self
.
navView
.
snp
.
makeConstraints
{
make
in
make
.
top
.
left
.
right
.
equalToSuperview
()
make
.
height
.
equalTo
(
statusBarHeight
+
44
)
}
self
.
setDefaultPage
()
self
.
normalView
.
dataChangeCallBack
=
{[
weak
self
]
isClear
in
guard
let
self
else
{
return
}
if
isClear
{
DispatchQueue
.
main
.
async
{
self
.
setDefaultPage
()
}
}
}
}
// 默认页面
func
setDefaultPage
(){
self
.
normalView
.
removeFromSuperview
()
self
.
view
.
addSubview
(
self
.
emptyView
)
self
.
emptyView
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
navView
.
snp
.
bottom
)
.
offset
(
0
)
make
.
left
.
right
.
equalToSuperview
()
make
.
bottom
.
equalToSuperview
()
}
}
func
setNormalPage
(){
self
.
emptyView
.
removeFromSuperview
()
self
.
view
.
addSubview
(
self
.
normalView
)
self
.
normalView
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
navView
.
snp
.
bottom
)
.
offset
(
0
)
make
.
left
.
right
.
equalToSuperview
()
make
.
bottom
.
equalToSuperview
()
}
}
}
extension
ContactsDupPreViewController
{
override
func
viewWillAppear
(
_
animated
:
Bool
)
{
super
.
viewWillAppear
(
animated
)
if
self
.
dataSourceModel
.
count
>
0
{
self
.
setNormalPage
()
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
()
}
}
else
{
self
.
setDefaultPage
()
}
}
}
PhoneManager/Class/Session/Contact/Controller/ContactsDupViewController.swift
View file @
c19fadbf
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
import
Foundation
import
Foundation
import
SnapKit
import
SnapKit
import
Contacts
class
ContactsDupViewController
:
BaseViewController
{
class
ContactsDupViewController
:
BaseViewController
{
var
dataSourceModel
:
[[
ContactModel
]]?
var
dataSourceModel
:
[[
ContactModel
]]?
...
@@ -38,6 +39,7 @@ class ContactsDupViewController : BaseViewController {
...
@@ -38,6 +39,7 @@ class ContactsDupViewController : BaseViewController {
// 默认页面
// 默认页面
func
setDefaultPage
(){
func
setDefaultPage
(){
self
.
normalView
.
removeFromSuperview
()
self
.
normalView
.
removeFromSuperview
()
self
.
selectAllButton
.
isHidden
=
true
self
.
view
.
addSubview
(
self
.
emptyView
)
self
.
view
.
addSubview
(
self
.
emptyView
)
self
.
emptyView
.
snp
.
makeConstraints
{
make
in
self
.
emptyView
.
snp
.
makeConstraints
{
make
in
...
@@ -45,20 +47,12 @@ class ContactsDupViewController : BaseViewController {
...
@@ -45,20 +47,12 @@ class ContactsDupViewController : BaseViewController {
make
.
left
.
right
.
equalToSuperview
()
make
.
left
.
right
.
equalToSuperview
()
make
.
bottom
.
equalToSuperview
()
make
.
bottom
.
equalToSuperview
()
}
}
self
.
navView
.
addSubview
(
self
.
selectAllButton
)
self
.
selectAllButton
.
snp
.
makeConstraints
{
make
in
make
.
right
.
equalTo
(
-
15
*
RScreenW
())
make
.
centerY
.
equalTo
(
self
.
navView
.
backButton
.
snp
.
centerY
)
widthConstraint
=
make
.
width
.
equalTo
(
115
)
.
constraint
make
.
height
.
equalTo
(
32
)
}
}
}
func
setNormalPage
(){
func
setNormalPage
(){
self
.
emptyView
.
removeFromSuperview
()
self
.
emptyView
.
removeFromSuperview
()
self
.
view
.
addSubview
(
self
.
normalView
)
self
.
view
.
addSubview
(
self
.
normalView
)
self
.
selectAllButton
.
isHidden
=
false
self
.
normalView
.
snp
.
makeConstraints
{
make
in
self
.
normalView
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
navView
.
snp
.
bottom
)
.
offset
(
0
)
make
.
top
.
equalTo
(
self
.
navView
.
snp
.
bottom
)
.
offset
(
0
)
make
.
left
.
right
.
equalToSuperview
()
make
.
left
.
right
.
equalToSuperview
()
...
@@ -77,6 +71,14 @@ class ContactsDupViewController : BaseViewController {
...
@@ -77,6 +71,14 @@ class ContactsDupViewController : BaseViewController {
make
.
height
.
equalTo
(
statusBarHeight
+
44
)
make
.
height
.
equalTo
(
statusBarHeight
+
44
)
}
}
self
.
navView
.
addSubview
(
self
.
selectAllButton
)
self
.
selectAllButton
.
snp
.
makeConstraints
{
make
in
make
.
right
.
equalTo
(
-
15
*
RScreenW
())
make
.
centerY
.
equalTo
(
self
.
navView
.
backButton
.
snp
.
centerY
)
widthConstraint
=
make
.
width
.
equalTo
(
115
)
.
constraint
make
.
height
.
equalTo
(
32
)
}
self
.
setDefaultPage
()
self
.
setDefaultPage
()
...
@@ -116,16 +118,17 @@ class ContactsDupViewController : BaseViewController {
...
@@ -116,16 +118,17 @@ class ContactsDupViewController : BaseViewController {
}
}
}
}
}
}
let
dataUpdated
=
Notification
.
Name
(
ContactDupPreNormalView
.
CONTACT_MERGED
)
NotificationCenter
.
default
.
addObserver
(
self
,
selector
:
#selector(
handleDataUpdated(_:)
)
,
name
:
dataUpdated
,
object
:
nil
)
}
}
}
}
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
{
...
@@ -154,5 +157,55 @@ extension ContactsDupViewController {
...
@@ -154,5 +157,55 @@ extension ContactsDupViewController {
}
}
return
totalElementCount
return
totalElementCount
}
}
@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
duplicates
:
[[
ContactModel
]]
=
[]
var
contactsByName
:
[
String
:
[
ContactModel
]]
=
[:]
try
store
.
enumerateContacts
(
with
:
request
)
{
contact
,
stop
in
let
givenName
=
contact
.
givenName
let
familyName
=
contact
.
familyName
let
fullName
=
"
\(
familyName
)\(
givenName
)
"
let
phoneNumbers
=
contact
.
phoneNumbers
.
map
{
$0
.
value
.
stringValue
}
let
model
=
ContactModel
.
init
(
name
:
fullName
,
phoneNumber
:
phoneNumbers
,
identifier
:
contact
.
identifier
)
if
!
fullName
.
isEmpty
{
if
contactsByName
[
fullName
]
==
nil
{
contactsByName
[
fullName
]
=
[
model
]
}
else
{
contactsByName
[
fullName
]?
.
append
(
model
)
}
}
duplicates
=
contactsByName
.
values
.
filter
{
$0
.
count
>
1
}
}
DispatchQueue
.
main
.
async
{
self
.
dataSourceModel
=
self
.
sortDupDataSource
(
orgData
:
duplicates
)
self
.
normalView
.
tableView
.
reloadData
()
}
}
catch
{
DispatchQueue
.
main
.
async
{
print
(
"获取联系人信息时发生错误:
\(
error
)
"
)
}
}
}
/// 重复项排序-做一个反序操作,让最新添加的联系人显示在最前面
/// - Parameter orgData: 原始数据
/// - Returns: 排序后的数据
func
sortDupDataSource
(
orgData
:[[
ContactModel
]])
->
[[
ContactModel
]]{
return
orgData
.
map
{
$0
.
reversed
()
}
}
}
}
PhoneManager/Class/Session/Contact/Controller/CustomContactViewController.swift
0 → 100644
View file @
c19fadbf
//
// CustomContactViewController.swift
// PhoneManager
//
// Created by edy on 2025/5/8.
//
import
ContactsUI
// 步骤1: 创建子类继承 CNContactViewController
class
CustomContactViewController
:
CNContactViewController
{
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
setupCancelButton
()
}
// 自定义取消按钮
private
func
setupCancelButton
()
{
navigationItem
.
leftBarButtonItem
=
UIBarButtonItem
(
title
:
"Cancel"
,
style
:
.
plain
,
target
:
self
,
action
:
#selector(
dismissEditor
)
)
}
}
extension
CustomContactViewController
{
@objc
private
func
dismissEditor
()
{
dismiss
(
animated
:
true
,
completion
:
nil
)
}
// 使用自定义视图控制器
func
presentCustomContactEditor
(
with
identifier
:
String
,
viewController
:
UIViewController
)
{
let
contactStore
=
CNContactStore
()
let
keys
=
[
CNContactViewController
.
descriptorForRequiredKeys
()]
do
{
let
contact
=
try
contactStore
.
unifiedContact
(
withIdentifier
:
identifier
,
keysToFetch
:
keys
)
let
mutableContact
=
contact
.
mutableCopy
()
as!
CNMutableContact
// 步骤4: 使用自定义子类初始化
let
editVC
=
CustomContactViewController
(
for
:
mutableContact
)
editVC
.
contactStore
=
contactStore
let
navController
=
UINavigationController
(
rootViewController
:
editVC
)
viewController
.
present
(
navController
,
animated
:
true
)
}
catch
{
print
(
"获取联系人失败:
\(
error
)
"
)
}
}
}
PhoneManager/Class/Session/Contact/Tool/ContactManager.swift
0 → 100644
View file @
c19fadbf
This diff is collapsed.
Click to expand it.
PhoneManager/Class/Session/Contact/View/All/ContactAllView.swift
View file @
c19fadbf
...
@@ -6,7 +6,10 @@
...
@@ -6,7 +6,10 @@
//
//
import
Foundation
import
Foundation
import
SnapKit
class
ContactAllView
:
UIView
{
class
ContactAllView
:
UIView
{
private
var
bottomConstraint
:
Constraint
?
var
dataSourceModel
:
[
ContactModel
]
=
[]
var
dataSourceModel
:
[
ContactModel
]
=
[]
...
@@ -59,10 +62,6 @@ class ContactAllView : UIView {
...
@@ -59,10 +62,6 @@ class ContactAllView : UIView {
lazy
var
deleteButton
:
DeleteButtonView
=
{
lazy
var
deleteButton
:
DeleteButtonView
=
{
let
deleteButton
=
DeleteButtonView
()
let
deleteButton
=
DeleteButtonView
()
// 设置删除按钮
deleteButton
.
layer
.
cornerRadius
=
23
deleteButton
.
clipsToBounds
=
true
deleteButton
.
isHidden
=
true
return
deleteButton
return
deleteButton
}()
}()
...
@@ -91,13 +90,12 @@ class ContactAllView : UIView {
...
@@ -91,13 +90,12 @@ 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
(
-
102
*
RScreenH
()
)
make
.
bottom
.
equalToSuperview
()
.
offset
(
-
safeHeight
)
}
}
self
.
deleteButton
.
snp
.
makeConstraints
{
make
in
self
.
deleteButton
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
tableView
.
snp
.
bottom
)
.
offset
(
16
*
RScreenH
())
make
.
left
.
right
.
equalToSuperview
()
make
.
width
.
equalTo
(
345
*
RScreenW
())
self
.
bottomConstraint
=
make
.
bottom
.
equalToSuperview
()
.
offset
(
68
)
.
constraint
make
.
height
.
equalTo
(
46
)
make
.
height
.
equalTo
(
68
)
make
.
centerX
.
equalToSuperview
()
}
}
// 排序
// 排序
...
@@ -125,6 +123,11 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
...
@@ -125,6 +123,11 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
return
sectionedContacts
[
sectionTitle
]?
.
count
??
0
return
sectionedContacts
[
sectionTitle
]?
.
count
??
0
}
}
func
tableView
(
_
tableView
:
UITableView
,
didSelectRowAt
indexPath
:
IndexPath
)
{
let
cell
=
tableView
.
cellForRow
(
at
:
indexPath
)
as!
CustomContactAllViewTableViewCell
cell
.
selectContact
(
cell
.
selectButton
)
}
func
tableView
(
_
tableView
:
UITableView
,
cellForRowAt
indexPath
:
IndexPath
)
->
UITableViewCell
{
func
tableView
(
_
tableView
:
UITableView
,
cellForRowAt
indexPath
:
IndexPath
)
->
UITableViewCell
{
let
cell
=
tableView
.
dequeueReusableCell
(
withIdentifier
:
"CustomContactAllViewTableViewCell"
,
for
:
indexPath
)
as!
CustomContactAllViewTableViewCell
let
cell
=
tableView
.
dequeueReusableCell
(
withIdentifier
:
"CustomContactAllViewTableViewCell"
,
for
:
indexPath
)
as!
CustomContactAllViewTableViewCell
let
sectionTitle
=
sectionTitles
[
indexPath
.
section
]
let
sectionTitle
=
sectionTitles
[
indexPath
.
section
]
...
@@ -148,11 +151,18 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
...
@@ -148,11 +151,18 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
// 判断button是否显示
// 判断button是否显示
if
self
.
selectedContacts
.
count
>
0
{
if
self
.
selectedContacts
.
count
>
0
{
// 设置button的title
// 设置button的title
self
.
deleteButton
.
titleLabel
.
text
=
"Delete
\(
self
.
selectedContacts
.
count
)
Contact"
self
.
deleteButton
.
deleteButton
.
setTitle
(
"Delete
\(
self
.
selectedContacts
.
count
)
Contact"
,
for
:
.
normal
)
self
.
deleteButton
.
isHidden
=
false
UIView
.
animate
(
withDuration
:
0.1
)
{
// 更新约束
self
.
bottomConstraint
?
.
update
(
offset
:
-
safeHeight
)
self
.
layoutIfNeeded
()
}
}
else
{
}
else
{
UIView
.
animate
(
withDuration
:
0.1
)
{
self
.
deleteButton
.
isHidden
=
true
// 更新约束
self
.
bottomConstraint
?
.
update
(
offset
:
68
)
self
.
layoutIfNeeded
()
}
}
}
}
}
...
@@ -269,8 +279,8 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
...
@@ -269,8 +279,8 @@ extension ContactAllView : UITableViewDataSource,UITableViewDelegate {
// 备份成功
// 备份成功
success
()
success
()
DispatchQueue
.
main
.
async
{
DispatchQueue
.
main
.
async
{
let
buAlertVc
=
ContactBackUpCompletedAlertView
(
frame
:
(
self
.
responderViewController
()?
.
view
.
bounds
)
!
)
let
buAlertVc
=
ContactBackUpCompletedAlertView
(
frame
:
(
cWindow
?
.
bounds
)
!
)
self
.
responderViewController
()?
.
view
.
addSubview
(
buAlertVc
)
cWindow
?
.
addSubview
(
buAlertVc
)
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
1
)
{
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
1
)
{
buAlertVc
.
removeFromSuperview
()
buAlertVc
.
removeFromSuperview
()
}
}
...
...
PhoneManager/Class/Session/Contact/View/Bac/ContactBackUpNormalView.swift
View file @
c19fadbf
...
@@ -76,7 +76,7 @@ class ContactBackUpNormalView : UIView {
...
@@ -76,7 +76,7 @@ class ContactBackUpNormalView : UIView {
make
.
top
.
equalTo
(
self
.
addButon
.
snp
.
bottom
)
.
offset
(
16
)
make
.
top
.
equalTo
(
self
.
addButon
.
snp
.
bottom
)
.
offset
(
16
)
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
()
make
.
bottom
.
equalToSuperview
()
.
offset
(
-
safeHeight
)
}
}
}
}
}
}
...
@@ -125,8 +125,8 @@ extension ContactBackUpNormalView : UITableViewDelegate,UITableViewDataSource{
...
@@ -125,8 +125,8 @@ extension ContactBackUpNormalView : UITableViewDelegate,UITableViewDataSource{
}
}
DispatchQueue
.
main
.
async
{
DispatchQueue
.
main
.
async
{
// 弹框提示成功
// 弹框提示成功
let
buAlertVc
=
ContactBackUpDeleteCompletedAlertView
(
frame
:
(
self
.
responderViewController
()?
.
view
.
bounds
)
!
)
let
buAlertVc
=
ContactBackUpDeleteCompletedAlertView
(
frame
:
(
cWindow
?
.
bounds
)
!
)
self
.
responderViewController
()?
.
view
.
addSubview
(
buAlertVc
)
cWindow
?
.
addSubview
(
buAlertVc
)
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
2
)
{
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
2
)
{
buAlertVc
.
removeFromSuperview
()
buAlertVc
.
removeFromSuperview
()
}
}
...
@@ -168,8 +168,8 @@ extension ContactBackUpNormalView : UITableViewDelegate,UITableViewDataSource{
...
@@ -168,8 +168,8 @@ extension ContactBackUpNormalView : UITableViewDelegate,UITableViewDataSource{
let
vm
=
BackupViewModel
()
let
vm
=
BackupViewModel
()
vm
.
backupAllContacts
(
self
.
dataSourceAllModel
??
[])
{
finished
,
error
in
vm
.
backupAllContacts
(
self
.
dataSourceAllModel
??
[])
{
finished
,
error
in
DispatchQueue
.
main
.
async
{
DispatchQueue
.
main
.
async
{
let
buAlertVc
=
ContactBackUpCompletedAlertView
(
frame
:
(
self
.
responderViewController
()?
.
view
.
bounds
)
!
)
let
buAlertVc
=
ContactBackUpCompletedAlertView
(
frame
:
(
cWindow
?
.
bounds
)
!
)
self
.
responderViewController
()?
.
view
.
addSubview
(
buAlertVc
)
cWindow
?
.
addSubview
(
buAlertVc
)
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
1
)
{
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
1
)
{
buAlertVc
.
removeFromSuperview
()
buAlertVc
.
removeFromSuperview
()
}
}
...
...
PhoneManager/Class/Session/Contact/View/Cell/CustomContactAllViewTableViewCell.swift
View file @
c19fadbf
...
@@ -72,7 +72,7 @@ class CustomContactAllViewTableViewCell : UITableViewCell {
...
@@ -72,7 +72,7 @@ class CustomContactAllViewTableViewCell : UITableViewCell {
}
}
extension
CustomContactAllViewTableViewCell
{
extension
CustomContactAllViewTableViewCell
{
@objc
private
func
selectContact
(
_
sender
:
UIButton
)
{
@objc
func
selectContact
(
_
sender
:
UIButton
)
{
sender
.
isSelected
=
!
sender
.
isSelected
sender
.
isSelected
=
!
sender
.
isSelected
buttonSelectCallBack
(
model
!
,
sender
.
isSelected
)
buttonSelectCallBack
(
model
!
,
sender
.
isSelected
)
}
}
...
...
PhoneManager/Class/Session/Contact/View/Cell/CustomContactDupPreTableViewCell.swift
0 → 100644
View file @
c19fadbf
//
// CustomContactDupTableViewCell.swift
// PhoneManager
//
// Created by edy on 2025/5/6.
//
import
Foundation
class
CustomContactDupPreTableViewCell
:
UITableViewCell
{
var
indexPath
:
IndexPath
?
var
cellSelectCallCack
:
(
IndexPath
,
Bool
)
->
Void
=
{
index
,
choose
in
}
var
model
:
[
ContactModel
]
=
[]
{
didSet
{
DispatchQueue
.
main
.
async
{
if
self
.
model
.
count
>
0
{
self
.
nameLabel
.
text
=
self
.
model
.
first
?
.
name
self
.
numberLabel
.
text
=
self
.
getPhoneNumberString
(
contacts
:
self
.
model
)
}
else
{
self
.
nameLabel
.
text
=
""
self
.
numberLabel
.
text
=
""
}
}
}
}
lazy
var
backView
:
UIView
=
{
let
view
=
UIView
()
view
.
backgroundColor
=
UIColor
(
red
:
0.95
,
green
:
0.96
,
blue
:
0.99
,
alpha
:
1
)
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
12
return
view
}()
lazy
var
nameLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
textColor
=
UIColor
(
red
:
0.2
,
green
:
0.2
,
blue
:
0.2
,
alpha
:
1
)
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
16
,
weight
:
.
bold
)
return
label
}()
lazy
var
numberLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
textColor
=
UIColor
(
red
:
0.4
,
green
:
0.4
,
blue
:
0.4
,
alpha
:
1
)
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
14
,
weight
:
.
regular
)
return
label
}()
lazy
var
moreButton
:
UIButton
=
{
let
button
=
UIButton
(
type
:
.
custom
)
button
.
setImage
(
UIImage
(
named
:
"icon_left_setting_grey"
),
for
:
.
normal
)
return
button
}()
override
init
(
style
:
UITableViewCell
.
CellStyle
,
reuseIdentifier
:
String
?)
{
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
self
.
selectionStyle
=
.
none
self
.
contentView
.
addSubview
(
self
.
backView
)
self
.
backView
.
addSubview
(
self
.
nameLabel
)
self
.
backView
.
addSubview
(
self
.
numberLabel
)
self
.
backView
.
addSubview
(
self
.
moreButton
)
self
.
backView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
top
.
equalToSuperview
()
make
.
height
.
equalTo
(
71
)
}
self
.
nameLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
16
*
RScreenH
())
make
.
top
.
equalToSuperview
()
.
offset
(
16
)
make
.
width
.
equalTo
(
210
)
make
.
height
.
equalTo
(
22
)
}
self
.
numberLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
16
*
RScreenH
())
make
.
top
.
equalTo
(
self
.
nameLabel
.
snp
.
bottom
)
.
offset
(
0
)
make
.
right
.
equalTo
(
self
.
moreButton
.
snp
.
left
)
.
offset
(
0
)
make
.
height
.
equalTo
(
20
)
}
self
.
moreButton
.
snp
.
makeConstraints
{
make
in
make
.
width
.
height
.
equalTo
(
24
)
make
.
centerY
.
equalToSuperview
()
make
.
right
.
equalToSuperview
()
.
offset
(
-
16
*
RScreenW
())
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
extension
CustomContactDupPreTableViewCell
{
func
getPhoneNumberString
(
contacts
:
[
ContactModel
])
->
String
{
var
photoNumbers
:
[
String
]
=
[]
for
item
in
contacts
{
if
let
tempNumbers
=
item
.
phoneNumber
{
photoNumbers
=
photoNumbers
+
tempNumbers
}
}
let
nonEmptyStrings
=
photoNumbers
.
filter
{
!
$0
.
isEmpty
}
if
nonEmptyStrings
.
count
<=
0
{
return
""
}
return
photoNumbers
.
joined
(
separator
:
" / "
)
}
}
PhoneManager/Class/Session/Contact/View/Cell/CustomContactDupTableViewCell.swift
View file @
c19fadbf
...
@@ -81,7 +81,7 @@ class CustomContactDupTableViewCell : UITableViewCell {
...
@@ -81,7 +81,7 @@ class CustomContactDupTableViewCell : UITableViewCell {
self
.
numberLabel
.
snp
.
makeConstraints
{
make
in
self
.
numberLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
16
*
RScreenH
())
make
.
left
.
equalToSuperview
()
.
offset
(
16
*
RScreenH
())
make
.
top
.
equalTo
(
self
.
nameLabel
.
snp
.
bottom
)
.
offset
(
0
)
make
.
top
.
equalTo
(
self
.
nameLabel
.
snp
.
bottom
)
.
offset
(
0
)
make
.
width
.
equalTo
(
21
0
)
make
.
right
.
equalTo
(
self
.
selectButton
.
snp
.
left
)
.
offset
(
0
)
make
.
height
.
equalTo
(
20
)
make
.
height
.
equalTo
(
20
)
}
}
...
@@ -100,7 +100,7 @@ class CustomContactDupTableViewCell : UITableViewCell {
...
@@ -100,7 +100,7 @@ class CustomContactDupTableViewCell : UITableViewCell {
}
}
extension
CustomContactDupTableViewCell
{
extension
CustomContactDupTableViewCell
{
@objc
private
func
selectContact
(
_
sender
:
UIButton
)
{
@objc
func
selectContact
(
_
sender
:
UIButton
)
{
sender
.
isSelected
=
!
sender
.
isSelected
sender
.
isSelected
=
!
sender
.
isSelected
if
let
indexPath
=
self
.
indexPath
{
if
let
indexPath
=
self
.
indexPath
{
self
.
cellSelectCallCack
(
indexPath
,
sender
.
isSelected
)
self
.
cellSelectCallCack
(
indexPath
,
sender
.
isSelected
)
...
...
PhoneManager/Class/Session/Contact/View/Cell/CustomDupPreHeaderView.swift
0 → 100644
View file @
c19fadbf
//
// CustomDupHeaderView.swift
// PhoneManager
//
// Created by edy on 2025/5/7.
//
import
Foundation
class
CustomDupPreHeaderView
:
UITableViewHeaderFooterView
{
var
model
:
[
ContactModel
]
=
[]
{
didSet
{
DispatchQueue
.
main
.
async
{
self
.
tiplabel
.
text
=
"
\(
self
.
model
.
count
)
Contacts Merged"
}
}
}
// 当前的section
var
currentSection
:
Int
=
0
var
headerCallback
:
([
ContactModel
],
Int
)
->
Void
=
{
array
,
currentSection
in
}
var
selectStatus
:
Bool
=
false
lazy
var
tiplabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"
\(
self
.
model
.
count
)
Contacts Merged"
label
.
textAlignment
=
.
left
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
16
,
weight
:
.
medium
)
label
.
textColor
=
UIColor
(
red
:
0.4
,
green
:
0.4
,
blue
:
0.4
,
alpha
:
1
)
return
label
}()
lazy
var
deSelectButton
:
UIButton
=
{
let
button
=
UIButton
(
type
:
.
custom
)
button
.
setImage
(
UIImage
(
named
:
"ic_close_similar"
),
for
:
.
normal
)
button
.
addTarget
(
self
,
action
:
#selector(
removeCurrentData
)
,
for
:
.
touchUpInside
)
return
button
}()
override
init
(
reuseIdentifier
:
String
?)
{
super
.
init
(
reuseIdentifier
:
reuseIdentifier
)
self
.
backgroundColor
=
.
clear
self
.
addSubview
(
self
.
tiplabel
)
self
.
tiplabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
top
.
equalToSuperview
()
make
.
width
.
equalTo
(
200
)
make
.
height
.
equalTo
(
22
)
}
self
.
addSubview
(
self
.
deSelectButton
)
self
.
deSelectButton
.
snp
.
makeConstraints
{
make
in
make
.
width
.
equalTo
(
20
)
make
.
height
.
equalTo
(
20
)
make
.
right
.
equalToSuperview
()
make
.
centerY
.
equalTo
(
self
.
tiplabel
.
snp
.
centerY
)
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
extension
CustomDupPreHeaderView
{
@objc
func
removeCurrentData
(){
self
.
headerCallback
(
self
.
model
,
currentSection
)
}
}
PhoneManager/Class/Session/Contact/View/Common/AlertView/ContactBackUpCompletedAlertView.swift
View file @
c19fadbf
...
@@ -8,7 +8,6 @@
...
@@ -8,7 +8,6 @@
import
Foundation
import
Foundation
class
ContactBackUpCompletedAlertView
:
UIView
{
class
ContactBackUpCompletedAlertView
:
UIView
{
var
sureCallBack
:
()
->
Void
=
{}
// 懒加载背景视图
// 懒加载背景视图
private
lazy
var
backgroundView
:
UIView
=
{
private
lazy
var
backgroundView
:
UIView
=
{
...
...
PhoneManager/Class/Session/Contact/View/Common/AlertView/ContactRestoreSuccessView.swift
0 → 100644
View file @
c19fadbf
//
// ContactRestoreSuccessView.swift
// PhoneManager
//
// Created by edy on 2025/5/8.
//
import
Foundation
class
ContactRestoreSuccessView
:
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_ok_duolicates"
)
return
view
}()
// 懒加载标题标签
private
lazy
var
titleLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"Backup restored"
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
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
(
95
)
}
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
(
20
)
}
}
}
PhoneManager/Class/Session/Contact/View/Common/DeleteButtonView.swift
View file @
c19fadbf
...
@@ -10,43 +10,40 @@ class DeleteButtonView : UIView {
...
@@ -10,43 +10,40 @@ class DeleteButtonView : UIView {
var
submitCallBack
:
(()
->
Void
)
=
{}
var
submitCallBack
:
(()
->
Void
)
=
{}
lazy
var
imageView
:
UIImageView
=
{
lazy
var
deleteButton
:
UIButton
=
{
let
imageView
=
UIImageView
()
let
view
=
UIButton
(
type
:
.
custom
)
imageView
.
image
=
UIImage
(
named
:
"ic_delete_duplicates"
)
view
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
1
)
return
imageView
view
.
setTitleColor
(
.
white
,
for
:
.
normal
)
}()
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
23
lazy
var
titleLabel
:
UILabel
=
{
view
.
titleLabel
?
.
font
=
UIFont
.
systemFont
(
ofSize
:
16
,
weight
:
.
bold
)
let
label
=
UILabel
()
view
.
setTitle
(
"See Merge Preview"
,
for
:
.
normal
)
label
.
textAlignment
=
.
left
view
.
setImage
(
UIImage
(
named
:
"ic_hebing"
),
for
:
.
normal
)
label
.
textColor
=
UIColor
(
red
:
1
,
green
:
1
,
blue
:
1
,
alpha
:
1
)
return
label
// 设置间距为 8
let
spacing
:
CGFloat
=
8
// 获取图片和文字的大小
let
imageSize
=
view
.
imageView
?
.
image
?
.
size
??
.
zero
let
titleSize
=
view
.
titleLabel
?
.
intrinsicContentSize
??
.
zero
// 计算 imageEdgeInsets 和 titleEdgeInsets
view
.
imageEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
-
spacing
/
2
,
bottom
:
0
,
right
:
spacing
/
2
)
view
.
titleEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
spacing
/
2
,
bottom
:
0
,
right
:
-
spacing
/
2
)
view
.
addTarget
(
self
,
action
:
#selector(
deleteButtonAction
)
,
for
:
.
touchUpInside
)
return
view
}()
}()
override
init
(
frame
:
CGRect
)
{
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
self
.
isUserInteractionEnabled
=
true
self
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
1
)
let
tap
=
UITapGestureRecognizer
()
tap
.
addTarget
(
self
,
action
:
#selector(
submitAction
)
)
self
.
addGestureRecognizer
(
tap
)
self
.
addSubview
(
self
.
imageView
)
self
.
addSubview
(
self
.
titleLabel
)
super
.
init
(
frame
:
frame
)
self
.
backgroundColor
=
.
white
self
.
addSubview
(
self
.
deleteButton
)
self
.
imageView
.
snp
.
makeConstraints
{
make
in
self
.
deleteButton
.
snp
.
makeConstraints
{
make
in
make
.
width
.
height
.
equalTo
(
20
)
make
.
left
.
equalToSuperview
()
.
offset
(
15
)
make
.
centerY
.
equalToSuperview
()
make
.
right
.
equalToSuperview
()
.
offset
(
-
15
)
make
.
left
.
equalToSuperview
()
.
offset
(
94
*
RScreenW
())
make
.
height
.
equalTo
(
46
)
}
make
.
top
.
equalToSuperview
()
.
offset
(
16
)
self
.
titleLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalTo
(
self
.
imageView
.
snp
.
right
)
.
offset
(
8
*
RScreenW
())
make
.
centerY
.
equalToSuperview
()
make
.
height
.
equalTo
(
22
)
}
}
}
}
...
@@ -60,7 +57,7 @@ class DeleteButtonView : UIView {
...
@@ -60,7 +57,7 @@ class DeleteButtonView : UIView {
extension
DeleteButtonView
{
extension
DeleteButtonView
{
@objc
func
submit
Action
(){
@objc
func
deleteButton
Action
(){
submitCallBack
()
submitCallBack
()
}
}
}
}
PhoneManager/Class/Session/Contact/View/Dup/ContactDupNormalView.swift
View file @
c19fadbf
...
@@ -6,21 +6,28 @@
...
@@ -6,21 +6,28 @@
//
//
import
Foundation
import
Foundation
import
SnapKit
class
ContactDupNormalView
:
UIView
{
class
ContactDupNormalView
:
UIView
{
var
dataSourceModel
:
[[
ContactModel
]]
=
[]
var
dataSourceModel
:
[[
ContactModel
]]
=
[]
var
selectData
:
[
String
:
[
ContactModel
]]
=
[:]
var
preButtonShowStatus
:
Bool
=
false
var
selectData
:
[
String
:
[
ContactModel
]]
=
[:]
{
didSet
{
// 是否更新底部合并预览按钮
showPreMergeButton
()
}
}
var
dataChangeCallBack
:(
Bool
)
->
Void
=
{
changed
in
}
var
dataChangeCallBack
:(
Bool
)
->
Void
=
{
changed
in
}
/// 选择的联系人
private
var
bottomConstraint
:
Constraint
?
private
var
selectedContacts
:
[
ContactModel
]
=
[]
lazy
var
titleLabel
:
UILabel
=
{
lazy
var
titleLabel
:
UILabel
=
{
let
label
=
UILabel
()
let
label
=
UILabel
()
label
.
text
=
"
All contact
s"
label
.
text
=
"
Duplicate
s"
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
20
,
weight
:
.
bold
)
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
20
,
weight
:
.
bold
)
label
.
textColor
=
UIColor
(
red
:
0.2
,
green
:
0.2
,
blue
:
0.2
,
alpha
:
1
)
label
.
textColor
=
UIColor
(
red
:
0.2
,
green
:
0.2
,
blue
:
0.2
,
alpha
:
1
)
label
.
textAlignment
=
.
left
label
.
textAlignment
=
.
left
...
@@ -50,11 +57,18 @@ class ContactDupNormalView : UIView {
...
@@ -50,11 +57,18 @@ class ContactDupNormalView : UIView {
return
tableView
return
tableView
}()
}()
lazy
var
preButtonView
:
MergePreButtonView
=
{
let
view
=
MergePreButtonView
()
return
view
}()
override
init
(
frame
:
CGRect
)
{
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
super
.
init
(
frame
:
frame
)
self
.
addSubview
(
self
.
titleLabel
)
self
.
addSubview
(
self
.
titleLabel
)
self
.
addSubview
(
self
.
subTitleLabel
)
self
.
addSubview
(
self
.
subTitleLabel
)
self
.
addSubview
(
self
.
tableView
)
self
.
addSubview
(
self
.
tableView
)
self
.
addSubview
(
self
.
preButtonView
)
self
.
titleLabel
.
snp
.
makeConstraints
{
make
in
self
.
titleLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
15
*
RScreenW
())
make
.
left
.
equalToSuperview
()
.
offset
(
15
*
RScreenW
())
...
@@ -74,7 +88,19 @@ class ContactDupNormalView : UIView {
...
@@ -74,7 +88,19 @@ 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
(
-
44
*
RScreenH
())
make
.
bottom
.
equalToSuperview
()
.
offset
(
-
safeHeight
)
}
self
.
preButtonView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
equalToSuperview
()
self
.
bottomConstraint
=
make
.
bottom
.
equalToSuperview
()
.
offset
(
68
)
.
constraint
make
.
height
.
equalTo
(
68
)
}
self
.
preButtonView
.
mergePreCallBack
=
{
let
vc
=
ContactsDupPreViewController
()
vc
.
dataSourceModel
=
self
.
selectData
self
.
responderViewController
()?
.
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
}
}
}
}
...
@@ -155,6 +181,16 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
...
@@ -155,6 +181,16 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
return
34
return
34
}
}
func
tableView
(
_
tableView
:
UITableView
,
didSelectRowAt
indexPath
:
IndexPath
)
{
// 调起系统弹窗
let
cell
=
tableView
.
cellForRow
(
at
:
indexPath
)
as!
CustomContactDupTableViewCell
if
let
model
=
cell
.
model
{
if
let
vc
=
self
.
responderViewController
()
{
ContactManager
.
callContactWithIdentifier
(
model
,
viewController
:
vc
)
}
}
}
// MARK: 辅助方法
// MARK: 辅助方法
...
@@ -215,6 +251,40 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
...
@@ -215,6 +251,40 @@ extension ContactDupNormalView : UITableViewDelegate,UITableViewDataSource{
}
}
return
false
return
false
}
}
// 是否显示预览按钮
func
showPreMergeButton
(){
var
show
:
Bool
=
false
for
(
_
,
value
)
in
self
.
selectData
{
// 判断至少有一组且大于2的开始合并
if
value
.
count
>=
2
{
show
=
true
}
}
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
0.1
)
{
// 如果有且当前是显示的
if
show
{
if
self
.
preButtonShowStatus
==
false
{
self
.
preButtonShowStatus
=
true
UIView
.
animate
(
withDuration
:
0.1
)
{
// 更新约束
self
.
bottomConstraint
?
.
update
(
offset
:
-
safeHeight
)
self
.
layoutIfNeeded
()
}
}
}
else
{
if
self
.
preButtonShowStatus
==
true
{
self
.
preButtonShowStatus
=
false
UIView
.
animate
(
withDuration
:
0.1
)
{
// 更新约束
self
.
bottomConstraint
?
.
update
(
offset
:
68
)
self
.
layoutIfNeeded
()
}
}
}
}
}
}
}
PhoneManager/Class/Session/Contact/View/Dup/ContactDupPreNormalView.swift
0 → 100644
View file @
c19fadbf
//
// ContactDupPreNormalView.swift
// PhoneManager
//
// Created by edy on 2025/5/8.
//
import
Foundation
class
ContactDupPreNormalView
:
UIView
{
static
let
CONTACT_MERGED
=
"contact_merged"
var
dataSourceModel
:
[[
ContactModel
]]
=
[]
var
preButtonShowStatus
:
Bool
=
false
// 如果将不想合并的重复联系人删除完了,就显示没有预览可用页面
var
dataChangeCallBack
:
(
Bool
)
->
Void
=
{
isClear
in
}
lazy
var
titleLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"Duplicates"
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
20
,
weight
:
.
bold
)
label
.
textColor
=
UIColor
(
red
:
0.2
,
green
:
0.2
,
blue
:
0.2
,
alpha
:
1
)
label
.
textAlignment
=
.
left
return
label
}()
lazy
var
subTitleLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"
\(
self
.
dataSourceModel
.
count
)
Contacts"
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
14
,
weight
:
.
regular
)
label
.
textColor
=
UIColor
(
red
:
0.2
,
green
:
0.2
,
blue
:
0.2
,
alpha
:
1
)
label
.
textAlignment
=
.
left
return
label
}()
lazy
var
tableView
:
UITableView
=
{
let
tableView
=
UITableView
(
frame
:
CGRect
(
x
:
0
,
y
:
0
,
width
:
0
,
height
:
12
),
style
:
UITableView
.
Style
.
grouped
)
tableView
.
dataSource
=
self
tableView
.
delegate
=
self
tableView
.
register
(
CustomContactDupPreTableViewCell
.
self
,
forCellReuseIdentifier
:
"CustomContactDupPreTableViewCell"
)
tableView
.
separatorStyle
=
.
none
tableView
.
backgroundColor
=
.
clear
tableView
.
showsVerticalScrollIndicator
=
false
if
#available(iOS 15.0, *)
{
tableView
.
sectionHeaderTopPadding
=
0
}
return
tableView
}()
lazy
var
mergeButtonView
:
MergeButtonView
=
{
let
view
=
MergeButtonView
()
return
view
}()
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
self
.
addSubview
(
self
.
titleLabel
)
self
.
addSubview
(
self
.
subTitleLabel
)
self
.
addSubview
(
self
.
tableView
)
self
.
addSubview
(
self
.
mergeButtonView
)
self
.
titleLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
15
*
RScreenW
())
make
.
top
.
equalToSuperview
()
.
offset
(
14
*
RScreenH
())
make
.
width
.
equalTo
(
345
*
RScreenW
())
make
.
height
.
equalTo
(
32
)
}
self
.
subTitleLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
15
*
RScreenW
())
make
.
top
.
equalTo
(
self
.
titleLabel
.
snp
.
bottom
)
.
offset
(
2
*
RScreenH
())
make
.
width
.
equalTo
(
345
*
RScreenW
())
make
.
height
.
equalTo
(
20
)
}
self
.
tableView
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
subTitleLabel
.
snp
.
bottom
)
.
offset
(
16
*
RScreenH
())
make
.
left
.
equalToSuperview
()
.
offset
(
15
*
RScreenW
())
make
.
right
.
equalToSuperview
()
.
offset
(
-
15
*
RScreenW
())
make
.
bottom
.
equalToSuperview
()
.
offset
(
-
safeHeight
-
68
)
}
self
.
mergeButtonView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
equalToSuperview
()
make
.
bottom
.
equalToSuperview
()
.
offset
(
-
safeHeight
)
make
.
height
.
equalTo
(
68
)
}
self
.
mergeButtonView
.
mergeCallBack
=
{
ContactManager
.
mergeContacts
(
groups
:
self
.
dataSourceModel
)
{
result
in
switch
result
{
case
.
success
(
let
newIDs
):
print
(
"新联系人ID:
\(
newIDs
)
"
)
DispatchQueue
.
main
.
async
{
self
.
removeData
()
// 弹框提示成功
let
buAlertVc
=
ContactBackUpDeleteCompletedAlertView
(
frame
:
(
cWindow
?
.
bounds
)
!
)
cWindow
?
.
addSubview
(
buAlertVc
)
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
2
)
{
buAlertVc
.
removeFromSuperview
()
}
}
break
case
.
failure
(
let
error
):
print
(
"合并失败:
\(
error
.
localizedDescription
)
"
)
}
}
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
/// 合并成功后移除数据源
func
removeData
(){
self
.
dataSourceModel
.
removeAll
()
self
.
tableView
.
reloadData
()
// 更新下头部数据
self
.
subTitleLabel
.
text
=
"
\(
self
.
dataSourceModel
.
count
)
Contacts"
self
.
dataChangeCallBack
(
true
)
// 发起通知
let
dataUpdated
=
Notification
.
Name
(
ContactDupPreNormalView
.
CONTACT_MERGED
)
NotificationCenter
.
default
.
post
(
name
:
dataUpdated
,
object
:
nil
,
userInfo
:
nil
)
}
}
extension
ContactDupPreNormalView
:
UITableViewDelegate
,
UITableViewDataSource
{
func
numberOfSections
(
in
tableView
:
UITableView
)
->
Int
{
return
self
.
dataSourceModel
.
count
}
func
tableView
(
_
tableView
:
UITableView
,
numberOfRowsInSection
section
:
Int
)
->
Int
{
return
1
}
func
tableView
(
_
tableView
:
UITableView
,
didSelectRowAt
indexPath
:
IndexPath
)
{
// 调起系统弹窗
let
cell
=
tableView
.
cellForRow
(
at
:
indexPath
)
as!
CustomContactDupPreTableViewCell
if
let
model
=
cell
.
model
.
first
{
if
let
vc
=
self
.
responderViewController
()
{
ContactManager
.
callContactWithIdentifier
(
model
,
viewController
:
vc
)
}
}
}
func
tableView
(
_
tableView
:
UITableView
,
cellForRowAt
indexPath
:
IndexPath
)
->
UITableViewCell
{
let
cell
=
tableView
.
dequeueReusableCell
(
withIdentifier
:
"CustomContactDupPreTableViewCell"
,
for
:
indexPath
)
as!
CustomContactDupPreTableViewCell
cell
.
indexPath
=
indexPath
cell
.
model
=
self
.
dataSourceModel
[
indexPath
.
section
]
return
cell
}
func
tableView
(
_
tableView
:
UITableView
,
heightForRowAt
indexPath
:
IndexPath
)
->
CGFloat
{
return
77
+
8
*
RScreenH
()
}
func
tableView
(
_
tableView
:
UITableView
,
viewForHeaderInSection
section
:
Int
)
->
UIView
?
{
let
view
=
CustomDupPreHeaderView
(
frame
:
CGRect
(
x
:
0
,
y
:
0
,
width
:
self
.
tableView
.
width
,
height
:
22
))
view
.
model
=
self
.
dataSourceModel
[
section
]
view
.
currentSection
=
section
view
.
headerCallback
=
{
array
,
currentSection
in
self
.
dataSourceModel
.
remove
(
at
:
currentSection
)
DispatchQueue
.
main
.
async
{
self
.
tableView
.
reloadData
()
self
.
subTitleLabel
.
text
=
"
\(
self
.
dataSourceModel
.
count
)
Contacts"
if
self
.
dataSourceModel
.
count
==
0
{
self
.
dataChangeCallBack
(
true
)
}
}
}
return
view
}
func
tableView
(
_
tableView
:
UITableView
,
heightForHeaderInSection
section
:
Int
)
->
CGFloat
{
return
34
}
}
PhoneManager/Class/Session/Contact/View/Dup/ContactNoDupPreView.swift
0 → 100644
View file @
c19fadbf
//
// ContactNoDupPreView.swift
// PhoneManager
//
// Created by edy on 2025/5/8.
//
import
Foundation
class
ContactNoDupPreView
:
UIView
{
lazy
var
titleLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"Duplicates"
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
20
,
weight
:
.
bold
)
label
.
textColor
=
UIColor
(
red
:
0.2
,
green
:
0.2
,
blue
:
0.2
,
alpha
:
1
)
label
.
textAlignment
=
.
left
return
label
}()
lazy
var
subTitleLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"0 Contacts"
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
14
,
weight
:
.
regular
)
label
.
textColor
=
UIColor
(
red
:
0.2
,
green
:
0.2
,
blue
:
0.2
,
alpha
:
1
)
label
.
textAlignment
=
.
left
return
label
}()
lazy
var
tipLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"No Preview Available"
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
24
,
weight
:
.
bold
)
label
.
textColor
=
UIColor
(
red
:
0.2
,
green
:
0.2
,
blue
:
0.2
,
alpha
:
1
)
label
.
textAlignment
=
.
center
return
label
}()
lazy
var
subTipLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
text
=
"Go back and select duplicate contacts to see a preview"
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
14
,
weight
:
.
regular
)
label
.
textColor
=
UIColor
(
red
:
0.4
,
green
:
0.4
,
blue
:
0.4
,
alpha
:
1
)
label
.
numberOfLines
=
0
label
.
textAlignment
=
.
center
return
label
}()
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
self
.
addSubview
(
self
.
titleLabel
)
self
.
addSubview
(
self
.
subTitleLabel
)
self
.
addSubview
(
self
.
tipLabel
)
self
.
addSubview
(
self
.
subTipLabel
)
self
.
titleLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
15
*
RScreenW
())
make
.
top
.
equalToSuperview
()
.
offset
(
14
*
RScreenH
())
make
.
width
.
equalTo
(
345
*
RScreenW
())
make
.
height
.
equalTo
(
32
)
}
self
.
subTitleLabel
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
15
*
RScreenW
())
make
.
top
.
equalTo
(
self
.
titleLabel
.
snp
.
bottom
)
.
offset
(
2
*
RScreenH
())
make
.
width
.
equalTo
(
345
*
RScreenW
())
make
.
height
.
equalTo
(
20
)
}
self
.
tipLabel
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
subTitleLabel
.
snp
.
bottom
)
.
offset
(
218
*
RScreenH
())
make
.
width
.
equalTo
(
315
*
RScreenW
())
make
.
height
.
equalTo
(
34
)
make
.
centerX
.
equalToSuperview
()
}
self
.
subTipLabel
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
self
.
tipLabel
.
snp
.
bottom
)
.
offset
(
8
*
RScreenH
())
make
.
width
.
equalTo
(
315
*
RScreenW
())
make
.
height
.
equalTo
(
40
)
make
.
centerX
.
equalToSuperview
()
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
PhoneManager/Class/Session/Contact/View/Dup/MergeButtonView.swift
0 → 100644
View file @
c19fadbf
//
// MergeButtonView.swift
// PhoneManager
//
// Created by edy on 2025/5/8.
//
import
Foundation
import
Contacts
class
MergeButtonView
:
UIView
{
var
mergeCallBack
:
()
->
Void
=
{}
lazy
var
mergeButton
:
UIButton
=
{
let
view
=
UIButton
(
type
:
.
custom
)
view
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
1
)
view
.
setTitleColor
(
.
white
,
for
:
.
normal
)
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
23
view
.
titleLabel
?
.
font
=
UIFont
.
systemFont
(
ofSize
:
16
,
weight
:
.
bold
)
view
.
setTitle
(
"Merge 0 Contacts"
,
for
:
.
normal
)
view
.
setImage
(
UIImage
(
named
:
"ic_hebing"
),
for
:
.
normal
)
// 设置间距为 8
let
spacing
:
CGFloat
=
8
// 获取图片和文字的大小
let
imageSize
=
view
.
imageView
?
.
image
?
.
size
??
.
zero
let
titleSize
=
view
.
titleLabel
?
.
intrinsicContentSize
??
.
zero
// 计算 imageEdgeInsets 和 titleEdgeInsets
view
.
imageEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
-
spacing
/
2
,
bottom
:
0
,
right
:
spacing
/
2
)
view
.
titleEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
spacing
/
2
,
bottom
:
0
,
right
:
-
spacing
/
2
)
view
.
addTarget
(
self
,
action
:
#selector(
merge
)
,
for
:
.
touchUpInside
)
return
view
}()
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
self
.
backgroundColor
=
.
white
self
.
addSubview
(
self
.
mergeButton
)
self
.
mergeButton
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
15
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
15
)
make
.
height
.
equalTo
(
46
)
make
.
top
.
equalToSuperview
()
.
offset
(
16
)
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
extension
MergeButtonView
{
@objc
func
merge
(){
// 弹出提示框
alertWhenMergeContact
()
}
func
alertWhenMergeContact
()
{
// 删除之前弹出是否需要备份
let
alertVc
=
ContactBackupAlertView
()
alertVc
.
frame
=
(
self
.
responderViewController
()?
.
view
.
bounds
)
!
self
.
responderViewController
()?
.
view
.
addSubview
(
alertVc
)
alertVc
.
sureCallBack
=
{[
weak
self
]
isSure
in
guard
let
self
else
{
return
}
if
isSure
{
backupContactsByselect
{
// 备份完成后开始合并
self
.
mergeCallBack
()
}
}
else
{
// 直接合并
self
.
mergeCallBack
()
}
}
}
func
backupContactsByselect
(
success
:
@escaping
()
->
Void
){
// 直接备份所有联系人
let
vm
=
BackupViewModel
()
// 获取所有联系人
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
let
givenName
=
contact
.
givenName
let
familyName
=
contact
.
familyName
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
if
finised
{
// 备份成功
success
()
DispatchQueue
.
main
.
async
{
let
buAlertVc
=
ContactBackUpCompletedAlertView
(
frame
:
(
cWindow
?
.
bounds
)
!
)
cWindow
?
.
addSubview
(
buAlertVc
)
DispatchQueue
.
main
.
asyncAfter
(
deadline
:
.
now
()
+
1
)
{
buAlertVc
.
removeFromSuperview
()
}
}
}
else
{
Print
(
"备份失败"
)
}
}
}
catch
{
DispatchQueue
.
main
.
async
{
print
(
"获取联系人信息时发生错误:
\(
error
)
"
)
}
}
}
}
PhoneManager/Class/Session/Contact/View/Dup/MergePreButtonView.swift
0 → 100644
View file @
c19fadbf
//
// MergePreButtonView.swift
// PhoneManager
//
// Created by edy on 2025/5/8.
//
import
Foundation
class
MergePreButtonView
:
UIView
{
var
mergePreCallBack
:
()
->
Void
=
{}
lazy
var
mergePreButton
:
UIButton
=
{
let
view
=
UIButton
(
type
:
.
custom
)
view
.
backgroundColor
=
UIColor
(
red
:
0
,
green
:
0.51
,
blue
:
1
,
alpha
:
1
)
view
.
setTitleColor
(
.
white
,
for
:
.
normal
)
view
.
clipsToBounds
=
true
view
.
layer
.
cornerRadius
=
23
view
.
titleLabel
?
.
font
=
UIFont
.
systemFont
(
ofSize
:
16
,
weight
:
.
bold
)
view
.
setTitle
(
"See Merge Preview"
,
for
:
.
normal
)
view
.
setImage
(
UIImage
(
named
:
"ic_hebing"
),
for
:
.
normal
)
// 设置间距为 8
let
spacing
:
CGFloat
=
8
// 获取图片和文字的大小
let
imageSize
=
view
.
imageView
?
.
image
?
.
size
??
.
zero
let
titleSize
=
view
.
titleLabel
?
.
intrinsicContentSize
??
.
zero
// 计算 imageEdgeInsets 和 titleEdgeInsets
view
.
imageEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
-
spacing
/
2
,
bottom
:
0
,
right
:
spacing
/
2
)
view
.
titleEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
spacing
/
2
,
bottom
:
0
,
right
:
-
spacing
/
2
)
view
.
addTarget
(
self
,
action
:
#selector(
mergePre
)
,
for
:
.
touchUpInside
)
return
view
}()
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
self
.
backgroundColor
=
.
white
self
.
addSubview
(
self
.
mergePreButton
)
self
.
mergePreButton
.
snp
.
makeConstraints
{
make
in
make
.
left
.
equalToSuperview
()
.
offset
(
15
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
15
)
make
.
height
.
equalTo
(
46
)
make
.
top
.
equalToSuperview
()
.
offset
(
16
)
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
extension
MergePreButtonView
{
@objc
func
mergePre
(){
self
.
mergePreCallBack
()
}
}
PhoneManager/Class/Session/Contact/View/Inc/ContactNormalIncomView.swift
View file @
c19fadbf
This diff is collapsed.
Click to expand it.
PhoneManager/Class/Tool/Singleton/Singleton.swift
View file @
c19fadbf
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
import
Foundation
import
Foundation
import
GoogleMobileAds
import
GoogleMobileAds
import
ContactsUI
class
Singleton
{
class
Singleton
{
// 使用静态常量来保存单例实例
// 使用静态常量来保存单例实例
...
...
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