iOS實(shí)現(xiàn)微信/QQ顯示最近拍攝圖片的功能實(shí)例代碼
如果你剛剛拍攝了圖片,在使用微信/QQ發(fā)生消息時(shí)會(huì)顯示“你可能要發(fā)送的圖片”,
實(shí)現(xiàn)原理:
1、打開(kāi)或重新進(jìn)入聊天窗口時(shí)查詢(xún)圖庫(kù)最新的照片, 對(duì)比拍照時(shí)間和當(dāng)前時(shí)間的差,當(dāng)?shù)陀陂撝担ɡ缫环昼姡r(shí)就顯示出來(lái)。 PS:閾值是邏輯上判斷是否最近的依據(jù)。優(yōu)點(diǎn):總能找到最近拍攝的圖片; 缺點(diǎn):每次都要查詢(xún)圖片數(shù)據(jù),響應(yīng)較慢。
2、注冊(cè)圖庫(kù)變化監(jiān)聽(tīng)(觀察者模式), 響應(yīng)圖庫(kù)的增刪改事件, 拿到變化圖片數(shù)據(jù)后做對(duì)應(yīng)的邏輯。 優(yōu)點(diǎn): 實(shí)時(shí)響應(yīng); 缺點(diǎn):影響性能, 在注冊(cè)監(jiān)聽(tīng)前拿不到變化數(shù)據(jù)。
實(shí)現(xiàn)方式:
1、在info.plist文件中添加訪問(wèn)相機(jī)數(shù)據(jù)的權(quán)限。
2、在啟動(dòng)應(yīng)用后要獲取相機(jī)權(quán)限, 調(diào)用PHPhotoLibrary.requestAuthoriztion方法,提示內(nèi)容是plist對(duì)應(yīng)相機(jī)權(quán)限字段內(nèi)容(PS:跟Android的動(dòng)態(tài)權(quán)限獲取是一個(gè)套路)。
3、獲取相機(jī)權(quán)限后,要緩存所有PHAsset類(lèi)型的照片記錄(不包含圖片二進(jìn)制數(shù)據(jù),所有不用擔(dān)心內(nèi)存溢出); 緩存所有圖片記錄是為了后續(xù)比較變化使用, 邏輯上是變化前數(shù)據(jù)。
4、觀察者模式的register, 注意在適當(dāng)?shù)牡胤揭獔?zhí)行unregisterChangeObserver。
5、在回調(diào)函數(shù)photoLibraryDidChange里做圖庫(kù)變化后的邏輯, 這里的PHChange類(lèi)可以跟前面緩存的變化前數(shù)據(jù)比較并得到變化的部分(包括新增、刪除、修改,厲害了; Android沒(méi)有這么方便的API。。。)。
6、使用DispatchQueue.main.async是主線程異步執(zhí)行, 作用同Android主線程Handler的sendMessage。這是觀察者模式的標(biāo)準(zhǔn)做法,避免阻塞通知隊(duì)列。
7、使用PHCachingImageManager取出PHAsset的圖片數(shù)據(jù)ImageView對(duì)象。
8、顯示到UI里。
參考代碼:
import UIKit import Photos //使用圖庫(kù)功能時(shí)必須引用這個(gè)包 //顯示最近拍攝的照片為縮略圖 class ViewController: UIViewController, PHPhotoLibraryChangeObserver { var assetsFetchResults:PHFetchResult<PHAsset>! var imageManager: PHCachingImageManager! //帶緩存的圖片管理對(duì)象 var imageView: UIImageView! //用于顯示縮略圖 var assetGridThumbnailSize: CGSize! //縮略圖大小 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. imageView = UIImageView() imageView.frame = CGRect(x: 50, y: 50, width: 100, height: 100) imageView.contentMode = .scaleAspectFit imageView.clipsToBounds = true self.view.addSubview(imageView) self.imageManager = PHCachingImageManager() //初始化和充值緩存 let scale = UIScreen.main.scale //像素比 assetGridThumbnailSize = CGSize(width: imageView.frame.width*scale, height: imageView.frame.height*scale) //申請(qǐng)權(quán)限 PHPhotoLibrary.requestAuthorization({ (status) in if status != .authorized { return } //獲取所有圖片資源(按照創(chuàng)建時(shí)間排序) let allPhotoOptions = PHFetchOptions() allPhotoOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)] //排序方式 allPhotoOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue) //類(lèi)型 self.assetsFetchResults = PHAsset.fetchAssets(with: .image, options: allPhotoOptions) //查詢(xún)照片類(lèi)型 var i = 0 while i<self.assetsFetchResults.count { let asset = self.assetsFetchResults[i] print(" 創(chuàng)建時(shí)間:\(asset.creationDate?.description)") //打印所有圖片的創(chuàng)建時(shí)間 i += 1 } if (self.assetsFetchResults.count > 0) { //顯示最近一張拍攝的圖片(也可以根據(jù)拍攝時(shí)間遠(yuǎn)近決定是否要顯示) self.imageManager.requestImage(for: self.assetsFetchResults[0], //最近一張圖片 targetSize: self.assetGridThumbnailSize, contentMode: .aspectFill, options: nil, resultHandler: { (image, info) in self.imageView.image = image //取出圖像并顯示出來(lái) }) } print("圖片數(shù)量:\(self.assetsFetchResults?.count)") //注冊(cè)監(jiān)聽(tīng)資源變化 PHPhotoLibrary.shared().register(self) //刪除是unregisterChangeObserver }) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func photoLibraryDidChange(_ changeInstance: PHChange) { guard let changes = changeInstance.changeDetails(for: self.assetsFetchResults as! PHFetchResult<PHObject>) else { return } //異步執(zhí)行,避免阻塞圖片變化事件隊(duì)列 DispatchQueue.main.async { if let result = changes.fetchResultAfterChanges as? PHFetchResult<PHAsset> { self.assetsFetchResults = result //差異結(jié)果 } //判斷是否有新增圖片或刪除圖片的情況 if !changes.hasIncrementalChanges || changes.hasMoves { return } else { print("圖片數(shù)據(jù)有變化") if let indexs = changes.changedIndexes, indexs.count>0 { //不顯示0的情況 print("有\(zhòng)(indexs.count)張圖片發(fā)生變化") } if let removes = changes.removedIndexes, removes.count>0 { print("刪除了\(removes.count)張圖片") } if let inserts = changes.insertedIndexes, inserts.count>0 { //有新增圖片 print("新增了\(inserts.count)張圖片") let picture = self.assetsFetchResults[inserts.first!] self.imageManager.requestImage(for: picture, targetSize: self.assetGridThumbnailSize, contentMode: .aspectFill, options: nil, resultHandler: { (image, option) in self.imageView.image = image //取出圖像并顯示出來(lái) }) } } } } }
以上所述是小編給大家介紹的iOS實(shí)現(xiàn)微信/QQ顯示最近拍攝圖片的功能實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
詳解iOS平臺(tái)調(diào)用后臺(tái)接口的正確姿勢(shì)
這篇文章主要介紹了詳解iOS平臺(tái)調(diào)用后臺(tái)接口的正確姿勢(shì),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10詳解iOS中Button按鈕的狀態(tài)和點(diǎn)擊事件
這篇文章先是給大家介紹iOS中Button按鈕的狀態(tài),而后又詳細(xì)介紹了iOS中按鈕點(diǎn)擊事件處理方式,本文介紹的很詳細(xì),有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。2016-09-09深入解析iOS應(yīng)用開(kāi)發(fā)中對(duì)設(shè)計(jì)模式中的橋接模式的使用
這篇文章主要介紹了iOS應(yīng)用開(kāi)發(fā)中對(duì)設(shè)計(jì)模式中的橋接模式的使用,bridge橋接模式中主張把抽象部分與實(shí)現(xiàn)部分分離,需要的朋友可以參考下2016-03-03Swift 開(kāi)發(fā)之懶加載的實(shí)例詳解
這篇文章主要介紹了Swift 開(kāi)發(fā)之懶加載的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文能幫助到大家,實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-09-09針對(duì)iOS開(kāi)發(fā)的一些Xcode使用技巧小結(jié)
這篇文章主要介紹了針對(duì)iOS開(kāi)發(fā)的一些Xcode使用技巧小結(jié),Xcode是Mac上編寫(xiě)iOS應(yīng)用的開(kāi)發(fā)環(huán)境,需要的朋友可以參考下2015-12-12