Commit 1cc0c07d authored by CZ1004's avatar CZ1004

压缩功能

parent d8fd3bc7
//
// CompressSelectCell.swift
// PhoneManager
//
// Created by edy on 2025/4/2.
//
import Foundation
typealias CompressSelectCellCallback = (ResourceModel,Bool)->Void
class CompressSelectCell : UICollectionViewCell {
var callBack : CompressSelectCellCallback = {model,choose in}
var model : ResourceModel? {
didSet{
guard let model = self.model else {return}
let image = PhotoAndVideoMananger.mananger.getImageFromAssetID(id: model.ident)
self.backImageView.image = image
// 把压缩前的值减去压缩后的值就为可以节省的值。然后这里需要判定下如果是大于1000MB,则再除以1024换算成GB
let saveSize = model.orgSize - model.compressSize
if saveSize > 1000 {
self.saveSizeLabel.text = String(format: "Save %.2f GB" ,saveSize/1024.0)
}else{
self.saveSizeLabel.text = String(format: "Save %.2f MB" ,saveSize)
}
}
}
var choose : Bool = false {
didSet{
if choose {
self.selectImageView.image = UIImage(named: "ic_unsel_com")
}else{
self.selectImageView.image = UIImage(named: "ic_sel_com")
}
callBack(self.model! ,self.choose)
}
}
lazy var backImageView: UIImageView = {
let view = UIImageView()
view.isUserInteractionEnabled = true
view.contentMode = .scaleAspectFill
view.clipsToBounds = true
view.layer.masksToBounds = true
view.layer.cornerRadius = 12
return view
}()
lazy var saveSizeView: UIView = {
let view = UIView()
view.layer.masksToBounds = true
view.layer.cornerRadius = 4
view.backgroundColor = UIColor(red: 0, green: 0.51, blue: 1, alpha: 1)
return view
}()
lazy var saveSizeLabel: UILabel = {
let view = UILabel()
view.textAlignment = .left
view.textColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1)
view.font = UIFont.systemFont(ofSize: 12, weight: .regular)
view.text = "Save 1.3MB"
return view
}()
lazy var moreImageView: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "icon_left_setting_grey")
view.backgroundColor = .clear
return view
}()
lazy var selectImageView: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "ic_sel_com")
view.backgroundColor = .clear
view.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer()
tap.addTarget(self, action: #selector(selectClick))
view.addGestureRecognizer(tap)
return view
}()
@objc func selectClick(){
self.choose = !self.choose
}
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(self.backImageView)
self.addSubview(self.saveSizeView)
self.saveSizeView.addSubview(self.saveSizeLabel)
self.saveSizeView.addSubview(self.moreImageView)
self.addSubview(self.selectImageView)
self.backImageView.snp.makeConstraints { make in
make.left.right.height.width.equalToSuperview()
}
self.saveSizeView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(12)
make.bottom.equalToSuperview().offset(-12)
make.height.equalTo(48)
make.width.equalTo(120)
}
self.saveSizeLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(8)
make.centerY.equalToSuperview()
make.height.equalTo(48)
make.width.equalTo(120)
}
self.moreImageView.snp.makeConstraints { make in
make.right.equalToSuperview().offset(-4)
make.centerY.equalToSuperview()
make.height.width.equalTo(16)
}
self.selectImageView.snp.makeConstraints { make in
make.bottom.right.equalToSuperview().offset(-12)
make.height.width.equalTo(24)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//
// CompressSortCell.swift
// PhoneManager
//
// Created by edy on 2025/4/3.
//
import Foundation
class CompressSortCell : UITableViewCell {
var cellTag : Int = 0
var callBack : callBack<Any> = {cellTag in}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
self.contentView.addSubview(self.selectButton)
self.selectButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(0)
make.right.equalToSuperview().offset(0)
make.top.equalToSuperview().offset(6)
make.bottom.equalToSuperview().offset(-6)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var selectButton : UIButton = {
let view = UIButton(type: UIButton.ButtonType.custom)
view.backgroundColor = UIColor(red: 0.95, green: 0.96, blue: 0.99, alpha: 1)
view.layer.cornerRadius = 12
view.clipsToBounds = true
view.setTitleColor(UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1), for: .normal)
view.addTarget(self, action: #selector(selectAction), for: .touchUpInside)
view.layer.borderColor = UIColor(red: 0, green: 0.51, blue: 1, alpha: 1).cgColor
return view
}()
@objc func selectAction(){
callBack(self.cellTag)
}
}
//
// CompressController.swift
// PhoneManager
//
// Created by edy on 2025/4/2.
//
import Foundation
import SnapKit
import Photos
class CompressController : BaseViewController {
private var compressNav:CompressNavView?
var modeData = [ResourceModel](){
didSet{
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
}
func getData(){
let source :[PHAsset] = ResourceManager.manager.getAllPhotosByPHAsset()
for asset in source{
let options = PHImageRequestOptions()
options.isSynchronous = false
options.deliveryMode = .highQualityFormat
PHImageManager.default().requestImageDataAndOrientation(for: asset, options: options) { (imageData, _, _, _) in
guard let imageData else {return}
// 这里还需要计算下可以压缩的大小
let model = ResourceModel(ident: asset.localIdentifier, saveSize: imageData.count, orgSize: imageData.count,choose: false)
self.modeData.append(model)
}
}
}
lazy var collectionView:UICollectionView = {
let layout = WaterfallMutiSectionFlowLayout()
layout.delegate = self
let sview:UICollectionView = UICollectionView.init(frame: CGRect(x: marginLR, y: self.compressNav!.height, width: self.view.width - 2 * marginLR, height: self.view.height - self.compressNav!.height - 102), collectionViewLayout: layout)
sview.register(CompressSelectCell.self, forCellWithReuseIdentifier: "CompressSelectCell")
sview.register(CompressCustomHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "CompressCustomHeaderView")
sview.register( UICollectionReusableView.self,forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter,withReuseIdentifier: "footerID")
sview.dataSource = self
sview.delegate = self
sview.showsVerticalScrollIndicator = false
if #available(iOS 11.0, *) {
sview.contentInsetAdjustmentBehavior = .never
}
sview.backgroundColor = .clear
return sview
}()
lazy var submitButton : UIButton = {
let view = UIButton()
view.backgroundColor = UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1)
view.setTitle("Compress", for: UIControl.State.normal)
view.setTitleColor(UIColor(red: 1, green: 1, blue: 1, alpha: 1), for: .normal)
view.clipsToBounds = true
view.layer.cornerRadius = 23
view.backgroundColor = UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1)
return view
}()
func setUI(){
compressNav = CompressNavView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: statusBarHeight + 44))
self.view.addSubview(compressNav!)
compressNav?.snp.makeConstraints({ make in
make.top.centerX.width.equalToSuperview()
make.height.equalTo(statusBarHeight + 44)
})
self.view.insertSubview(collectionView, at: 0)
self.view.addSubview(self.submitButton)
self.submitButton.snp.makeConstraints { make in
make.top.equalTo(self.collectionView.snp.bottom).offset(16)
make.left.equalToSuperview().offset(15)
make.right.equalToSuperview().offset(-15)
make.height.equalTo(46)
}
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
self.navigationController?.navigationBar.isHidden = true
setUI()
getData()
}
}
extension CompressController:WaterfallMutiSectionDelegate,UICollectionViewDataSource,UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.modeData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CompressSelectCell", for: indexPath) as! CompressSelectCell
cell.model = self.modeData[indexPath.row]
cell.callBack = {[weak self] (model:ResourceModel,choose:Bool) ->() in
let vc : CompressQualityController = CompressQualityController()
vc.model = model
self?.navigationController?.pushViewController(vc, animated: true)
}
return cell
}
func heightForRowAtIndexPath(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, indexPath: IndexPath, itemWidth: CGFloat) -> CGFloat {
if indexPath.row % 2 == 0{
return itemWidth
}
return itemWidth + 67
}
func columnNumber(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> Int {
return 2
}
func lineSpacing(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat {
return 8
}
func interitemSpacing(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat {
return 11
}
func spacingWithLastSection(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat {
return 8
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize {
return CGSize (width: self.collectionView.width, height: 188)
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionHeader {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "CompressCustomHeaderView", for: indexPath) as! CompressCustomHeaderView
header.modeData = self.modeData
return header
}else{
let footer = collectionView.dequeueReusableSupplementaryView(
ofKind: kind,
withReuseIdentifier: "footerID",
for: indexPath
)
return footer
}
}
}
...@@ -6,17 +6,20 @@ ...@@ -6,17 +6,20 @@
// //
import Foundation import Foundation
import Photos
struct ResourceModel { struct ResourceModel : Equatable{
var ident : String var ident : String
var saveSize : Int var compressSize : Double
var orgSize: Int var orgSize: Double
var choose : Bool var createDate : Date
var imageAsset: PHAsset
init(ident: String, saveSize: Int, orgSize: Int, choose: Bool) { init(ident: String, compressSize: Double, orgSize: Double, createDate: Date, imageAsset: PHAsset) {
self.ident = ident self.ident = ident
self.saveSize = saveSize self.compressSize = compressSize
self.orgSize = orgSize self.orgSize = orgSize
self.choose = choose self.createDate = createDate
self.imageAsset = imageAsset
} }
} }
//
// CircularProgressBar.swift
// PhoneManager
//
// Created by edy on 2025/4/3.
//
import Foundation
class CircularProgressBar: UIView {
private var progressLayer = CAShapeLayer()
private var trackLayer = CAShapeLayer()
var textLabel : UILabel = {
let view = UILabel()
view.text = "Compressing..."
view.textColor = .white
view.font = UIFont.systemFont(ofSize: 16, weight: .bold)
return view
}()
var progressColor = UIColor.blue {
didSet {
progressLayer.strokeColor = progressColor.cgColor
}
}
var trackColor = UIColor.lightGray {
didSet {
trackLayer.strokeColor = trackColor.cgColor
}
}
var lineWidth: CGFloat = 10 {
didSet {
progressLayer.lineWidth = lineWidth
trackLayer.lineWidth = lineWidth
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
private func setup() {
self.addSubview(self.textLabel)
self.textLabel.snp.makeConstraints { make in
make.width.equalTo(113 * RScreenW())
make.height.equalTo(22)
make.center.equalToSuperview()
}
// 创建轨道图层
trackLayer.fillColor = UIColor.clear.cgColor
trackLayer.strokeColor = trackColor.cgColor
trackLayer.lineWidth = lineWidth
layer.addSublayer(trackLayer)
// 创建进度图层
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.strokeColor = progressColor.cgColor
progressLayer.lineWidth = lineWidth
progressLayer.strokeEnd = 0
progressLayer.lineCap = .round
layer.addSublayer(progressLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let radius = (min(bounds.width, bounds.height) - lineWidth) / 2
let circularPath = UIBezierPath(arcCenter: center, radius: radius, startAngle: -.pi / 2, endAngle: 1.5 * .pi, clockwise: true)
trackLayer.path = circularPath.cgPath
progressLayer.path = circularPath.cgPath
}
func setProgress(_ progress: CGFloat, animated: Bool = true, duration: TimeInterval = 1.0) {
if animated {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.toValue = progress
animation.duration = duration
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
progressLayer.add(animation, forKey: "progressAnimation")
} else {
progressLayer.strokeEnd = progress
}
}
}
...@@ -9,15 +9,30 @@ import Foundation ...@@ -9,15 +9,30 @@ import Foundation
class CompressCustomHeaderView: UICollectionReusableView{ class CompressCustomHeaderView: UICollectionReusableView{
var callBack: callBack<Any> = {text in }
var modeData = [ResourceModel]() { var modeData = [ResourceModel]() {
didSet{ didSet{
// 计算图片总大小 // 计算图片总大小
var sum = 0; var sum = 0.0
// 计算可节省大小
var saveSum = 0.0
for model in self.modeData{ for model in self.modeData{
sum = sum + model.orgSize sum = sum + model.orgSize
saveSum = saveSum + (model.orgSize - model.compressSize)
}
if sum > 1000 {
self.siezLabel.text = String(format: "%.2f GB" ,(sum/1024))
}else{
self.siezLabel.text = String(format: "%.2f MB" ,(sum))
}
if saveSum > 1000 {
self.saveSizeLabel.text = String(format: "%.2f GB" ,(saveSum/1024.0))
}else {
self.saveSizeLabel.text = String(format: "%.2f MB" ,(saveSum))
} }
self.siezLabel.text = String(format: "%.2f MB" ,(Double(sum)/1024.0))
self.saveSizeLabel.text = String(format: "%.2f MB" ,(Double(sum)/1024.0))
} }
} }
...@@ -35,6 +50,14 @@ class CompressCustomHeaderView: UICollectionReusableView{ ...@@ -35,6 +50,14 @@ class CompressCustomHeaderView: UICollectionReusableView{
view.backgroundColor = UIColor(red: 0.95, green: 0.96, blue: 0.99, alpha: 1) view.backgroundColor = UIColor(red: 0.95, green: 0.96, blue: 0.99, alpha: 1)
view.layer.cornerRadius = 16 view.layer.cornerRadius = 16
view.clipsToBounds = true view.clipsToBounds = true
let tap = UITapGestureRecognizer()
tap.addTarget(self, action: #selector(selectQulity))
view.isUserInteractionEnabled = true
view.addGestureRecognizer(tap)
return view return view
}() }()
...@@ -60,8 +83,8 @@ class CompressCustomHeaderView: UICollectionReusableView{ ...@@ -60,8 +83,8 @@ class CompressCustomHeaderView: UICollectionReusableView{
return label return label
}() }()
lazy var changeView :UIView = { lazy var changeView :CompressSwitchView = {
let view = UIView() let view = CompressSwitchView()
view.backgroundColor = UIColor(red: 0.95, green: 0.96, blue: 0.99, alpha: 1) view.backgroundColor = UIColor(red: 0.95, green: 0.96, blue: 0.99, alpha: 1)
view.layer.cornerRadius = 8 view.layer.cornerRadius = 8
view.clipsToBounds = true view.clipsToBounds = true
...@@ -76,7 +99,7 @@ class CompressCustomHeaderView: UICollectionReusableView{ ...@@ -76,7 +99,7 @@ class CompressCustomHeaderView: UICollectionReusableView{
lazy var tipLabel :UILabel = { lazy var tipLabel :UILabel = {
let label = UILabel() let label = UILabel()
label.text = "Compress your media filesand save up to" label.text = "Compress your media files and save up to"
label.textAlignment = .left label.textAlignment = .left
label.numberOfLines = 0 label.numberOfLines = 0
label.textColor = UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1) label.textColor = UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1)
...@@ -164,6 +187,13 @@ class CompressCustomHeaderView: UICollectionReusableView{ ...@@ -164,6 +187,13 @@ class CompressCustomHeaderView: UICollectionReusableView{
} }
@objc func selectQulity(){
callBack("selectedQulity")
}
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
setUI() setUI()
......
//
// CompressSortView.swift
// PhoneManager
//
// Created by edy on 2025/4/3.
//
import Foundation
class CompressSortView : UIView,UITableViewDelegate,UITableViewDataSource {
var currentIndex : Int = 0
let tableData :[String] = ["Largest","Smallest","Newest","Oldest"]
var callBack : callBack<Any> = {sortType in}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : CompressSortCell = tableView.dequeueReusableCell(withIdentifier: "CompressSortCell",for: indexPath) as! CompressSortCell
cell.cellTag = indexPath.row
cell.selectButton.setTitle(tableData[indexPath.row], for: .normal)
cell.callBack = {[weak self] cellTag in
guard let self else {return}
self.currentIndex = cellTag as! Int
self.tableView.reloadData()
}
if indexPath.row == currentIndex {
cell.selectButton.layer.borderWidth = 1.0
cell.selectButton.setTitleColor(UIColor(red: 0, green: 0.51, blue: 1, alpha: 1), for: .normal)
}else{
cell.selectButton.layer.borderWidth = 0
cell.selectButton.setTitleColor(UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1), for: .normal)
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 48 * RScreenW()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(self.backView)
self.backView.addSubview(self.selectedView)
self.selectedView.addSubview(self.lineView)
self.selectedView.addSubview(self.titleLabel)
self.selectedView.addSubview(self.tableView)
self.selectedView.addSubview(self.applyButton)
self.backView.snp.makeConstraints { make in
make.top.left.right.bottom.equalToSuperview()
}
self.selectedView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.height.equalTo(416)
}
self.lineView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(16)
make.width.equalTo(57)
make.height.equalTo(4)
make.centerX.equalToSuperview()
}
self.titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.right.equalToSuperview().offset(-15)
make.top.equalTo(self.lineView.snp.bottom).offset(20)
make.height.equalTo(20)
}
self.tableView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.right.equalToSuperview().offset(-15)
make.top.equalTo(self.titleLabel.snp.bottom).offset(4)
make.height.equalTo(240)
}
self.applyButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.right.equalToSuperview().offset(-15)
make.height.equalTo(46)
make.bottom.equalToSuperview().offset(-46)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var backView : UIView = {
let view = UIView()
view.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5000)
return view
}()
lazy var selectedView : UIView = {
let view = UIView()
view.backgroundColor = .white
return view
}()
lazy var lineView : UIView = {
let view = UIView()
view.backgroundColor = UIColor(red: 0.85, green: 0.85, blue: 0.85, alpha: 1)
return view
}()
lazy var titleLabel : UILabel = {
let view = UILabel()
view.text = "Sort by"
view.textAlignment = .left
view.textColor = UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1)
view.font = UIFont.systemFont(ofSize: 14, weight: .bold)
return view
}()
lazy var tableView : UITableView = {
let view = UITableView()
view.register(CompressSortCell.classForCoder(), forCellReuseIdentifier: "CompressSortCell")
view.backgroundColor = .clear
view.separatorStyle = .none
view.showsVerticalScrollIndicator = false
view.delegate = self
view.dataSource = self
view.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
if #available(iOS 15.0, *) {
view.sectionHeaderTopPadding = 0
}
return view
}()
lazy var applyButton : UIButton = {
let view = UIButton(type: .custom)
view.setTitle("Apply", for: .normal)
view.layer.cornerRadius = 8
view.clipsToBounds = true
view.backgroundColor = UIColor(red: 0, green: 0.51, blue: 1, alpha: 1)
view.setTitleColor(.white, for: .normal)
view.addTarget(self, action: #selector(applyAction), for: .touchUpInside)
return view
}()
@objc func applyAction(){
// 传给上层控制器,对照片进行排序
callBack(currentIndex)
// 移除自身
self.removeFromSuperview()
}
}
//
// CpmpressSwitchView.swift
// PhoneManager
//
// Created by edy on 2025/4/3.
//
import Foundation
class CompressSwitchView : UIView {
var currentButton : UIButton?
lazy var leftButton : UIButton = {
let button = UIButton()
button.layer.cornerRadius = 4
button.clipsToBounds = true
button.setTitle("Photos", for: .normal)
button.addTarget(self, action: #selector(selectedButtonAction(_:)), for: .touchUpInside)
button.setTitleColor(UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1), for: .normal)
return button
}()
lazy var rightButton : UIButton = {
let button = UIButton()
button.layer.cornerRadius = 4
button.clipsToBounds = true
button.setTitle("Videos", for: .normal)
button.addTarget(self, action: #selector(selectedButtonAction(_:)), for: .touchUpInside)
button.setTitleColor(UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1), for: .normal)
return button
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = .clear
self.addSubview(self.leftButton)
self.addSubview(self.rightButton)
self.leftButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(4)
make.top.equalToSuperview().offset(4)
make.bottom.equalToSuperview().offset(-4)
make.width.equalTo(self.snp.width).multipliedBy(0.5).offset(-6)
}
self.rightButton.snp.makeConstraints { make in
make.right.equalToSuperview().offset(-4)
make.top.equalToSuperview().offset(4)
make.bottom.equalToSuperview().offset(-4)
make.left.equalTo(self.leftButton.snp.right).offset(4)
}
// 初始化的时候设置默认值
self.currentButton = self.leftButton
self.currentButton?.setTitleColor(UIColor(red: 0, green: 0.51, blue: 1, alpha: 1), for: .normal)
self.currentButton?.backgroundColor = .white
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func selectedButtonAction(_ sender : UIButton){
if sender != self.currentButton{
self.currentButton?.setTitleColor(UIColor(red: 0.7, green: 0.7, blue: 0.7, alpha: 1), for: .normal)
self.currentButton?.backgroundColor = .clear
}
sender.setTitleColor(UIColor(red: 0, green: 0.51, blue: 1, alpha: 1), for: .normal)
sender.backgroundColor = .white
self.currentButton = sender
}
}
...@@ -9,6 +9,9 @@ import Foundation ...@@ -9,6 +9,9 @@ import Foundation
class CompressingView: UIView{ class CompressingView: UIView{
var data: [ResourceModel]?
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
setUI() setUI()
...@@ -24,10 +27,12 @@ class CompressingView: UIView{ ...@@ -24,10 +27,12 @@ class CompressingView: UIView{
return view return view
}() }()
lazy var animationView:UIView = { lazy var animationView:CircularProgressBar = {
let view = UIView() let progressBar = CircularProgressBar()
view.backgroundColor = .gray progressBar.progressColor = UIColor.white
return view progressBar.trackColor = UIColor.colorWithHex(hexStr: "#2B85FF")
progressBar.lineWidth = 20
return progressBar
}() }()
lazy var tipLabel:UILabel = { lazy var tipLabel:UILabel = {
let view = UILabel() let view = UILabel()
...@@ -59,6 +64,4 @@ class CompressingView: UIView{ ...@@ -59,6 +64,4 @@ class CompressingView: UIView{
} }
} }
} }
...@@ -9,6 +9,9 @@ import Foundation ...@@ -9,6 +9,9 @@ import Foundation
class QualityView : UIView{ class QualityView : UIView{
var type : Int = 0
var callBack : callBack<Any> = {type in}
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
...@@ -65,6 +68,7 @@ class QualityView : UIView{ ...@@ -65,6 +68,7 @@ class QualityView : UIView{
let imageView = UIImageView() let imageView = UIImageView()
imageView.backgroundColor = .clear imageView.backgroundColor = .clear
imageView.image = UIImage(named: "ic_sel_com") imageView.image = UIImage(named: "ic_sel_com")
imageView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer() let tap = UITapGestureRecognizer()
tap.addTarget(self, action: #selector(selectClick)) tap.addTarget(self, action: #selector(selectClick))
imageView.addGestureRecognizer(tap) imageView.addGestureRecognizer(tap)
...@@ -72,7 +76,7 @@ class QualityView : UIView{ ...@@ -72,7 +76,7 @@ class QualityView : UIView{
}() }()
@objc func selectClick(){ @objc func selectClick(){
self.selectedImageView.image = UIImage(named: "ic_unsel_com") callBack(self.type)
} }
} }
//
// CompressViewModel.swift
// PhoneManager
//
// Created by edy on 2025/4/3.
//
import Foundation
import Photos
typealias Finished = ([ResourceModel])->Void
class CompressViewModel{
func processData(finised: @escaping() -> Void) {
// 模拟异步操作
DispatchQueue.global().async {
// 模拟耗时操作
Thread.sleep(forTimeInterval: 2)
finised()
}
}
/// 获取所有图片信息
/// - Returns: 图片信息
func getAllPhotos(_ finished : @escaping Finished){
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let photosAssets = PHAsset.fetchAssets(with: .image, options: fetchOptions)
// 获取到了所有图片的assets
let assetsArray = photosAssets.objects(at: IndexSet(0..<photosAssets.count))
// 初始化一个model数组
var models : [ResourceModel] = []
let options = PHImageRequestOptions()
options.isSynchronous = false
options.deliveryMode = .highQualityFormat
for asset in assetsArray {
PHImageManager.default().requestImageDataAndOrientation(for: asset, options: options) { (imageData, _, _, _) in
if let data = imageData {
// 图片大小
let sizeInBytes = Double(data.count)
let sizeInMB = sizeInBytes / (1024 * 1024)
// 获取图片的日期
let creationDate = asset.creationDate
// 获取图片的localIdentifier
let localIdentifier = asset.localIdentifier
// 计算压缩后的大小
PHImageManager.default().requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode:.aspectFit, options: options) { (image, _) in
if let originalImage = image {
// 项目中用到的是【0.2、0.5和0.8】,这里我们初始化的时候使用0.2去计算
if let compressedData = originalImage.jpegData(compressionQuality: 0.2) {
let compressCompletedSize = Double(compressedData.count) / (1024 * 1024)
// 构建model
let model = ResourceModel(ident: localIdentifier, compressSize: compressCompletedSize, orgSize: sizeInMB, createDate: creationDate!,imageAsset: asset)
models.append(model)
finished(models)
}
}
}
}
}
}
}
/// 对资源进行排序
/// - Parameters:
/// - resource: 原资源
/// - sortType: 排序的类型,升序或者降序。0-升序,1-降序
/// - sortKind: 排序的种类 大小或者时间 0-大小,1-时间
/// - Returns: 返回排序结果
func sortRsource(resource:[ResourceModel],sortType:Int,sortKind:Int)->[ResourceModel]{
if sortKind == 0 {
if sortType == 0 {
return resource.sorted { $0.orgSize < $1.orgSize }
}else{
return resource.sorted { $0.orgSize > $1.orgSize }
}
}else{
if sortType == 0 {
return resource.sorted { $0.createDate < $1.createDate }
}else{
return resource.sorted { $0.createDate > $1.createDate }
}
}
}
/// 压缩多张图片
/// - Parameters:
/// - assets: 图片集合
/// - compressionQuality: 图片质量
/// - progressHandler: 进度
/// - completion: 完成
func compress(assets: [ResourceModel], compressionQuality : CGFloat, progressHandler: @escaping (Float) -> Void, completion: @escaping ([Data?], [Error?]) -> Void) {
var compressedDataArray: [Data?] = Array(repeating: nil, count: assets.count)
var errorArray: [Error?] = Array(repeating: nil, count: assets.count)
var completedCount = 0
let totalCount = assets.count
for (index, model) in assets.enumerated() {
compressSingleAsset(model.imageAsset,compressionQuality) { (progress) in
let singleProgress = Float(completedCount) / Float(totalCount) + progress / Float(totalCount)
progressHandler(singleProgress)
} completion: { (compressedData, error) in
compressedDataArray[index] = compressedData
errorArray[index] = error
completedCount += 1
if completedCount == totalCount {
completion(compressedDataArray, errorArray)
}
}
}
}
private func compressSingleAsset(_ asset: PHAsset,_ compressionQuality : CGFloat, progress: @escaping (Float) -> Void, completion: @escaping (Data?, Error?) -> Void) {
let options = PHImageRequestOptions()
options.isSynchronous = false
options.deliveryMode = .highQualityFormat
PHImageManager.default().requestImageDataAndOrientation(for: asset, options: options) { (imageData, _, _, error) in
if let error = error {
completion(nil, error as? Error)
return
}
guard let originalData = imageData else {
completion(nil, nil)
return
}
let totalSize = originalData.count
var processedSize = 0
self.compressData(originalData, compressionQuality: compressionQuality) { (progressValue) in
processedSize = Int(Float(totalSize) * progressValue)
let currentProgress = Float(processedSize) / Float(totalSize)
progress(currentProgress)
} completion: { (compressedData, error) in
completion(compressedData, error)
}
}
}
private func compressData(_ data: Data, compressionQuality: CGFloat, progress: @escaping (Float) -> Void, completion: @escaping (Data?, Error?) -> Void) {
guard let originalImage = UIImage(data: data) else {
completion(nil, nil)
return
}
DispatchQueue.global().async {
var progressValue: Float = 0
let step = 0.1
while progressValue < 1 {
progress(progressValue)
progressValue += Float(step)
Thread.sleep(forTimeInterval: 0.1)
}
if let compressedData = originalImage.jpegData(compressionQuality: compressionQuality) {
DispatchQueue.main.async {
progress(1.0)
completion(compressedData, nil)
}
} else {
DispatchQueue.main.async {
completion(nil, nil)
}
}
}
}
}
...@@ -50,4 +50,13 @@ class ResourceManager { ...@@ -50,4 +50,13 @@ class ResourceManager {
} }
return array return array
} }
func getAllVideosByPHAsset()-> [PHAsset]{
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let videoAssets = PHAsset.fetchAssets(with: .video, options: fetchOptions)
let assetsArray = videoAssets.objects(at: IndexSet(0..<videoAssets.count))
return assetsArray
}
} }
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