主頁 > 移動端開發 > iOS開發tips-PhotoKit

iOS開發tips-PhotoKit

2020-09-11 20:56:33 移動端開發

概述

PhotoKit應該是iOS 8 開始引入為了替代之前ALAssetsLibrary的相冊資源訪問的標準庫,后者在iOS 9開始被棄用,當然相對于ALAssetsLibrary其擴展性更高,api使用起來也更加的強大,但這并非今天討論的重點,這里主要討論PhotoKit使用的一些技巧和容易踩的坑,

PHImageManager or Custom

訪問相冊資源常用的操作還是獲取資源,比如獲取一張相冊的圖片,可以通過PHImageManager.default().requestImage(xxx)一個回呼就可以了,其實除了簡單的圖片拉取蘋果建議大家使用一個自己維護的PHCachingImageManager(PHImageManager子類)單例,因為從名字可以看出它可以進行資源快取(具體用法參見:PHCachingImageManager),這個在串列滑動程序中比較有用,因為可以使用startCachingImages(for:targetSize:contentMode:options:)預加載還未顯示的資源,在不需要使用的時候呼叫stopCachingImages(for:targetSize:contentMode:options:)移除快取,除此之外其實它更多的是使用父類的功能,

關于requestImage(for:targetSize:contentMode:options:resultHandler:)方法其實它的options是更容易讓大家使用的時候經常迷糊的地方,因為iOS相冊的照片很可能并不在本地而是在iCloud上面存盤,本地只有縮略圖:

  • isNetworkAccessAllowed:是不是打開網路加載,對于iCloud優化的圖片本地只有縮略圖,需要了開啟網路加載,默認是false,但是建議非特殊情況下不要關閉網路加載設為true
  • isSynchronous:獲取圖片時是否同步獲取,否則異步獲取,非特殊情況下不建議使用同步獲取會阻塞執行緒,默認為false
  • version:使用資源的版本,例如說一個視頻獲取程序中是要獲取編輯過的還是獲取原始視頻(因為iOS的相冊編輯時可以恢復的,所以其實里面包含了編輯資訊),默認current對于未編輯的則獲取原始資源,編輯過則獲取編輯過的資源,
  • deliveryMode:字面意思資源交付模式,就是當發起一個請求后系統如何提供請求的資源(不過很可能這個資源并不在本地),默認是opportunistic同步呼叫只回傳一種資源異步呼叫回傳多種資源(例如不同尺寸的圖片,這也就是說和上面的isSynchronous相關);highQualityFormat任何情況下只回傳高質量的一種資源;fastFormat任何情況下只回傳一種結果,它可能是低清圖片(是不是低清晰度可以通過resultHandler結果中的info欄位PHImageResultIsDegradedKey來判斷是不是低清晰度),
  • resizeMode:重設尺寸模式,這個其實關系到方法中targetSize引數,默認是fast代表當本地是原圖則回傳原圖,本地是縮略圖則使用targetSize來獲取一個最優圖片,但是尺寸可能比targetSize要略大(注意如果targetSize是PHImageManagerMaximumSize則會拉取原圖此屬性此時沒有意義直接忽略);none則回傳原圖大小;exactfast但是回傳的高清圖,但是在異步情況下因為可能存在兩種圖片會稍有不同,下面分兩種情況介紹,

isSynchronousdeliveryModeresizeMode之間的關系(前提是開啟網路加載isNetworkAccessAllowed = true):

isSynchronous = true同步加載:此時deliveryMode會被忽略掉,所以只要看resizeMode

  • none:回傳原圖尺寸
  • fast:原圖為縮略圖時使用targetSize優化,回傳一個可能比targetSize稍大的圖片
  • exact:回傳指定targetSize的高清圖片

isSynchronous = false異步加載:此時要看deliveryMode和resizeMode兩者的變化情況

  • deliveryMode = opportunistic

    • none:先回傳低清圖片,再回傳原圖
    • fast:先回傳低清圖片,再回傳使用targetSize優化,可能比targetSize稍大的圖片
    • exact:先回傳低清圖片,再回傳指定targetSize的高清圖片
  • deliveryMode = highQualityFormat

    • none:回傳原圖
    • fast:回傳使用targetSize優化,可能比targetSize稍大的圖片
    • exact:回傳指定targetSize的高清圖片
  • deliveryMode = fastFormat

    • none:回傳低清圖片
    • fast:回傳低清圖片
    • exact:回傳低清圖片

對于是否回傳兩次結果總結起來對于回傳結果只有異步請求在不設定deliveryMode或者deliveryMode = opportunistic 時會發送兩次請求,

沒錯上面的情況如果了解不清楚很容易掉進坑里,一般的情況下只要打開網路,使用默認值即可,但是話說沒有網路的情況下是什么情況呢?

無網路情況

上面說了那么多配置那么對于沒有網路的情況呢?因為PHImageRequestOptions默認其實就是沒有網路的,先看一下下面的請求:

let requestOption = PHImageRequestOptions()
requestOption.resizeMode = .exact
let scale:CGFloat = UIScreen.main.scale
let newSize = CGSize(width: 200.0, height: 200)
PHImageManager.default().requestImage(for: asset, targetSize: newSize, contentMode: .aspectFill, options: requestOption,resultHandler: completeHandler)

