-
Part 1
绘制当前 Screenshot
UIGraphicsBeginImageContextWithOptions(currentView.bounds.size, false, UIScreen.main.scale)
currentView.drawHierarchy(in: currentView.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
-
Part 2
系统相册权限逻辑处理
Step 1
查询当前的授权状态
Step 2
处理当前的授权状态:
1.已授权 --> 直接写入相册未决定
2.请求权限 --> 如果成功直接写入相册
3.已拒绝 --> Open系统设置
private func saveImageToPhotoLibrary(image: UIImage?) {
guard let img = image else {
return
}
// 判断权限
switch PHPhotoLibrary.authorizationStatus() {
case .authorized:
saveImage(image: img)
case .notDetermined:
PHPhotoLibrary.requestAuthorization { [weak self](status) in
if status == .authorized {
self?.saveImage(image: img)
} else {
print("User denied")
}
}
case .restricted, .denied:
if let url = URL.init(string: UIApplication.openSettingsURLString) {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.openURL(url)
}
}
}
}
private func saveImage(image: UIImage) {
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAsset(from: image)
}, completionHandler: { [weak self](isSuccess, error) in
DispatchQueue.main.async {
if isSuccess {// 成功
print("Success")
}
}
})
}
-
Part 3
特殊情况处理,当用户在系统设置中把相册的权限由未授权变更为授权时,APP会自动重启,如果有需要可以在崩溃前把图片缓存到本地,启动时再做处理。
-
Part 4
附上压缩图片到指定大小的分类方法(网上找的,能用就行。。。)
import UIKit
public extension UIImage {
/// 压缩图片的大小,并且返回压缩后的Data
class func resetSizeOfImageData(sourceImage: UIImage, maxSize: Int) -> Data? {
if let finallImageData = sourceImage.jpegData(compressionQuality: 1.0) {
return resetSizeOfImageData(sourceData: finallImageData, maxSize: maxSize)
}
return nil
}
class func resetSizeOfImageData(sourceData: Data, maxSize: Int) -> Data? {
//先判断当前质量是否满足要求,不满足再进行压缩
guard let sourceImage = UIImage(data: sourceData) else {
return nil
}
var finallImageData = sourceData
let sizeOrigin = finallImageData.count
let sizeOriginKB = sizeOrigin / 1024
if sizeOriginKB <= maxSize {
return finallImageData
}
//获取原图片宽高比
let sourceImageAspectRatio = sourceImage.size.width/sourceImage.size.height
//先调整分辨率
var defaultSize = CGSize(width: 1024, height: 1024/sourceImageAspectRatio)
guard let newImage = self.newSizeImage(size: defaultSize, sourceImage: sourceImage) else {
return nil
}
guard let newImageData = newImage.jpegData(compressionQuality: 1.0) else {
return nil
}
finallImageData = newImageData
//保存压缩系数
var compressionQualityArr: [CGFloat] = []
let avg = CGFloat(1.0/250)
var value = avg
var i = 250
repeat {
i -= 1
value = CGFloat(i)*avg
compressionQualityArr.append(value)
} while i >= 1
/*
调整大小
说明:压缩系数数组compressionQualityArr是从大到小存储。
*/
//思路:使用二分法搜索
guard let halfData = self.halfFuntion(arr: compressionQualityArr, image: newImage, sourceData: finallImageData, maxSize: maxSize) else {
return nil
}
finallImageData = halfData
//如果还是未能压缩到指定大小,则进行降分辨率
while finallImageData.count == 0 {
//每次降100分辨率
let reduceWidth = 100.0
let reduceHeight = 100.0/sourceImageAspectRatio
if (defaultSize.width-CGFloat(reduceWidth)) <= 0 || (defaultSize.height-CGFloat(reduceHeight)) <= 0 {
break
}
defaultSize = CGSize(width: (defaultSize.width-CGFloat(reduceWidth)), height: (defaultSize.height-CGFloat(reduceHeight)))
guard let lastCompressionData = newImage.jpegData(compressionQuality: compressionQualityArr.last ?? 1) else {
return nil
}
guard let lastCompressionImage = UIImage.init(data: lastCompressionData) else {
return nil
}
guard let image = self.newSizeImage(size: defaultSize, sourceImage: lastCompressionImage) else {
return nil
}
guard let sourceData = image.jpegData(compressionQuality: 1.0),
let halfData = halfFuntion(arr: compressionQualityArr, image: image, sourceData: sourceData, maxSize: maxSize) else {
return nil
}
finallImageData = halfData
}
return finallImageData
}
// MARK: - 调整图片分辨率/尺寸(等比例缩放)
class func newSizeImage(size: CGSize, sourceImage: UIImage) -> UIImage? {
var newSize = CGSize(width: sourceImage.size.width, height: sourceImage.size.height)
let tempHeight = newSize.height / size.height
let tempWidth = newSize.width / size.width
if tempWidth > 1.0 && tempWidth > tempHeight {
newSize = CGSize(width: sourceImage.size.width / tempWidth, height: sourceImage.size.height / tempWidth)
} else if tempHeight > 1.0 && tempWidth < tempHeight {
newSize = CGSize(width: sourceImage.size.width / tempHeight, height: sourceImage.size.height / tempHeight)
}
UIGraphicsBeginImageContext(newSize)
sourceImage.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
// MARK: - 二分法
class func halfFuntion(arr: [CGFloat], image: UIImage, sourceData finallImageData: Data, maxSize: Int) -> Data? {
var tempFinallImageData = finallImageData
var tempData = Data.init()
var start = 0
var end = arr.count - 1
var index = 0
var difference = Int.max
while start <= end {
index = start + (end - start)/2
guard let imageJpegData = image.jpegData(compressionQuality: arr[index]) else {
return nil
}
tempFinallImageData = imageJpegData
let sizeOrigin = tempFinallImageData.count
let sizeOriginKB = sizeOrigin / 1024
print("当前降到的质量:\(sizeOriginKB)\n\(index)----\(arr[index])")
if sizeOriginKB > maxSize {
start = index + 1
} else if sizeOriginKB < maxSize {
if maxSize-sizeOriginKB < difference {
difference = maxSize-sizeOriginKB
tempData = tempFinallImageData
}
if index<=0 {
break
}
end = index - 1
} else {
break
}
}
return tempData
}
}