Swift 屏幕截屏觉义、圖片保存到相冊(cè) 功能詳解

  • 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
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末着撩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子匾委,更是在濱河造成了極大的恐慌拖叙,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赂乐,死亡現(xiàn)場(chǎng)離奇詭異薯鳍,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)挨措,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)挖滤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人浅役,你說(shuō)我怎么就攤上這事斩松。” “怎么了觉既?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵惧盹,是天一觀的道長(zhǎng)乳幸。 經(jīng)常有香客問(wèn)我,道長(zhǎng)钧椰,這世上最難降的妖魔是什么粹断? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮演侯,結(jié)果婚禮上姿染,老公的妹妹穿的比我還像新娘。我一直安慰自己秒际,他們只是感情好悬赏,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著娄徊,像睡著了一般闽颇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上寄锐,一...
    開(kāi)封第一講書(shū)人閱讀 52,696評(píng)論 1 312
  • 那天兵多,我揣著相機(jī)與錄音,去河邊找鬼橄仆。 笑死剩膘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的盆顾。 我是一名探鬼主播怠褐,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼您宪!你這毒婦竟也來(lái)了奈懒?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宪巨,失蹤者是張志新(化名)和其女友劉穎磷杏,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體捏卓,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡极祸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了怠晴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贿肩。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖龄寞,靈堂內(nèi)的尸體忽然破棺而出汰规,到底是詐尸還是另有隱情,我是刑警寧澤物邑,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布溜哮,位于F島的核電站滔金,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏茂嗓。R本人自食惡果不足惜餐茵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望述吸。 院中可真熱鬧忿族,春花似錦、人聲如沸蝌矛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)入撒。三九已至隆豹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茅逮,已是汗流浹背璃赡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留献雅,地道東北人碉考。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像挺身,于是被迫代替她去往敵國(guó)和親豆励。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容