仿照微信的效果,實現了一個支援多選、選原圖和視訊的圖片選擇器,支援iOS6+,3行程式碼即可整合

譚真發表於2018-07-20

重要提示

  1. 1.9.0版本已釋出,移除了”prefs:root=”的呼叫,這個API已經被列為私有API,請大家儘快升級。其它同樣使用了該API的庫大家可以檢查下,比如著名的SVProgressHUD
  2. 如果你發現了Bug,請先嚐試更新到最新版,此前的版本可能存在一些bug。如果你已經是最新版了,請在github上提一個issue,我看到了會盡快處理哈~

前段時間空餘時間比較多,打算嘗試做一個圖片選擇器出來,仔細對比了很多自定義了圖片選擇器的應用,感覺最喜歡微信的介面效果,當然微博的功能更強大,還支援了LivePhoto,所以打算模仿微信的介面效果,瞄著微博的功能去做一個圖片選擇器出來。

一.  TZImagePickerController簡介

這個圖片選擇器還沒達到我理想中的效果,但是最近工作開始忙起來了,所以有一些功能放在以後加入吧。目前這個圖片選擇器:

  1. 支援圖片多選、選原圖和視訊;
  1. 支援預覽圖片和視訊;
  2. 支援iOS6+;

總體上跟微信的照片選擇器介面和功能都差不多一樣,當然我這個弱不少…效果圖如下:

  1. TZPhotoPickerController, 照片選擇控制器

2.TZPhotoPreviewController. 照片預覽控制器

3.TZVideoPlayerControlle. 視訊預覽控制器

對照片選擇器要求不是很高的應用來說,這個圖片選擇器還算是夠用了,這段時間考察了github上若干個支援多選的圖片選擇器,介面效果和功能都比這個差些,可能是有更好的我沒發現吧…

二.  如何整合

該圖片選擇器支援CocoaPods, 在你的Podfile檔案中加入`pod `TZImagePickerController` 即可整合。

如果你喜歡手動匯入,到github下載程式碼後,將TZImagePickerController資料夾拖入到你的專案中,再#import "TZImagePickerController.h"即可。

整合這個圖片選擇器,最少只需要三行程式碼,用起來還是很方便,可以節省開發者的時間,把更多的時間和精力花在業務邏輯和自己想鑽研的技術點上去。

TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:9 delegate:self];

// You can get the photos by block, the same as by delegate.
// 你可以通過block或者代理,來得到使用者選擇的照片.
[imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {

}];
[self presentViewController:imagePickerVc animated:YES completion:nil];

程式碼截圖如下:

三. 相關類的介紹

1.TZImageManager:唯一import了和的類,向外界提供有獲取相簿/照片/視訊資源的介面,在裡面每個方法內部會判斷系統版本,從而選擇是從AssetsLibrary庫「iOS9以前可用」還是從Photos庫裡獲取照片資源「iOS8以後可用」。
2.TZImagePickerController:導航欄控制器,通過改變該控制器的一些屬性來達到你想要的效果,比如設定maxImagesCount屬性來約束使用者最大可選圖片張數,預設為9張;設定allowPickingOriginalPhoto屬性為NO不允許使用者選擇視訊,預設是YES;設定allowPickingVideo屬性為NO不允許使用者選擇原圖,預設是YES。
3.TZPhotoPickerController:照片選擇控制器,一個collectionView每行4個cell展示圖片。
4.TZPhotoPreviewController:照片預覽控制器,用的是collectionView而不是scrollView,所以不用處理重用邏輯,然而圖片的間隙我還沒弄出來…以後再弄吧…(已出…)
5.TZVideoPlayerController:視訊預覽控制器,簡單的播放/暫停/傳送視訊功能,用的是AVPlayer來播放。進度條下次有空再加上吧…
6.TZAssetModel:裝有一個圖片/視訊/音訊資源的模型,對應一個圖片/視訊Cell「TZAssetCell」,資源屬性名為asset,可以從TZImageManager取出資源物件「圖片/視訊/音訊」。
7.TZAlbumModel:裝有一個相簿資源的模型,對應一個相簿Cell「TZAlbumCell」,資源屬性名為result,可以從TZImageManager取出所含有的圖片資源陣列。

四. 微信圖片選擇器的一些技術點

優點實在太多了,說兩個我發現的小缺點吧。

小缺點1:在相簿列表頁,空的cell也會顯示,出現許多空的分割線。「也可能是微信的產品或iOS喜歡這個調調…」

  • 我的解決方案:加上這一句_tableView.tableFooterView = [[UIView alloc] init];會不再顯示空的cell。當然也可以隱藏系統的分割線,自己加一個高0.5~1畫素的View作為分割線。

小缺點2:在照片選擇器頁,微信的設計是不允許同時選擇視訊和照片的,但是在照片預覽頁面,使用者卻可以同時選中視訊和照片,此時微信會預設將視訊作為圖片傳送,而沒有做一個提示。並且,如果使用者選擇了傳送原圖,此時視訊雖然也被選中出來了,但是會一直髮送失敗。

  • 我的解決方案:在照片預覽頁面,如果使用者在選擇了圖片的情況下又選擇了視訊,提示使用者會預設將視訊做圖片傳送。並且在圖片瀏覽器頁面,如果預覽到了一個視訊,則將原圖按鈕隱藏,在計算原圖大小的方法裡也會過濾掉視訊資源。

當然微信的圖片選擇器是很優秀的,比如我今天在用iOS6系統的4s真機測試時,發現第一次彈出圖片選擇器時,如果相機膠捲相簿圖片數大於1000,我的這個會有比較明顯的卡頓,而微信的卻依然流暢…考慮到這個罕見的iOS6系統4s機子不是我的、工作要開始忙了、畢竟這只是4s等原因,這個優化就等下次有空再來研究吧…(1.4.2版本更新:這裡已優化,是AssetsLibrary的一個坑…)

五. 更新記錄

1.4.5版本(2016.05.23)
在照片列表頁新增了拍照按鈕,可以全域性記錄哪個相簿已選中了多少張圖片,預覽控制器可以在外界開啟。同時Demo頁面也做了一些優化,可以直接刪除選中的照片、可以對照片進行長按排序等。當然期間也修復了許多小bug,表現更加好了。
最值得一提的是,1.4.5版本的效能大幅提升了,在我的iOS9.3.2系統6s裝置上(870張照片),平均滑動幀數在58左右,滑動十分流暢,在iOS7.0.4的4s裝置上(124張照片),平均滑動幀數在57左右,也十分流暢。經過對比,和QQ的圖片選擇器滑動幀數表現基本一致,都十分流暢,同時都強於微信的圖片選擇器。微信的圖片選擇器,在快速滑動的時候明顯感到有一絲卡頓,通過Core Animation檢視發現,微信的圖片選擇器在我的6s裝置下幀數平均約52左右,好幾次甚至低於50,在4s裝置上則表現更糟一些。下面貼上幀數測試截圖,大家也可以測試一下~

TZImagePickerController的幀數表現 (iOS9.3.2 6s).png

TZImagePickerController的表現 (iOS7.0.4 4s).png

QQ圖片選擇器的幀數表現 (iOS9.3.2 6s).png

QQ圖片選擇器的幀數表現 (iOS7.0.4 4s).png

微信圖片選擇器的幀數表現 (iOS9.3.2 6s).png

1.5.0版本(2016.06.22)
1.可把拍照按鈕放在外面了,可以設定彈出一個sheet提示使用者選擇相簿或相機;
2.新增了sortAscendingByModificationDate屬性,預設為YES,設定為NO時,照片會按修改時間降序,拍照按鈕會在第一個;
3.優化了Demo頁面的UI,新增6個開關控制元件,可方便地更改各個設定來開啟選擇器;
4.修復了若干bug;

1.6.3版本(2016.08.29)
1.支援單選模式,將maxImagesCount設定為1即可。
2.支援國際化,目前支援中文和英文。
3.圖片名字可從外界傳,無須再改動原始碼。
4.圖片預覽介面照片之間留20畫素的間隙,優化預覽效果。
5.圖片選擇頁可自定義圖片展示列數。

最近更新
2.2.2 修復minPhotoWidthSelectable不生效的問題, 使用@available消除警告
2.1.8 優化gif圖播放的體驗,加入iCloud同步進度條;新增notScaleImage屬性,設定為YES時內部不去縮放圖片
2.1.6 新增allowCameraLocation屬性,預設為YES,置為NO時不會在照相/攝像時定位,修復一個序號紊亂的bug
2.1.4 新增多個頁面和元件的樣式自定義block,允許自定義絕大多數UI樣式
2.1.2 新增showPhotoCannotSelectLayer屬性,當已選照片張數達到最大可選張數時,可像微信一樣讓其它照片顯示一個提示不可選的浮層
2.1.1 新增是否顯示圖片選中序號的屬性,優化一些細節
2.1.0.3 新增拍攝視訊功能,優化一些細節
2.0.0.6 優化自定義languageBundle的支援,加入使用示例
2.0.0.5 優化效能,提高選擇器開啟速度,新增越南語支援
2.0.0.2 新增繁體語言,可設定首選語言,國際化支援更強大;優化一些細節
1.9.8 支援Carthage,優化一些細節
1.9.6 優化視訊預覽和gif預覽頁toolbar在iPhoneX上的樣式
1.9.4 適配iPhoneX
1.9.0 移除”prefs:root=”的呼叫,這個API已經被列為私有API,請大家儘快升級
1.8.4 加入橫豎屏適配;支援視訊/gif多選;支援視訊和照片一起選
1.8.1 新增2個代理方法,支援由上層來決定相簿/照片的顯示與否
1.8.0 修復若干bug, 提升流暢度

1.7.7 支援GIF圖片的播放和選擇
1.7.6 支援對共享相簿和同步相簿的顯示
1.7.5 允許不進入預覽頁面直接選擇照片
1.7.4 支援單選模式下裁剪照片,支援任意矩形和圓形裁剪框
1.7.3 優化iCloud照片的顯示與選擇

六. 常見問題

Q:pod search TZImagePickerController 搜尋出來的不是最新版本
A:需要在終端執行cd轉換檔案路徑命令退回到Desktop,然後執行pod setup命令更新本地spec快取(可能需要幾分鐘),然後再搜尋就可以了

Q:拍照後照片儲存失敗
A:請參考issue481:https://github.com/banchichen/TZImagePickerController/issues/481 的資訊排查,若還有問題請直接在issue內評論

Q:photos陣列圖片不是原圖,如何獲取原圖?
A:請參考issue457的解釋:https://github.com/banchichen/TZImagePickerController/issues/457

Q:系統語言是中文/英文,介面上卻有部分相簿名字、返回按鈕顯示成了英文/中文?
A:請參考 https://github.com/banchichen/TZImagePickerController/issues/443https://github.com/banchichen/TZImagePickerController/issues/929

Q:預覽介面能否支援傳入NSURL、UIImage物件?
A:排期中,優先順序高

Q:設定可選視訊的最大/最小時長?照片的最小/最大尺寸?不符合要求的不顯示
A:可以的,參照Demo的isAssetCanSelect方法實現。我會返回asset出來,顯示與否你來決定,注意這個是一個同步方法,對於需要根據asset去非同步獲取的資訊如視訊的大小、視訊是否存在iCloud裡來過濾的,無法做到。如果真要這樣做,相簿開啟速度會變慢,你需要改我原始碼。

Q:可否支援橫屏?
A:1.8.4版本已支援

Q:可否加入視訊拍攝功能?
A:2.1.0.3版本已支援

Q:可否加入視訊多選功能?
A:1.8.4版本已支援

Q:可否讓視訊和圖片允許一起選?
A:1.8.4版本已支援

Q:可否增加微信編輯圖片的功能?
A:考慮下,優先順序低

Q:是否有QQ/微信群?
A:有QQ群:778723997

Q:想提交一個PR?
A:請先加QQ群和我確認下,避免同時改動同一處內容。一個PR請只修復1個問題,變動內容越少越好

Q:demo在真機上跑不起來?
A:1、team選你自己的;2、bundleId也改成你自己的或改成一個不會和別人重複的。可參考簡書的這篇部落格

七. 其它

更具體的資訊大家感興趣的話去看程式碼吧,如果發現了bug請提一個issue,當然最好你給順便解決了並提一個pull request,這樣最帥了對吧…
程式碼地址:https://github.com/banchichen/TZImagePickerController
歡迎使用,覺得不錯請給一個小小的star鼓勵一下~


相關文章