首先沒有設定isNetworkAccessAllowed屬性,那么默認值就是false,這個時候也就是沒有任何網路請求,其次resizeMode = .exact也就是請求比較高清的圖片,但是一個重要的問題是這個圖片可能會是一個低清圖片,甚至達不到一個200200的縮略圖的預期,有可能特別模糊,
按照前面說的,deliveryMode 沒有設定默認是
opportunisticisSynchronous*沒有設定默認是false,在異步情況下是 首先這種情況下也會回傳兩個結果,列印info資訊:
第一次:
[AnyHashable("PHImageResultIsDegradedKey"): 1, AnyHashable("PHImageResultRequestIDKey"): 1100]
第二次:
[AnyHashable("PHImageResultIsDegradedKey"): 0, AnyHashable("PHImageErrorKey"): Error Domain=NSCocoaErrorDomain Code=-1 "(null)", AnyHashable("PHImageResultIsInCloudKey"): 1, AnyHashable("PHImageResultRequestIDKey"): 1100]

可以看出第一次是低清圖片,第二次是高清,但是此時出錯了PHImageResultIsInCloudKey = 1,本地并沒有高清圖,但是因為無法訪問網路去獲取就報錯了,拋出PHImageErrorKey資訊,同時此時回傳的image = nil,這樣的結果就是只能看到低清圖片,因此是否回傳清晰照片除了上面說的,還和是否允許網路請求有直接關系,

綜上來看除非特殊情況下,請打開網路請求使用異步請求,并且在合適的時機判斷是否請求回傳兩次,

視頻獲取

對于視瞥澩的獲取和圖片還有些不同,因為使用PhotoKit上傳視頻的程序并不是直接獲取到視頻路徑來做的,當然如果不熟悉這個程序很可能使用下面的方式:

let option = PHVideoRequestOptions()
option.isNetworkAccessAllowed = true
option.version = .current
option.deliveryMode = .highQualityFormat
PHImageManager.default().requestAVAsset(forVideo: phAsset, options: option) { (avAsset, _, _) in
    if let avAsset = avAsset as? AVURLAsset {
        let fileURL = avAsset.url
        // upload by fileURL
    }
}

這套代碼遇到的問題很可能是iOS 10之前的系統上傳失敗,之后的基本還是可以傳成功的,主要是因為這個url路徑在低版本系統訪問受限,

正確的姿勢應該是先把視頻匯出到沙盒然后從本地上傳,那么如何copy到本地呢?答案是使用PHAssetResourceManager,這個類出現的比較晚在iOS 9才引入的,就是為了方便資源管理,可以通過他將本地相冊的資源寫入沙盒然后上傳沙盒的資源,

let resources = PHAssetResource.assetResources(for: phAsset)
let options = PHAssetResourceRequestOptions()
options.isNetworkAccessAllowed = true
PHAssetResourceManager.default().writeData(for: assetResource, toFile: videoURL, options: options, completionHandler: { (error) in
    // upload by videoURL
    
})

但是這并非就萬事大吉了,接下來的一個bug就是,通過這種方式如果上傳用戶已經編輯過的資源會發現它上傳的是編輯之前的(比如說用戶將60s的視頻通過系統相冊剪輯到50s,它上傳的還是60s的),因為它相比較于PHImageManager請求可以設定PHVideoRequestOptions.version它缺少了這個資訊,查找api也沒有發現可以用的設定,所以這種方式還是不可取(如果有朋友知道怎么使用這種方式獲取不同的version可以留言告訴我),所以這時可以采用PHImageManager的另一個方法requestExportSession(xxx)將視頻匯出到沙盒然后上傳,但是這么做的另一個小問題就是如果想要匯出原始視頻就不太可能了,只能盡可能拿到一個更高清晰度的視頻,

let videoOption = PHVideoRequestOptions()
videoOption.version = PHVideoRequestOptionsVersion.current
videoOption.isNetworkAccessAllowed = true
PHImageManager.default().requestExportSession(forVideo: phAsset, options: videoOption, exportPreset: AVAssetExportPresetHighestQuality) { (exportSession, info) in
    if let exportSession = exportSession {
        exportSession.outputURL = videoURL
        exportSession.outputFileType = AVFileType.mp4
        exportSession.exportAsynchronously {
        if exportSession.status == AVAssetExportSession.Status.completed {
            // upload by videoURL
        }
    }
}

話說到了這里是不是就真的沒事了?試著用下面的視頻上傳試試:
TestVideo.zip
exportSession.status應該會失敗,當然如果你是iOS 13應該是可以的,但是如果是iOS 13以下在當前環境測驗都是通不過的,這個視頻查看meta資訊也沒有什么特殊的,但是這個是Android匯出的一個視頻,失敗資訊是:無法完成此操作,除此之外并沒有有用的資訊,初步猜測匯出時應該是編解碼出錯了,

其實到了這里,用上面的方式應該就無法解決這個問題了,至少目前沒有找到有效的辦法,兜底策略就是失敗后采用上面的第二種方式,

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/7487.html

標籤:iOS

上一篇:PromiseKit基本使用及原始碼決議

下一篇:iOS界面流暢技巧之微博 Demo 性能優化技巧

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more