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
112ce94a
Commit
112ce94a
authored
Apr 08, 2025
by
CZ1004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改
parent
639dbf43
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
378 additions
and
70 deletions
+378
-70
project.pbxproj
PhoneManager.xcodeproj/project.pbxproj
+2
-5
HomeInfoViewController.swift
...lass/Session/Home/Controller/HomeInfoViewController.swift
+0
-1
HomeViewController.swift
...er/Class/Session/Home/Controller/HomeViewController.swift
+5
-1
HomeView.swift
PhoneManager/Class/Session/Home/View/HomeView.swift
+6
-4
HomePhotosModel .swift
...ager/Class/Session/Home/View/Model/HomePhotosModel .swift
+175
-50
HomeOtherCollectionCell.swift
...lass/Session/Home/View/cell/HomeOtherCollectionCell.swift
+38
-6
PhotoAndVideoMananger.swift
...l/Class/PhotoAndVideoMananger/PhotoAndVideoMananger.swift
+152
-3
No files found.
PhoneManager.xcodeproj/project.pbxproj
View file @
112ce94a
...
...
@@ -485,11 +485,9 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME
=
WidgetBackground
;
CODE_SIGN_ENTITLEMENTS
=
widgetExtension.entitlements
;
CODE_SIGN_IDENTITY
=
"Apple Development"
;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]"
=
"iPhone Developer"
;
CODE_SIGN_STYLE
=
Manual
;
CODE_SIGN_STYLE
=
Automatic
;
CURRENT_PROJECT_VERSION
=
1
;
DEVELOPMENT_TEAM
=
""
;
"DEVELOPMENT_TEAM[sdk=iphoneos*]"
=
6K23946NQ5
;
DEVELOPMENT_TEAM
=
6K23946NQ5
;
ENABLE_USER_SCRIPT_SANDBOXING
=
YES
;
GCC_PREPROCESSOR_DEFINITIONS
=
(
"DEBUG=1"
,
...
...
@@ -509,7 +507,6 @@
PRODUCT_BUNDLE_IDENTIFIER
=
com.app.phonemanager.bswidget
;
PRODUCT_NAME
=
"$(TARGET_NAME)"
;
PROVISIONING_PROFILE_SPECIFIER
=
""
;
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]"
=
phonemanager_widget_dev
;
SKIP_INSTALL
=
YES
;
SWIFT_EMIT_LOC_STRINGS
=
YES
;
SWIFT_VERSION
=
5.0
;
...
...
PhoneManager/Class/Session/Home/Controller/HomeInfoViewController.swift
View file @
112ce94a
...
...
@@ -116,7 +116,6 @@ class HomeInfoViewController:BaseViewController {
tablewView
.
changeALlValue
(
isSeleted
:
seletedAllBtn
.
isSelected
)
}
}
}
PhoneManager/Class/Session/Home/Controller/HomeViewController.swift
View file @
112ce94a
...
...
@@ -85,15 +85,18 @@ class HomeViewController:BaseViewController {
func
setupData
()
{
// 详情数据
PhotoDataManager
.
manager
.
loadFromFileSystem
(
resultModel
:
{[
weak
self
]
model
in
self
?
.
homeView
?
.
model
=
model
})
// 总数据 文件数量和文件大小
PhotoAndVideoMananger
.
mananger
.
fetchAllFile
{[
weak
self
]
index
,
FileSize
in
guard
let
self
else
{
return
}
// 相当于进度条
self
.
homeView
?
.
model
?
.
allFileNumber
=
index
self
.
homeView
?
.
model
?
.
allFileSize
=
FileSize
self
.
homeView
?
.
setTitle
()
...
...
@@ -117,6 +120,7 @@ class HomeViewController:BaseViewController {
if
!
isShowPay
{
// 获取主页数据
setupData
()
isShowPay
=
true
...
...
PhoneManager/Class/Session/Home/View/HomeView.swift
View file @
112ce94a
...
...
@@ -72,7 +72,7 @@ class HomeView:UIView {
func
reload
(
type
:
PhotsFileType
)
{
var
indexPath
:
IndexPath
!
var
indexPath
:
IndexPath
if
type
==
.
duplicates
{
...
...
@@ -90,8 +90,6 @@ class HomeView:UIView {
guard
let
self
else
{
return
}
self
.
collectionView
.
reloadData
()
}
}
...
...
@@ -138,7 +136,7 @@ class HomeView:UIView {
func
setData
()
{
// 加载数据
}
...
...
@@ -238,6 +236,10 @@ extension HomeView:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICol
return
cell
case
1
:
let
cell
=
collectionView
.
dequeueReusableCell
(
withReuseIdentifier
:
HomeOtherCollectionCell
.
identifier
,
for
:
indexPath
)
as!
HomeOtherCollectionCell
cell
.
mediaType
=
0
if
indexPath
.
row
==
0
{
cell
.
mediaType
=
1
}
cell
.
model
=
model
?
.
otherModelArray
[
indexPath
.
row
]
return
cell
default
:
...
...
PhoneManager/Class/Session/Home/View/Model/HomePhotosModel .swift
View file @
112ce94a
This diff is collapsed.
Click to expand it.
PhoneManager/Class/Session/Home/View/cell/HomeOtherCollectionCell.swift
View file @
112ce94a
import
UIKit
import
Photos
import
AVFoundation
class
HomeOtherCollectionCell
:
UICollectionViewCell
{
var
similarFlag
:
Bool
=
false
// 如果是图片,类型为0,视频为1
var
mediaType
:
Int
=
0
// MARK: - Properties
static
let
identifier
=
"HomeOtherCollectionCellID"
...
...
@@ -92,14 +97,41 @@ class HomeOtherCollectionCell: UICollectionViewCell {
titleLabel
.
text
=
model
.
folderName
guard
let
asset
=
model
.
assets
.
first
?
.
first
else
{
return
}
let
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
asset
)
DispatchQueue
.
main
.
async
{[
weak
self
]
in
if
self
.
mediaType
==
0
{
let
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
asset
)
DispatchQueue
.
main
.
async
{[
weak
self
]
in
guard
let
self
else
{
return
}
imageView
.
image
=
image
}
}
else
{
guard
let
self
else
{
return
}
// 定义请求选项来获取视频的第一帧
let
options
=
PHImageRequestOptions
()
// 获取当前版本的照片或视频
options
.
version
=
.
current
// 尽可能快地提供结果
options
.
deliveryMode
=
.
opportunistic
// 允许从iCloud请求
options
.
isNetworkAccessAllowed
=
true
// 异步请求
options
.
isSynchronous
=
false
// 从 PHAsset 获取 AVAsset
if
let
videoAsset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
asset
]){
// 使用requestImageForAsset方法请求视频的第一帧图片
PHImageManager
.
default
()
.
requestImage
(
for
:
videoAsset
,
targetSize
:
CGSize
(
width
:
400
,
height
:
400
),
contentMode
:
PHImageContentMode
.
aspectFit
,
options
:
options
)
{
image
,
_
in
// 处理获取到的图片
if
let
thumbnailImage
=
image
{
// 使用获取到的图片,例如显示在UIImageView上
DispatchQueue
.
main
.
async
{
// 确保在主线程更新UI
self
.
imageView
.
image
=
thumbnailImage
}
}
else
{
print
(
"无法获取图片"
)
}
}
}
imageView
.
image
=
image
}
}
...
...
PhoneManager/Class/Tool/Class/PhotoAndVideoMananger/PhotoAndVideoMananger.swift
View file @
112ce94a
...
...
@@ -146,10 +146,8 @@ class PhotoAndVideoMananger {
guard
let
self
=
self
else
{
return
}
// 计算总大小
self
.
calculateTotalSize
(
of
:
combinedArray
,
progress
:
{
fileSiez
,
index
in
propress
(
index
,
Double
(
fileSiez
))
},
completion
:
{
fileSize
,
index
in
completion
(
Double
(
fileSize
),
index
)
})
...
...
@@ -168,7 +166,6 @@ class PhotoAndVideoMananger {
propress
(
index
,
Double
(
fileSiez
))
},
completion
:
{
fileSize
,
index
in
completion
(
Double
(
fileSize
),
index
)
})
...
...
@@ -606,6 +603,15 @@ class PhotoAndVideoMananger {
return
assetsArray
.
first
}
func
getPHAsssetwithIDs
(
ids
:[
String
])
->
[
PHAsset
]?
{
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
ids
,
options
:
nil
)
let
assetsArray
=
fetchResult
.
objects
(
at
:
IndexSet
(
0
..<
fetchResult
.
count
))
return
assetsArray
}
func
findBestQualityImage
(
from
identifiers
:
[
String
])
async
->
[
String
]
{
var
bestIds
:
[
String
]
=
[]
var
maxFileSize
:
Int64
=
0
...
...
@@ -648,6 +654,149 @@ class PhotoAndVideoMananger {
}
}
// MARK: - 新方法处理相似图片向下-------------------------------------------------------
func
dealSimilarPhotos
(
assets
:[
PHAsset
],
threshold
:
Double
,
completionHandler
:
@escaping
([[
String
]])
->
Void
){
// 重复照片
var
index
=
assets
.
startIndex
var
count
=
0
var
finalData
:[[
String
]]
=
[]
while
index
<
assets
.
endIndex
{
let
nextIndex
=
assets
.
index
(
index
,
offsetBy
:
5
,
limitedBy
:
assets
.
endIndex
)
??
assets
.
endIndex
// 当前组
let
chunk
=
Array
(
assets
[
index
..<
nextIndex
])
index
=
nextIndex
dealSimilarDetailPhotos
(
assets
:
chunk
as
[
PHAsset
],
threshold
:
threshold
)
{
data
in
count
=
count
+
chunk
.
count
finalData
=
finalData
+
data
if
count
==
assets
.
count
{
completionHandler
(
finalData
)
}
}
}
}
// 和上面的方法一起处理,防止内存崩溃
private
func
dealSimilarDetailPhotos
(
assets
:[
PHAsset
],
threshold
:
Double
,
completionHandler
:
@escaping
([[
String
]])
->
Void
){
var
groupAssets
:[[
String
]]
=
[]
// 图片请求选项
let
imageRequestOptions
=
PHImageRequestOptions
()
imageRequestOptions
.
deliveryMode
=
.
highQualityFormat
imageRequestOptions
.
isSynchronous
=
true
imageRequestOptions
.
resizeMode
=
.
exact
// 开一个线程去处理
DispatchQueue
.
global
()
.
async
{
// 需要监听是否完成
var
count1
=
0
var
count2
=
0
for
asset
in
assets
{
PHImageManager
.
default
()
.
requestImage
(
for
:
asset
,
targetSize
:
CGSizeMake
(
50
,
50
),
contentMode
:
.
aspectFit
,
options
:
imageRequestOptions
)
{
image1
,
info
in
var
currentGroup
:
[
String
]
=
[]
// 如果当前组为空,先加一个上去
currentGroup
.
append
(
asset
.
localIdentifier
)
// 然后分成区域比较
var
index
=
assets
.
startIndex
while
index
<
assets
.
endIndex
{
let
nextIndex
=
assets
.
index
(
index
,
offsetBy
:
20
,
limitedBy
:
assets
.
endIndex
)
??
assets
.
endIndex
// 当前组
var
chunk
=
Array
(
assets
[
index
..<
nextIndex
])
index
=
nextIndex
// 比较image重复
for
item
in
chunk
{
// 获取到当前图片
PHImageManager
.
default
()
.
requestImage
(
for
:
item
,
targetSize
:
CGSizeMake
(
50
,
50
),
contentMode
:
.
aspectFit
,
options
:
imageRequestOptions
)
{
image2
,
info
in
let
isSamilar
:
Bool
=
OpenCVWrapper
.
areImagesSimilar
(
image1
,
withImage2
:
image2
,
threshold
:
threshold
)
// 如果相似或者相同
if
isSamilar
{
currentGroup
.
append
(
item
.
localIdentifier
)
}
count2
=
count2
+
1
}
if
count2
==
assets
.
count
&&
currentGroup
.
count
>=
2
{
groupAssets
.
append
(
currentGroup
)
}
}
// 将trunk移除
chunk
.
removeAll
(
keepingCapacity
:
false
)
}
count1
=
count1
+
1
currentGroup
.
removeAll
(
keepingCapacity
:
false
)
}
if
count1
==
assets
.
count
{
completionHandler
(
self
.
removeDuplicates
(
from
:
groupAssets
))
}
}
}
}
/// 去掉数据重复
/// - Parameter array: 当前数据
/// - Returns: 去重后的数据
func
removeDuplicates
(
from
array
:
[[
String
]])
->
[[
String
]]
{
var
set
=
Set
<
[
String
]
>
()
var
result
:
[[
String
]]
=
[]
for
subArray
in
array
{
if
set
.
insert
(
subArray
)
.
inserted
{
result
.
append
(
subArray
)
}
}
return
result
}
// MARK: - 新方法处理相似图片向上-------------------------------------------------------
// MARK: - 处理视频数据-------------------------------------------------------
func
dealVideoData
(
completionHandler
:
@escaping
([[
String
]])
->
Void
){
var
data
:[
String
]
=
[]
for
item
in
self
.
videoAssets
{
data
.
append
(
item
.
localIdentifier
)
}
var
finalData
:
[[
String
]]
=
[]
finalData
.
append
(
data
)
completionHandler
(
finalData
)
}
// MARK: - 处理视频数据-------------------------------------------------------
// MARK: - 处理截图数据-------------------------------------------------------
func
dealScreenShotData
(
completionHandler
:
@escaping
([[
String
]])
->
Void
){
var
data
:[
String
]
=
[]
for
item
in
self
.
screenShotAssets
{
data
.
append
(
item
.
localIdentifier
)
}
var
finalData
:
[[
String
]]
=
[]
finalData
.
append
(
data
)
completionHandler
(
finalData
)
}
// MARK: - 处理截图数据-------------------------------------------------------
// MARK: - 处理照片数据-------------------------------------------------------
func
dealImageAssetData
(
completionHandler
:
@escaping
([[
String
]])
->
Void
){
var
data
:[
String
]
=
[]
for
item
in
self
.
imageAssets
{
data
.
append
(
item
.
localIdentifier
)
}
var
finalData
:
[[
String
]]
=
[]
finalData
.
append
(
data
)
completionHandler
(
finalData
)
}
// MARK: - 处理截图数据-------------------------------------------------------
}
...
...
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