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
71bca841
Commit
71bca841
authored
Apr 14, 2025
by
CZ1004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修改数据源结构方式
parent
7ab40d47
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
341 additions
and
281 deletions
+341
-281
HomeInfoViewController.swift
...lass/Session/Home/Controller/HomeInfoViewController.swift
+2
-2
HomePhotosDetailViewController.swift
...sion/Home/Controller/HomePhotosDetailViewController.swift
+24
-68
HomeVideoDetailController.swift
...s/Session/Home/Controller/HomeVideoDetailController.swift
+23
-57
HomeInfoView.swift
PhoneManager/Class/Session/Home/View/HomeInfoView.swift
+5
-5
HomePhotosModel .swift
...ager/Class/Session/Home/View/Model/HomePhotosModel .swift
+87
-60
ImageCollectionModel.swift
.../Class/Session/Home/View/Model/ImageCollectionModel.swift
+1
-1
ImageSeletedCollectionItem.swift
.../Session/Home/View/Model/ImageSeletedCollectionItem.swift
+1
-1
HomeOtherCollectionCell.swift
...lass/Session/Home/View/cell/HomeOtherCollectionCell.swift
+2
-2
HomePhotosDetailCollectionCell.swift
...ssion/Home/View/cell/HomePhotosDetailCollectionCell.swift
+3
-3
HomeTitleCollectionCell.swift
...lass/Session/Home/View/cell/HomeTitleCollectionCell.swift
+0
-3
HomeVideoDetailCell.swift
...er/Class/Session/Home/View/cell/HomeVideoDetailCell.swift
+4
-4
ImageCollectionCell.swift
...er/Class/Session/Home/View/cell/ImageCollectionCell.swift
+1
-1
ImageSeletedCollectionCell.swift
...s/Session/Home/View/cell/ImageSeletedCollectionCell.swift
+2
-2
PMShowImgVideoController.swift
...nager/Class/Session/Secret/PMShowImgVideoController.swift
+1
-1
PhotoAndVideoMananger.swift
...l/Class/PhotoAndVideoMananger/PhotoAndVideoMananger.swift
+163
-66
PhotoSimilarityFinder.swift
...l/Class/PhotoAndVideoMananger/PhotoSimilarityFinder.swift
+22
-5
No files found.
PhoneManager/Class/Session/Home/Controller/HomeInfoViewController.swift
View file @
71bca841
...
...
@@ -89,11 +89,11 @@ class HomeInfoViewController:BaseViewController {
return
sview
}()
var
ids
:
[[
String
]]?
var
ids
:
[[
AssetModel
]]?
var
titleText
:
String
?
init
(
ids
:
[[
String
]],
type
:
PhotsFileType
?,
titleText
:
String
)
{
init
(
ids
:
[[
AssetModel
]],
type
:
PhotsFileType
?,
titleText
:
String
)
{
self
.
ids
=
ids
self
.
type
=
type
self
.
titleText
=
titleText
...
...
PhoneManager/Class/Session/Home/Controller/HomePhotosDetailViewController.swift
View file @
71bca841
...
...
@@ -29,10 +29,10 @@ class HomePhotosDetailViewController : BaseViewController {
private
var
videoDetailNavView
:
VideoDetaiNavView
?
var
resourceData
:
[
String
]
=
[]
var
resourceData
:
[
AssetModel
]
=
[]
func
dealData
(){
var
dataArray
:
[
String
]
=
[]
var
dataArray
:
[
AssetModel
]
=
[]
for
item
in
self
.
model
.
assets
{
dataArray
=
dataArray
+
item
}
...
...
@@ -52,7 +52,7 @@ class HomePhotosDetailViewController : BaseViewController {
}
// 当前页面选中的
var
selectedModel
:
[
String
]
=
[]
{
var
selectedModel
:
[
AssetModel
]
=
[]
{
didSet
{
if
self
.
selectedModel
.
count
==
0
{
self
.
deleteButton
.
setTitle
(
"Delete"
,
for
:
.
normal
)
...
...
@@ -86,12 +86,6 @@ class HomePhotosDetailViewController : BaseViewController {
}()
// lazy var emptyTrashView : EmptyTrashView = {
// let view = EmptyTrashView()
// view.backgroundColor = .white
// return view
// }()
lazy
var
deleteButton
:
UIButton
=
{
let
view
=
UIButton
()
view
.
setTitle
(
"Delete"
,
for
:
UIControl
.
State
.
normal
)
...
...
@@ -137,12 +131,6 @@ class HomePhotosDetailViewController : BaseViewController {
}
// self.view.addSubview(self.emptyTrashView)
// self.emptyTrashView.snp.makeConstraints { make in
// make.left.right.equalToSuperview()
// make.bottom.equalToSuperview().offset(-34)
// make.height.equalTo(70)
// }
self
.
view
.
insertSubview
(
collectionView
,
at
:
0
)
self
.
view
.
addSubview
(
self
.
deleteButton
)
...
...
@@ -195,7 +183,7 @@ extension HomePhotosDetailViewController:WaterfallMutiSectionDelegate,UICollecti
cell
.
resourceIdent
=
self
.
resourceData
[
indexPath
.
row
]
cell
.
currentOrder
=
indexPath
.
row
if
self
.
selectedModel
.
contains
(
cell
.
resourceIdent
)
{
if
self
.
selectedModel
.
contains
(
where
:
{
$0
.
localIdentifier
==
cell
.
resourceIdent
.
localIdentifier
}
)
{
cell
.
choose
=
true
}
else
{
cell
.
choose
=
false
...
...
@@ -214,7 +202,7 @@ extension HomePhotosDetailViewController:WaterfallMutiSectionDelegate,UICollecti
dataSource
.
isSeleted
=
true
dataSource
.
id
=
ident
// 获取image
dataSource
.
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
ident
)
dataSource
.
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
ident
.
localIdentifier
)
vc
.
homeDataSource
=
[
dataSource
]
self
.
navigationController
?
.
pushViewController
(
vc
,
animated
:
true
)
...
...
@@ -225,7 +213,7 @@ extension HomePhotosDetailViewController:WaterfallMutiSectionDelegate,UICollecti
if
click
==
true
{
self
.
selectedModel
.
append
(
self
.
resourceData
[
order
])
}
else
{
self
.
selectedModel
.
removeAll
{
$0
==
self
.
resourceData
[
order
]
}
self
.
selectedModel
.
removeAll
{
$0
.
localIdentifier
==
self
.
resourceData
[
order
]
.
localIdentifier
}
}
DispatchQueue
.
main
.
async
{
if
self
.
selectedModel
.
count
>
0
{
...
...
@@ -338,54 +326,21 @@ extension HomePhotosDetailViewController:WaterfallMutiSectionDelegate,UICollecti
/// 对当前页面资源排序(注意这里获取的资源是image)
/// - Parameter sortType: 排序类型
func
sortByType
(
sortType
:
Int
){
// 实际就是对Video数据排序
var
assetsWithSize
:
[(
asset
:
PHAsset
,
size
:
Int64
)]
=
[]
let
allImagesResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
self
.
resourceData
,
options
:
nil
)
let
allImages
=
allImagesResult
.
objects
(
at
:
IndexSet
(
0
..<
allImagesResult
.
count
))
for
item
in
allImages
{
let
resources
=
PHAssetResource
.
assetResources
(
for
:
item
)
for
resource
in
resources
{
if
let
fileSize
=
resource
.
value
(
forKey
:
"fileSize"
)
as?
Int64
{
assetsWithSize
.
append
((
item
,
fileSize
))
}
}
}
if
sortType
==
0
||
sortType
==
1
{
if
sortType
==
0
{
assetsWithSize
=
assetsWithSize
.
sorted
{
$0
.
size
<
$1
.
size
}
}
else
{
assetsWithSize
=
assetsWithSize
.
sorted
{
$0
.
size
>
$1
.
size
}
}
// 输出排序后的资源信息
var
sources
:[
String
]
=
[]
for
(
_
,
item
)
in
assetsWithSize
.
enumerated
()
{
sources
.
append
(
item
.
asset
.
localIdentifier
)
}
self
.
resourceData
=
sources
}
if
sortType
==
2
||
sortType
==
3
{
var
assetsWithDate
:
[(
asset
:
PHAsset
,
size
:
Int64
)]
=
[]
if
sortType
==
2
{
assetsWithDate
=
assetsWithSize
.
sorted
{
guard
let
date1
=
$0
.
asset
.
creationDate
,
let
date2
=
$1
.
asset
.
creationDate
else
{
return
false
}
return
date1
>
date2
}
}
else
{
assetsWithDate
=
assetsWithSize
.
sorted
{
guard
let
date1
=
$0
.
asset
.
creationDate
,
let
date2
=
$1
.
asset
.
creationDate
else
{
return
false
}
return
date1
<
date2
}
}
var
sources
:[
String
]
=
[]
for
item
in
assetsWithDate
{
sources
.
append
(
item
.
asset
.
localIdentifier
)
}
self
.
resourceData
=
sources
switch
sortType
{
case
0
:
self
.
resourceData
=
self
.
resourceData
.
sorted
{
$0
.
assetSize
>
$1
.
assetSize
}
break
case
1
:
self
.
resourceData
=
self
.
resourceData
.
sorted
{
$0
.
assetSize
<
$1
.
assetSize
}
break
case
2
:
self
.
resourceData
=
self
.
resourceData
.
sorted
{
$0
.
createDate
>
$1
.
createDate
}
break
case
3
:
self
.
resourceData
=
self
.
resourceData
.
sorted
{
$0
.
createDate
<
$1
.
createDate
}
break
default
:
break
}
}
...
...
@@ -393,7 +348,8 @@ extension HomePhotosDetailViewController:WaterfallMutiSectionDelegate,UICollecti
@objc
func
deleteButtonAction
(){
// 删除当前选择
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
self
.
selectedModel
,
options
:
nil
)
let
allIdent
=
self
.
selectedModel
.
map
{
$0
.
localIdentifier
}
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
allIdent
,
options
:
nil
)
PHPhotoLibrary
.
shared
()
.
performChanges
({
PHAssetChangeRequest
.
deleteAssets
(
fetchResult
as
NSFastEnumeration
)
}){
success
,
error
in
...
...
@@ -401,7 +357,7 @@ extension HomePhotosDetailViewController:WaterfallMutiSectionDelegate,UICollecti
print
(
"删除文件成功"
)
// 移除当前总数据源的数据
for
item
in
self
.
selectedModel
{
self
.
resourceData
.
removeAll
{
$0
==
item
}
self
.
resourceData
.
removeAll
{
$0
.
localIdentifier
==
item
.
localIdentifier
}
}
}
else
{
if
let
error
=
error
{
...
...
PhoneManager/Class/Session/Home/Controller/HomeVideoDetailController.swift
View file @
71bca841
...
...
@@ -25,10 +25,10 @@ class HomeVideoDetailController :BaseViewController {
private
var
videoDetailNavView
:
VideoDetaiNavView
?
var
resourceData
:
[
String
]
=
[]
var
resourceData
:
[
AssetModel
]
=
[]
func
dealData
(){
var
dataArray
:
[
String
]
=
[]
var
dataArray
:
[
AssetModel
]
=
[]
for
item
in
self
.
model
.
assets
{
dataArray
=
dataArray
+
item
}
...
...
@@ -46,7 +46,7 @@ class HomeVideoDetailController :BaseViewController {
}
// 当前页面选中的
var
selectedModel
:
[
String
]
=
[]
{
var
selectedModel
:
[
AssetModel
]
=
[]
{
didSet
{
DispatchQueue
.
main
.
async
{
[
self
]
in
if
self
.
selectedModel
.
count
==
0
{
...
...
@@ -182,7 +182,7 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
cell
.
resourceIdent
=
self
.
resourceData
[
indexPath
.
row
]
cell
.
currentOrder
=
indexPath
.
row
if
self
.
selectedModel
.
contains
(
cell
.
resourceIdent
)
{
if
self
.
selectedModel
.
contains
(
where
:
{
$0
.
localIdentifier
==
cell
.
resourceIdent
!.
localIdentifier
}
)
{
cell
.
choose
=
true
}
else
{
cell
.
choose
=
false
...
...
@@ -193,7 +193,7 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
if
click
==
true
{
self
.
selectedModel
.
append
(
self
.
resourceData
[
order
])
}
else
{
self
.
selectedModel
.
removeAll
{
$0
==
self
.
resourceData
[
order
]
}
self
.
selectedModel
.
removeAll
{
$0
.
localIdentifier
==
self
.
resourceData
[
order
]
.
localIdentifier
}
}
DispatchQueue
.
main
.
async
{
if
self
.
selectedModel
.
count
>
0
{
...
...
@@ -220,7 +220,7 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
dataSource
.
image
=
image
// 表示这个是视频
vc
.
homeDataSource
=
[
dataSource
]
vc
.
getVideoURLFromLocalIdentifier
(
localIdentifier
:
ident
)
{
url
,
error
in
vc
.
getVideoURLFromLocalIdentifier
(
localIdentifier
:
ident
.
localIdentifier
)
{
url
,
error
in
if
url
!=
nil
{
DispatchQueue
.
main
.
async
{
...
...
@@ -322,7 +322,7 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
@objc
func
deleteButtonAction
(){
// 删除当前选择
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
self
.
selectedModel
,
options
:
nil
)
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
self
.
selectedModel
.
map
{
$0
.
localIdentifier
}
,
options
:
nil
)
PHPhotoLibrary
.
shared
()
.
performChanges
({
PHAssetChangeRequest
.
deleteAssets
(
fetchResult
as
NSFastEnumeration
)
}){
success
,
error
in
...
...
@@ -330,7 +330,7 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
print
(
"删除文件成功"
)
// 移除当前总数据源的数据
for
item
in
self
.
selectedModel
{
self
.
resourceData
.
removeAll
{
$0
==
item
}
self
.
resourceData
.
removeAll
{
$0
.
localIdentifier
==
item
.
localIdentifier
}
}
}
else
{
if
let
error
=
error
{
...
...
@@ -384,55 +384,21 @@ extension HomeVideoDetailController:WaterfallMutiSectionDelegate,UICollectionVie
}
func
sortByType
(
sortType
:
Int
){
// 实际就是对Video数据排序
var
assetsWithSize
:
[(
asset
:
PHAsset
,
size
:
Int64
)]
=
[]
let
allVideos
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
self
.
resourceData
,
options
:
nil
)
allVideos
.
enumerateObjects
{
(
asset
,
index
,
stop
)
in
let
resources
=
PHAssetResource
.
assetResources
(
for
:
asset
)
for
resource
in
resources
{
if
let
fileSize
=
resource
.
value
(
forKey
:
"fileSize"
)
as?
Int64
{
assetsWithSize
.
append
((
asset
,
fileSize
))
}
}
}
if
sortType
==
0
||
sortType
==
1
{
if
sortType
==
0
{
assetsWithSize
=
assetsWithSize
.
sorted
{
$0
.
size
<
$1
.
size
}
}
else
{
assetsWithSize
=
assetsWithSize
.
sorted
{
$0
.
size
>
$1
.
size
}
}
// 输出排序后的资源信息
var
sources
:[
String
]
=
[]
for
(
_
,
item
)
in
assetsWithSize
.
enumerated
()
{
sources
.
append
(
item
.
asset
.
localIdentifier
)
}
self
.
resourceData
=
sources
}
if
sortType
==
2
||
sortType
==
3
{
var
assetsWithDate
:
[(
asset
:
PHAsset
,
size
:
Int64
)]
=
[]
if
sortType
==
2
{
assetsWithDate
=
assetsWithSize
.
sorted
{
guard
let
date1
=
$0
.
asset
.
creationDate
,
let
date2
=
$1
.
asset
.
creationDate
else
{
return
false
}
return
date1
>
date2
}
}
else
{
assetsWithDate
=
assetsWithSize
.
sorted
{
guard
let
date1
=
$0
.
asset
.
creationDate
,
let
date2
=
$1
.
asset
.
creationDate
else
{
return
false
}
return
date1
<
date2
}
}
var
sources
:[
String
]
=
[]
for
item
in
assetsWithDate
{
sources
.
append
(
item
.
asset
.
localIdentifier
)
}
self
.
resourceData
=
sources
switch
sortType
{
case
0
:
self
.
resourceData
=
self
.
resourceData
.
sorted
{
$0
.
assetSize
>
$1
.
assetSize
}
break
case
1
:
self
.
resourceData
=
self
.
resourceData
.
sorted
{
$0
.
assetSize
<
$1
.
assetSize
}
break
case
2
:
self
.
resourceData
=
self
.
resourceData
.
sorted
{
$0
.
createDate
>
$1
.
createDate
}
break
case
3
:
self
.
resourceData
=
self
.
resourceData
.
sorted
{
$0
.
createDate
<
$1
.
createDate
}
break
default
:
break
}
}
...
...
PhoneManager/Class/Session/Home/View/HomeInfoView.swift
View file @
71bca841
...
...
@@ -9,7 +9,7 @@ import UIKit
class
HomeInfoView
:
UIView
{
var
ids
:[[
String
]]?
var
ids
:[[
AssetModel
]]?
var
titleText
:
String
?
...
...
@@ -72,7 +72,7 @@ class HomeInfoView :UIView{
return
sview
}()
init
(
frame
:
CGRect
,
ids
:[[
String
]]?,
type
:
PhotsFileType
?,
titleText
:
String
?)
{
init
(
frame
:
CGRect
,
ids
:[[
AssetModel
]]?,
type
:
PhotsFileType
?,
titleText
:
String
?)
{
self
.
ids
=
ids
self
.
titleText
=
titleText
...
...
@@ -164,9 +164,9 @@ class HomeInfoView :UIView{
setTitleView
()
}
func
getSelectedArray
()
->
[
String
]
{
func
getSelectedArray
()
->
[
AssetModel
]
{
var
selectedArray
:[
String
]
=
[]
var
selectedArray
:[
AssetModel
]
=
[]
for
smodel
in
models
{
...
...
@@ -174,7 +174,7 @@ class HomeInfoView :UIView{
if
smodel2
.
isSeleted
??
false
{
selectedArray
.
append
(
smodel2
.
id
)
selectedArray
.
append
(
smodel2
.
id
!
)
}
}
}
...
...
PhoneManager/Class/Session/Home/View/Model/HomePhotosModel .swift
View file @
71bca841
...
...
@@ -54,6 +54,7 @@ class PhotoDataManager {
}
}
private
func
loadDataFromPhotos
(
resultModel
:
@escaping
(
_
model
:
PhotosManagerModel
)
->
()
=
{
mdoel
in
})
{
PhotoAndVideoMananger
.
mananger
.
setAssets
()
...
...
@@ -75,54 +76,62 @@ class PhotoDataManager {
let
allModel
:
PhotosManagerModel
=
PhotosManagerModel
(
allFileNumber
:
0
,
allFileSize
:
0
,
titleModelArray
:
[
model1
,
model2
],
otherModelArray
:
[
model3
,
model4
,
model5
,
model6
,
model7
])
resultModel
(
allModel
)
let
semaphore
=
DispatchSemaphore
(
value
:
1
)
DispatchQueue
.
global
()
.
async
{
// 重复照片
semaphore
.
wait
()
Print
(
"正在处理重复图片"
)
PhotoAndVideoMananger
.
mananger
.
dealSimilarPhotos
(
assets
:
PhotoAndVideoMananger
.
mananger
.
allAssets
,
threshold
:
0.99
)
{
data
in
var
dataArray
:
[
String
]
=
[]
for
item
in
data
{
dataArray
=
dataArray
+
item
PhotoAndVideoMananger
.
mananger
.
dealSimilarPhotos
(
assets
:
PhotoAndVideoMananger
.
mananger
.
allAssets
,
threshold
:
0.99
)
{
data1
,
data2
in
var
dataArray1
:
[
AssetModel
]
=
[]
var
dataArray2
:
[
AssetModel
]
=
[]
for
item
in
data1
{
dataArray1
=
dataArray1
+
item
}
PhotoAndVideoMananger
.
mananger
.
calculateTotalSize
(
of
:
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithIDs
(
ids
:
dataArray
)
!
,
progress
:
{
fileSiez
,
index
in
for
item
in
data2
{
dataArray2
=
dataArray2
+
item
}
PhotoAndVideoMananger
.
mananger
.
calculateTotalSize
(
of
:
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithIDs
(
ids
:
dataArray1
)
!
,
progress
:
{
fileSiez
,
index
in
// 不做处理
},
completion
:
{
fileSize
,
index
in
model1
.
assets
=
data
model1
.
assets
=
data
1
model1
.
allFileSize
=
Double
(
fileSize
)
resultModel
(
allModel
)
Print
(
"处理重复图片结束"
)
})
semaphore
.
signal
()
PhotoAndVideoMananger
.
mananger
.
calculateTotalSize
(
of
:
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithIDs
(
ids
:
dataArray2
)
!
,
progress
:
{
fileSize
,
index
in
// 不做处理
},
completion
:
{
fileSize
,
index
in
model2
.
assets
=
data2
model2
.
allFileSize
=
Double
(
fileSize
)
resultModel
(
allModel
)
})
}
completionHandler
:
{
data1
,
data2
in
var
dataArray1
:
[
AssetModel
]
=
[]
var
dataArray2
:
[
AssetModel
]
=
[]
for
item
in
data1
{
dataArray1
=
dataArray1
+
item
}
// 相似照片
semaphore
.
wait
()
Print
(
"正在处理相似照片"
)
PhotoAndVideoMananger
.
mananger
.
dealSimilarPhotos
(
assets
:
PhotoAndVideoMananger
.
mananger
.
allAssets
,
threshold
:
0.85
)
{
data
in
var
dataArray
:
[
String
]
=
[]
for
item
in
data
{
dataArray
=
dataArray
+
item
for
item
in
data2
{
dataArray2
=
dataArray2
+
item
}
PhotoAndVideoMananger
.
mananger
.
calculateTotalSize
(
of
:
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithIDs
(
ids
:
dataArray
)
!
,
progress
:
{
fileSiez
,
index
in
PhotoAndVideoMananger
.
mananger
.
calculateTotalSize
(
of
:
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithIDs
(
ids
:
dataArray
1
)
!
,
progress
:
{
fileSiez
,
index
in
// 不做处理
},
completion
:
{
fileSize
,
index
in
model
2
.
assets
=
data
model
2
.
allFileSize
=
Double
(
fileSize
)
model
1
.
assets
=
data1
model
1
.
allFileSize
=
Double
(
fileSize
)
resultModel
(
allModel
)
Print
(
"处理相似图片结束"
)
})
semaphore
.
signal
()
PhotoAndVideoMananger
.
mananger
.
calculateTotalSize
(
of
:
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithIDs
(
ids
:
dataArray1
)
!
,
progress
:
{
fileSize
,
index
in
// 不做处理
},
completion
:
{
fileSize
,
index
in
model2
.
assets
=
data2
model2
.
allFileSize
=
Double
(
fileSize
)
resultModel
(
allModel
)
})
Print
(
"处理重复图片结束"
)
}
// 视频数据
semaphore
.
wait
()
Print
(
"正在处理视频"
)
PhotoAndVideoMananger
.
mananger
.
dealVideoData
{
data
in
var
dataArray
:
[
String
]
=
[]
var
dataArray
:
[
AssetModel
]
=
[]
for
item
in
data
{
dataArray
=
dataArray
+
item
}
...
...
@@ -134,33 +143,42 @@ class PhotoDataManager {
resultModel
(
allModel
)
Print
(
"处理视频结束"
)
})
semaphore
.
signal
()
}
// 相似截图
semaphore
.
wait
()
Print
(
"正在处理相似截图"
)
PhotoAndVideoMananger
.
mananger
.
dealSimilarPhotos
(
assets
:
PhotoAndVideoMananger
.
mananger
.
screenShotAssets
,
threshold
:
0.85
)
{
data
in
var
dataArray
:
[
String
]
=
[]
for
item
in
data
{
dataArray
=
dataArray
+
item
PhotoAndVideoMananger
.
mananger
.
dealSimilarPhotos
(
assets
:
PhotoAndVideoMananger
.
mananger
.
screenShotAssets
,
threshold
:
0.99
)
{
data1
,
data2
in
var
dataArray1
:
[
AssetModel
]
=
[]
for
item
in
data1
{
dataArray1
=
dataArray1
+
item
}
PhotoAndVideoMananger
.
mananger
.
calculateTotalSize
(
of
:
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithIDs
(
ids
:
dataArray
)
!
,
progress
:
{
fileSiez
,
index
in
PhotoAndVideoMananger
.
mananger
.
calculateTotalSize
(
of
:
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithIDs
(
ids
:
dataArray1
)
!
,
progress
:
{
fileSiez
,
index
in
// 不做处理
},
completion
:
{
fileSize
,
index
in
model4
.
assets
=
data
model4
.
assets
=
data1
model4
.
allFileSize
=
Double
(
fileSize
)
resultModel
(
allModel
)
Print
(
"处理相似截图结束"
)
})
}
completionHandler
:
{
data1
,
data2
in
var
dataArray1
:
[
AssetModel
]
=
[]
for
item
in
data1
{
dataArray1
=
dataArray1
+
item
}
PhotoAndVideoMananger
.
mananger
.
calculateTotalSize
(
of
:
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithIDs
(
ids
:
dataArray1
)
!
,
progress
:
{
fileSiez
,
index
in
// 不做处理
},
completion
:
{
fileSize
,
index
in
model4
.
assets
=
data1
model4
.
allFileSize
=
Double
(
fileSize
)
resultModel
(
allModel
)
})
semaphore
.
signal
()
}
// 截图数据
semaphore
.
wait
()
Print
(
"正在处理截图"
)
PhotoAndVideoMananger
.
mananger
.
dealScreenShotData
{
data
in
var
dataArray
:
[
String
]
=
[]
var
dataArray
:
[
AssetModel
]
=
[]
for
item
in
data
{
dataArray
=
dataArray
+
item
}
...
...
@@ -172,15 +190,13 @@ class PhotoDataManager {
resultModel
(
allModel
)
Print
(
"处理截图结束"
)
})
semaphore
.
signal
()
}
// 相似视频
semaphore
.
wait
()
Print
(
"正在处理相似视频"
)
PhotoAndVideoMananger
.
mananger
.
fetXSVideo
{
array
in
PhotoSimilarityFinder
.
processSimilarVideoGroups
(
videoGroups
:
array
)
{
ids
in
var
dataArray
:
[
String
]
=
[]
var
dataArray
:
[
AssetModel
]
=
[]
for
item
in
ids
{
dataArray
=
dataArray
+
item
}
...
...
@@ -192,15 +208,12 @@ class PhotoDataManager {
resultModel
(
allModel
)
})
Print
(
"处理相似视频结束"
)
semaphore
.
signal
()
}
}
// 照片数据
semaphore
.
wait
()
Print
(
"正在处理其他"
)
PhotoAndVideoMananger
.
mananger
.
dealImageAssetData
{
data
in
var
dataArray
:
[
String
]
=
[]
var
dataArray
:
[
AssetModel
]
=
[]
for
item
in
data
{
dataArray
=
dataArray
+
item
}
...
...
@@ -211,12 +224,11 @@ class PhotoDataManager {
model7
.
allFileSize
=
Double
(
fileSize
)
resultModel
(
allModel
)
// 最后做一下缓存
PhotoDataManager
.
manager
.
saveToFileSystem
(
model
:
allModel
)
//
PhotoDataManager.manager.saveToFileSystem(model: allModel)
})
semaphore
.
signal
()
}
}
//
}
}
}
...
...
@@ -239,11 +251,26 @@ class HomePhotosModel:Codable {
var
folderName
:
String
var
allFileSize
:
Double
var
assets
:[[
String
]]
var
assets
:[[
AssetModel
]]
init
(
folderName
:
String
,
allFileSize
:
Double
,
assets
:
[[
String
]])
{
init
(
folderName
:
String
,
allFileSize
:
Double
,
assets
:
[[
AssetModel
]])
{
self
.
folderName
=
folderName
self
.
allFileSize
=
allFileSize
self
.
assets
=
assets
}
}
class
AssetModel
:
Codable
{
var
localIdentifier
:
String
var
assetSize
:
Double
var
createDate
:
Date
init
(
localIdentifier
:
String
,
assetSize
:
Double
,
createDate
:
Date
)
{
self
.
localIdentifier
=
localIdentifier
self
.
assetSize
=
assetSize
self
.
createDate
=
createDate
}
}
PhoneManager/Class/Session/Home/View/Model/ImageCollectionModel.swift
View file @
71bca841
...
...
@@ -10,5 +10,5 @@ import Photos
struct
ImageCollectionModel
{
var
asset
:
String
var
asset
:
AssetModel
}
PhoneManager/Class/Session/Home/View/Model/ImageSeletedCollectionItem.swift
View file @
71bca841
...
...
@@ -10,7 +10,7 @@ import UIKit
class
ImageSeletedCollectionItem
{
var
id
:
String
=
""
var
id
:
AssetModel
?
var
image
:
UIImage
?
var
isSeleted
:
Bool
?
}
...
...
PhoneManager/Class/Session/Home/View/cell/HomeOtherCollectionCell.swift
View file @
71bca841
...
...
@@ -130,7 +130,7 @@ class HomeOtherCollectionCell: UICollectionViewCell {
guard
let
asset
=
model
.
assets
.
first
?
.
first
else
{
return
}
if
self
.
mediaType
==
0
{
let
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
asset
)
let
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
asset
.
localIdentifier
)
DispatchQueue
.
main
.
async
{[
weak
self
]
in
guard
let
self
else
{
return
}
imageView
.
image
=
image
...
...
@@ -148,7 +148,7 @@ class HomeOtherCollectionCell: UICollectionViewCell {
// 异步请求
options
.
isSynchronous
=
false
// 从 PHAsset 获取 AVAsset
if
let
videoAsset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
asset
]){
if
let
videoAsset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
asset
.
localIdentifier
]){
// 使用requestImageForAsset方法请求视频的第一帧图片
PHImageManager
.
default
()
.
requestImage
(
for
:
videoAsset
,
targetSize
:
CGSize
(
width
:
400
,
height
:
400
),
contentMode
:
PHImageContentMode
.
aspectFit
,
options
:
options
)
{
image
,
_
in
// 处理获取到的图片
...
...
PhoneManager/Class/Session/Home/View/cell/HomePhotosDetailCollectionCell.swift
View file @
71bca841
...
...
@@ -12,7 +12,7 @@ class HomePhotosDetailCollectionCell : UICollectionViewCell {
var
clickCallBack
:
(
Bool
,
Int
)
->
Void
=
{
choose
,
order
in
}
var
cellCallBack
:
(
String
,
Int
)
->
Void
=
{
ident
,
order
in
}
var
cellCallBack
:
(
AssetModel
,
Int
)
->
Void
=
{
ident
,
order
in
}
var
currentMediaType
:
Int
=
0
...
...
@@ -27,10 +27,10 @@ class HomePhotosDetailCollectionCell : UICollectionViewCell {
}
}
var
resourceIdent
:
String
=
""
{
var
resourceIdent
:
AssetModel
=
AssetModel
(
localIdentifier
:
""
,
assetSize
:
0.0
,
createDate
:
Date
())
{
didSet
{
DispatchQueue
.
global
()
.
async
{
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
[
self
.
resourceIdent
],
options
:
nil
)
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
[
self
.
resourceIdent
.
localIdentifier
],
options
:
nil
)
let
assetsArray
=
fetchResult
.
objects
(
at
:
IndexSet
(
0
..<
fetchResult
.
count
))
let
options
=
PHImageRequestOptions
()
options
.
isNetworkAccessAllowed
=
true
...
...
PhoneManager/Class/Session/Home/View/cell/HomeTitleCollectionCell.swift
View file @
71bca841
...
...
@@ -107,9 +107,6 @@ class HomeTitleCollectionCell:UICollectionViewCell {
assetsModels
.
append
(
smodel
)
}
Print
(
assetsModels
)
Print
(
model
.
assets
)
DispatchQueue
.
main
.
async
{[
weak
self
]
in
guard
let
self
else
{
return
}
...
...
PhoneManager/Class/Session/Home/View/cell/HomeVideoDetailCell.swift
View file @
71bca841
...
...
@@ -12,11 +12,11 @@ class HomeVideoDetailCell : UICollectionViewCell {
var
clickCallBack
:
(
Bool
,
Int
)
->
Void
=
{
choose
,
order
in
}
var
cellCallBack
:
(
String
,
Int
)
->
Void
=
{
ident
,
order
in
}
var
cellCallBack
:
(
AssetModel
,
Int
)
->
Void
=
{
ident
,
order
in
}
var
currentMediaType
:
Int
=
0
var
resourceIdent
:
String
=
""
{
var
resourceIdent
:
AssetModel
?
{
didSet
{
// 定义请求选项来获取视频的第一帧
let
options
=
PHImageRequestOptions
()
...
...
@@ -29,7 +29,7 @@ class HomeVideoDetailCell : UICollectionViewCell {
// 异步请求
options
.
isSynchronous
=
true
// 从 PHAsset 获取 AVAsset
if
let
videoAsset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
resourceIdent
]){
if
let
videoAsset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
resourceIdent
!.
localIdentifier
]){
// 使用requestImageForAsset方法请求视频的第一帧图片
PHImageManager
.
default
()
.
requestImage
(
for
:
videoAsset
,
targetSize
:
CGSize
(
width
:
400
,
height
:
400
),
contentMode
:
PHImageContentMode
.
aspectFit
,
options
:
options
)
{
image
,
_
in
// 处理获取到的图片
...
...
@@ -149,7 +149,7 @@ class HomeVideoDetailCell : UICollectionViewCell {
}
@objc
func
cellClick
(){
cellCallBack
(
self
.
resourceIdent
,
self
.
currentOrder
)
cellCallBack
(
self
.
resourceIdent
!
,
self
.
currentOrder
)
}
...
...
PhoneManager/Class/Session/Home/View/cell/ImageCollectionCell.swift
View file @
71bca841
...
...
@@ -34,7 +34,7 @@ class ImageCollectionCell:UICollectionViewCell {
guard
let
self
else
{
return
}
let
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
model
.
asset
)
let
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAssetID
(
id
:
model
.
asset
.
localIdentifier
)
DispatchQueue
.
main
.
async
{[
weak
self
]
in
...
...
PhoneManager/Class/Session/Home/View/cell/ImageSeletedCollectionCell.swift
View file @
71bca841
...
...
@@ -71,7 +71,7 @@ class ImageSeletedCollectionCell:UICollectionViewCell {
// 异步请求
options
.
isSynchronous
=
false
// 从 PHAsset 获取 AVAsset
if
let
videoAsset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
model
.
id
]){
if
let
videoAsset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
model
.
id
!.
localIdentifier
]){
// 使用requestImageForAsset方法请求视频的第一帧图片
PHImageManager
.
default
()
.
requestImage
(
for
:
videoAsset
,
targetSize
:
CGSize
(
width
:
400
,
height
:
400
),
contentMode
:
PHImageContentMode
.
aspectFit
,
options
:
options
)
{
image
,
_
in
// 处理获取到的图片
...
...
@@ -89,7 +89,7 @@ class ImageSeletedCollectionCell:UICollectionViewCell {
}
}
}
else
{
if
let
asset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
model
.
id
]){
if
let
asset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
model
.
id
!.
localIdentifier
]){
let
image
=
PhotoAndVideoMananger
.
mananger
.
getImageFromAsset
(
asset
:
asset
)
model
.
image
=
image
...
...
PhoneManager/Class/Session/Secret/PMShowImgVideoController.swift
View file @
71bca841
...
...
@@ -185,7 +185,7 @@ extension PMShowImgVideoController : UICollectionViewDelegate,UICollectionViewDa
let
cell
=
collectionView
.
dequeueReusableCell
(
withReuseIdentifier
:
PMShowVideoCellID
,
for
:
indexPath
)
as!
PMShowVideoCell
// 获取相似视频的URL
DispatchQueue
.
global
()
.
async
{
self
.
getVideoURLFromLocalIdentifier
(
localIdentifier
:
self
.
homeDataSource
!
[
indexPath
.
row
]
.
id
)
{[
weak
self
]
url
,
error
in
self
.
getVideoURLFromLocalIdentifier
(
localIdentifier
:
self
.
homeDataSource
!
[
indexPath
.
row
]
.
id
!.
localIdentifier
)
{[
weak
self
]
url
,
error
in
guard
self
!=
nil
else
{
return
}
if
let
error
=
error
{
print
(
"获取视频 URL 时出错:
\(
error
.
localizedDescription
)
"
)
...
...
PhoneManager/Class/Tool/Class/PhotoAndVideoMananger/PhotoAndVideoMananger.swift
View file @
71bca841
...
...
@@ -606,10 +606,10 @@ class PhotoAndVideoMananger {
return
assetsArray
.
first
}
func
getPHAsssetwithIDs
(
ids
:[
String
])
->
[
PHAsset
]?
{
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
ids
,
options
:
nil
)
func
getPHAsssetwithIDs
(
ids
:[
AssetModel
])
->
[
PHAsset
]?
{
let
localIdentifiers
=
ids
.
map
{
$0
.
localIdentifier
}
let
fetchResult
=
PHAsset
.
fetchAssets
(
withLocalIdentifiers
:
localIdentifiers
,
options
:
nil
)
let
assetsArray
=
fetchResult
.
objects
(
at
:
IndexSet
(
0
..<
fetchResult
.
count
))
return
assetsArray
...
...
@@ -659,31 +659,100 @@ 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
func
dealSimilarPhotos
(
assets
:[
PHAsset
]
,
threshold
:
Double
,
processHandler
:
@escaping
([[
AssetModel
]],[[
AssetModel
]])
->
Void
,
completionHandler
:
@escaping
([[
AssetModel
]],[[
AssetModel
]])
->
Void
){
dealSimilarDetailPhotos
(
assets
:
chunk
as
[
PHAsset
],
threshold
:
threshold
)
{
data
in
count
=
count
+
chunk
.
count
finalData
=
finalData
+
data
if
count
==
assets
.
count
{
completionHandler
(
finalData
)
DispatchQueue
.
global
()
.
async
{
// 图片请求选项
let
imageRequestOptions
=
PHImageRequestOptions
()
imageRequestOptions
.
isSynchronous
=
true
imageRequestOptions
.
deliveryMode
=
.
highQualityFormat
var
groupDuplicateAssets
:[[
AssetModel
]]
=
[]
var
groupSimilarAssets
:[[
AssetModel
]]
=
[]
for
(
currentIndex
,
currentAsset
)
in
assets
.
enumerated
()
{
var
currentDuplicateGroup
:
[
AssetModel
]
=
[]
var
currentSimilarGroup
:
[
AssetModel
]
=
[]
// 先添加一个到model
let
currentModel
=
AssetModel
.
init
(
localIdentifier
:
currentAsset
.
localIdentifier
,
assetSize
:
PhotoAndVideoMananger
.
mananger
.
findAssetSize
(
asset
:
currentAsset
),
createDate
:
currentAsset
.
creationDate
!
)
currentDuplicateGroup
.
append
(
currentModel
)
PHImageManager
.
default
()
.
requestImage
(
for
:
currentAsset
,
targetSize
:
CGSizeMake
(
400
,
400
),
contentMode
:
.
aspectFit
,
options
:
imageRequestOptions
)
{
image1
,
info1
in
let
nextIndex
=
currentIndex
+
1
if
nextIndex
<=
assets
.
count
{
for
changeIndex
in
nextIndex
..<
assets
.
count
{
let
changeAsset
=
assets
[
changeIndex
]
PHImageManager
.
default
()
.
requestImage
(
for
:
changeAsset
,
targetSize
:
CGSizeMake
(
400
,
400
),
contentMode
:
.
aspectFit
,
options
:
imageRequestOptions
)
{
image2
,
info2
in
let
isSamilar
:
Double
=
OpenCVWrapper
.
compareImageSimilarity
(
image1
,
withImage2
:
image2
)
if
isSamilar
>
0.995
&&
isSamilar
<
0.996
{
currentSimilarGroup
.
append
(
AssetModel
(
localIdentifier
:
changeAsset
.
localIdentifier
,
assetSize
:
self
.
findAssetSize
(
asset
:
changeAsset
),
createDate
:
changeAsset
.
creationDate
!
))
}
if
isSamilar
>
0.999
{
currentDuplicateGroup
.
append
(
AssetModel
(
localIdentifier
:
changeAsset
.
localIdentifier
,
assetSize
:
self
.
findAssetSize
(
asset
:
changeAsset
),
createDate
:
changeAsset
.
creationDate
!
))
}
}
}
}
if
(
currentSimilarGroup
.
count
>=
2
){
groupSimilarAssets
.
append
(
currentSimilarGroup
)
}
if
(
currentDuplicateGroup
.
count
>=
2
){
groupDuplicateAssets
.
append
(
currentDuplicateGroup
)
}
processHandler
(
groupDuplicateAssets
,
groupSimilarAssets
)
}
}
completionHandler
(
groupDuplicateAssets
,
groupSimilarAssets
)
}
// // 重复照片
// var index = assets.startIndex
// var count = 0
// var finalData :[[AssetModel]] = []
// 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], allAssets: assets, threshold: threshold) { data in
// count = count + chunk.count
// finalData = finalData + data
// if count == assets.count {
// completionHandler(finalData)
// }
// }
// }
}
/// 计算asset资源大小
/// - Parameter asset: 资源
/// - Returns: 文件大小
func
findAssetSize
(
asset
:
PHAsset
)
->
Double
{
let
resources
=
PHAssetResource
.
assetResources
(
for
:
asset
)
var
assetSize
:
Int
=
0
for
resource
in
resources
{
if
let
fileSize
=
resource
.
value
(
forKey
:
"fileSize"
)
as?
Int64
{
assetSize
+=
Int
(
fileSize
)
}
}
return
Double
(
assetSize
)
}
// 和上面的方法一起处理,防止内存崩溃
private
func
dealSimilarDetailPhotos
(
assets
:[
PHAsset
],
threshold
:
Double
,
completionHandler
:
@escaping
([[
String
]])
->
Void
){
private
func
dealSimilarDetailPhotos
(
assets
:[
PHAsset
],
allAssets
:[
PHAsset
],
threshold
:
Double
,
completionHandler
:
@escaping
([[
AssetModel
]])
->
Void
){
var
groupAssets
:[[
String
]]
=
[]
var
groupAssets
:[[
AssetModel
]]
=
[]
// 图片请求选项
let
imageRequestOptions
=
PHImageRequestOptions
()
...
...
@@ -695,22 +764,22 @@ class PhotoAndVideoMananger {
// 开一个线程去处理
DispatchQueue
.
global
()
.
async
{
//
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
]
=
[]
PHImageManager
.
default
()
.
requestImage
(
for
:
asset
,
targetSize
:
CGSizeMake
(
50
,
50
),
contentMode
:
.
aspectFit
,
options
:
imageRequestOptions
)
{
[
self
]
image1
,
info
in
var
currentGroup
:
[
AssetModel
]
=
[]
// 如果当前组为空,先加一个上去
currentGroup
.
append
(
asset
.
localIdentifier
)
currentGroup
.
append
(
AssetModel
(
localIdentifier
:
asset
.
localIdentifier
,
assetSize
:
self
.
findAssetSize
(
asset
:
asset
),
createDate
:
asset
.
creationDate
!
)
)
// 然后分成区域比较
var
index
=
assets
.
startIndex
while
index
<
assets
.
endIndex
{
let
nextIndex
=
assets
.
index
(
index
,
offsetBy
:
20
,
limitedBy
:
assets
.
endIndex
)
??
assets
.
endIndex
var
count2
=
0
while
index
<
allAssets
.
endIndex
{
let
nextIndex
=
assets
.
index
(
index
,
offsetBy
:
10
,
limitedBy
:
allAssets
.
endIndex
)
??
allAssets
.
endIndex
// 当前组
var
chunk
=
Array
(
assets
[
index
..<
nextIndex
])
var
chunk
=
Array
(
a
llA
ssets
[
index
..<
nextIndex
])
index
=
nextIndex
// 比较image重复
for
item
in
chunk
{
...
...
@@ -720,83 +789,111 @@ class PhotoAndVideoMananger {
let
isSamilar
:
Bool
=
OpenCVWrapper
.
areImagesSimilar
(
image1
,
withImage2
:
image2
,
threshold
:
threshold
)
// 如果相似或者相同
if
isSamilar
{
currentGroup
.
append
(
item
.
localIdentifier
)
currentGroup
.
append
(
AssetModel
(
localIdentifier
:
item
.
localIdentifier
,
assetSize
:
self
.
findAssetSize
(
asset
:
item
),
createDate
:
item
.
creationDate
!
))
}
}
count2
=
count2
+
1
}
if
count2
==
assets
.
count
&&
currentGroup
.
count
>=
2
{
// 将trunk移除
count2
=
count2
+
chunk
.
count
if
count2
==
allAssets
.
count
{
// 对当前组去重
let
result
=
removeDuplicates
(
currentGroup
)
if
(
result
.
count
>=
2
){
groupAssets
.
append
(
currentGroup
)
}
}
// 将trunk移除
chunk
.
removeAll
(
keepingCapacity
:
false
)
}
count1
=
count1
+
1
currentGroup
.
removeAll
(
keepingCapacity
:
false
)
}
count1
=
count1
+
1
if
count1
==
assets
.
count
{
completionHandler
(
self
.
removeDuplicates
(
from
:
groupAssets
))
completionHandler
(
self
.
removeDuplicatesIn2DArray
(
groupAssets
,
keyPath
:
\
.
localIdentifier
))
}
}
// }
}
// 去掉一维数组重复数据
func
removeDuplicates
(
_
array
:
[
AssetModel
])
->
[
AssetModel
]
{
var
uniqueLocalIdentifiers
:
[
String
]
=
[]
var
uniqueModel
:
[
AssetModel
]
=
[]
for
model
in
uniqueModel
{
if
!
uniqueLocalIdentifiers
.
contains
(
model
.
localIdentifier
)
{
uniqueLocalIdentifiers
.
append
(
model
.
localIdentifier
)
uniqueModel
.
append
(
model
)
}
}
return
uniqueModel
}
/// 去掉数据重复
/// - 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
)
func
removeDuplicatesIn2DArray
<
T
:
Hashable
>
(
_
array
:
[[
AssetModel
]],
keyPath
:
KeyPath
<
AssetModel
,
T
>
)
->
[[
AssetModel
]]
{
return
array
.
map
{
innerArray
in
var
seen
=
Set
<
T
>
()
return
innerArray
.
filter
{
if
seen
.
contains
(
$0
[
keyPath
:
keyPath
])
{
return
false
}
else
{
seen
.
insert
(
$0
[
keyPath
:
keyPath
])
return
true
}
}
}
return
result
}
// MARK: - 新方法处理相似图片向上-------------------------------------------------------
// MARK: - 处理视频数据-------------------------------------------------------
func
dealVideoData
(
completionHandler
:
@escaping
([[
String
]])
->
Void
){
var
data
:[
String
]
=
[]
func
dealVideoData
(
completionHandler
:
@escaping
([[
AssetModel
]])
->
Void
){
DispatchQueue
.
global
()
.
async
{
var
data
:[
AssetModel
]
=
[]
for
item
in
self
.
videoAssets
{
data
.
append
(
item
.
localIdentifier
)
data
.
append
(
AssetModel
.
init
(
localIdentifier
:
item
.
localIdentifier
,
assetSize
:
self
.
findAssetSize
(
asset
:
item
),
createDate
:
item
.
creationDate
!
)
)
}
var
finalData
:
[[
String
]]
=
[]
var
finalData
:
[[
AssetModel
]]
=
[]
finalData
.
append
(
data
)
completionHandler
(
finalData
)
}
}
// MARK: - 处理视频数据-------------------------------------------------------
// MARK: - 处理截图数据-------------------------------------------------------
func
dealScreenShotData
(
completionHandler
:
@escaping
([[
String
]])
->
Void
){
var
data
:[
String
]
=
[]
func
dealScreenShotData
(
completionHandler
:
@escaping
([[
AssetModel
]])
->
Void
){
DispatchQueue
.
global
()
.
async
{
var
data
:[
AssetModel
]
=
[]
for
item
in
self
.
screenShotAssets
{
data
.
append
(
item
.
localIdentifier
)
data
.
append
(
AssetModel
(
localIdentifier
:
item
.
localIdentifier
,
assetSize
:
self
.
findAssetSize
(
asset
:
item
),
createDate
:
item
.
creationDate
!
)
)
}
var
finalData
:
[[
String
]]
=
[]
var
finalData
:
[[
AssetModel
]]
=
[]
finalData
.
append
(
data
)
completionHandler
(
finalData
)
}
}
// MARK: - 处理截图数据-------------------------------------------------------
// MARK: - 处理照片数据-------------------------------------------------------
func
dealImageAssetData
(
completionHandler
:
@escaping
([[
String
]])
->
Void
){
var
data
:[
String
]
=
[]
func
dealImageAssetData
(
completionHandler
:
@escaping
([[
AssetModel
]])
->
Void
){
DispatchQueue
.
global
()
.
async
{
var
data
:[
AssetModel
]
=
[]
for
item
in
self
.
otherAssets
{
data
.
append
(
item
.
localIdentifier
)
data
.
append
(
AssetModel
(
localIdentifier
:
item
.
localIdentifier
,
assetSize
:
self
.
findAssetSize
(
asset
:
item
),
createDate
:
item
.
creationDate
!
)
)
}
var
finalData
:
[[
String
]]
=
[]
var
finalData
:
[[
AssetModel
]]
=
[]
finalData
.
append
(
data
)
completionHandler
(
finalData
)
}
}
// MARK: - 处理截图数据-------------------------------------------------------
...
...
@@ -806,7 +903,7 @@ class PhotoAndVideoMananger {
/// - Parameters:
/// - ident: 视频的标识
/// - finished: 完成回调
func
getVideoImageByIdent
(
ident
:
String
,
finished
:
@escaping
(
UIImage
)
->
Void
,
errorHandler
:
@escaping
()
->
Void
){
func
getVideoImageByIdent
(
ident
:
AssetModel
,
finished
:
@escaping
(
UIImage
)
->
Void
,
errorHandler
:
@escaping
()
->
Void
){
// 定义请求选项来获取视频的第一帧
let
options
=
PHImageRequestOptions
()
// 获取当前版本的照片或视频
...
...
@@ -818,7 +915,7 @@ class PhotoAndVideoMananger {
// 异步请求
options
.
isSynchronous
=
true
// 从 PHAsset 获取 AVAsset
if
let
videoAsset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
ident
]){
if
let
videoAsset
=
PhotoAndVideoMananger
.
mananger
.
getPHAsssetwithID
(
ids
:
[
ident
.
localIdentifier
]){
// 使用requestImageForAsset方法请求视频的第一帧图片
PHImageManager
.
default
()
.
requestImage
(
for
:
videoAsset
,
targetSize
:
CGSize
(
width
:
400
,
height
:
400
),
contentMode
:
PHImageContentMode
.
aspectFit
,
options
:
options
)
{
image
,
_
in
// 处理获取到的图片
...
...
PhoneManager/Class/Tool/Class/PhotoAndVideoMananger/PhotoSimilarityFinder.swift
View file @
71bca841
...
...
@@ -305,7 +305,7 @@ class PhotoSimilarityFinder {
}
}
static
func
processSimilarVideoGroups
(
videoGroups
:
[[
PHAsset
]],
completion
:
@escaping
([[
String
]])
->
Void
)
{
static
func
processSimilarVideoGroups
(
videoGroups
:
[[
PHAsset
]],
completion
:
@escaping
([[
AssetModel
]])
->
Void
)
{
print
(
"开始处理相似视频组..."
)
// 创建并发队列
...
...
@@ -390,11 +390,14 @@ class PhotoSimilarityFinder {
// 等待所有处理完成
group
.
notify
(
queue
:
.
main
)
{
// 将结果转换为 localIdentifier 数组
let
result
=
filteredGroups
.
map
{
group
in
group
.
map
{
$0
.
localIdentifier
}
var
result
:[[
AssetModel
]]
=
[]
for
item
in
filteredGroups
{
var
model
:
[
AssetModel
]
=
[]
for
item2
in
item
{
model
.
append
(
AssetModel
(
localIdentifier
:
item2
.
localIdentifier
,
assetSize
:
findAssetSize
(
asset
:
item2
),
createDate
:
item2
.
creationDate
!
))
}
result
.
append
(
model
)
}
print
(
"处理完成,剩余
\(
result
.
count
)
组相似视频"
)
completion
(
result
)
}
}
...
...
@@ -437,4 +440,18 @@ class PhotoSimilarityFinder {
}
}
}
/// 计算asset资源大小
/// - Parameter asset: 资源
/// - Returns: 文件大小
private
static
func
findAssetSize
(
asset
:
PHAsset
)
->
Double
{
let
resources
=
PHAssetResource
.
assetResources
(
for
:
asset
)
var
assetSize
:
Int
=
0
for
resource
in
resources
{
if
let
fileSize
=
resource
.
value
(
forKey
:
"fileSize"
)
as?
Int64
{
assetSize
+=
Int
(
fileSize
)
}
}
return
Double
(
assetSize
)
}
}
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