Commit 71bca841 authored by CZ1004's avatar CZ1004

修改数据源结构方式

parent 7ab40d47
......@@ -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
......
......@@ -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 {
......
......@@ -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
}
}
......
......@@ -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!)
}
}
}
......
......@@ -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 = data1
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: dataArray1)!,progress: { fileSiez, index in
// 不做处理
}, completion: { fileSize,index in
model2.assets = data
model2.allFileSize = Double(fileSize)
model1.assets = data1
model1.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
}
}
......@@ -10,5 +10,5 @@ import Photos
struct ImageCollectionModel {
var asset:String
var asset:AssetModel
}
......@@ -10,7 +10,7 @@ import UIKit
class ImageSeletedCollectionItem {
var id:String = ""
var id:AssetModel?
var image:UIImage?
var isSeleted:Bool?
}
......
......@@ -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
// 处理获取到的图片
......
......@@ -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
......
......@@ -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}
......
......@@ -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)
}
......
......@@ -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
......
......@@ -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
......
......@@ -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)")
......
......@@ -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(allAssets[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
// 处理获取到的图片
......
......@@ -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)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment