-
Part 1
繪制當(dāng)前 Screenshot
UIGraphicsBeginImageContextWithOptions(currentView.bounds.size, false, UIScreen.main.scale)
currentView.drawHierarchy(in: currentView.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
-
Part 2
系統(tǒng)相冊(cè)權(quán)限邏輯處理
Step 1
查詢當(dāng)前的授權(quán)狀態(tài)
Step 2
處理當(dāng)前的授權(quán)狀態(tài):
1.已授權(quán) --> 直接寫(xiě)入相冊(cè)未決定
2.請(qǐng)求權(quán)限 --> 如果成功直接寫(xiě)入相冊(cè)
3.已拒絕 --> Open系統(tǒng)設(shè)置
private func saveImageToPhotoLibrary(image: UIImage?) {
guard let img = image else {
return
}
// 判斷權(quán)限
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
特殊情況處理缤剧,當(dāng)用戶在系統(tǒng)設(shè)置中把相冊(cè)的權(quán)限由未授權(quán)變更為授權(quán)時(shí)客叉,APP會(huì)自動(dòng)重啟乃戈,如果有需要可以在崩潰前把圖片緩存到本地,啟動(dòng)時(shí)再做處理直晨。
-
Part 4
附上壓縮圖片到指定大小的分類(lèi)方法(網(wǎng)上找的万哪,能用就行。抡秆。。)
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? {
//先判斷當(dāng)前質(zhì)量是否滿足要求儒士,不滿足再進(jìn)行壓縮
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
//先調(diào)整分辨率
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
//保存壓縮系數(shù)
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
/*
調(diào)整大小
說(shuō)明:壓縮系數(shù)數(shù)組compressionQualityArr是從大到小存儲(chǔ)。
*/
//思路:使用二分法搜索
guard let halfData = self.halfFuntion(arr: compressionQualityArr, image: newImage, sourceData: finallImageData, maxSize: maxSize) else {
return nil
}
finallImageData = halfData
//如果還是未能壓縮到指定大小檩坚,則進(jìn)行降分辨率
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: - 調(diào)整圖片分辨率/尺寸(等比例縮放)
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("當(dāng)前降到的質(zhì)量:\(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
}
}