之前寫了一個仿Snapseed的ImagePicker,見Demo和之前的簡書文章,
之后發現有人說第一次未授權時collectionview會加載不出照片,發現沒有在合適時候調用權限管理。iOS10的這個權限管理是info.plist的一個鍵值,沒有回調方法。查詢photoskit方法里,發現有一個權限回調方法,就想封裝一個方法來友好的詢問用戶權限。
查詢文檔,相冊權限PHAuthorizationStatus枚舉類型有這么幾種。
typedef NS_ENUM(NSInteger, PHAuthorizationStatus) {
PHAuthorizationStatusNotDetermined = 0, // User has not yet made a choice with regards to this application 用戶未決定
PHAuthorizationStatusRestricted, // This application is not authorized to access photo data. 一般是家長權限之類的拒絕
// The user cannot change this application’s status, possibly due to active restrictions
// such as parental controls being in place.
PHAuthorizationStatusDenied, // User has explicitly denied this application access to photos data. 用戶拒絕
PHAuthorizationStatusAuthorized // User has authorized this application to access photos data. 用戶允許
} PHOTOS_AVAILABLE_IOS_TVOS(8_0, 10_0);
其中,我們不希望用戶去拒絕,達到PHAuthorizationStatusDenied
這個狀態,這樣的話用戶再要獲取權限就要到設置里的隱私里找到我們的應用再手動打開,而沒辦法在app內去請求權限更改。那么我們希望暫時拒絕后的狀態應該是PHAuthorizationStatusNotDetermined
的,思路就是提示一個alertviewcontroller去詢問,用戶取消則不去調用真正的詢問權限(相當于忽略),以便下次提醒在詢問。用戶同意則調用系統詢問權限,這時一般用戶也會再允許了。流程示意圖如下。
代碼很簡單,直接貼上來
- (void)showPermissionAlertInController{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"需要你的圖庫的權限" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
//do something
}];
UIAlertAction *requestAction = [UIAlertAction actionWithTitle:@"同意" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status == PHAuthorizationStatusAuthorized) {
NSLog(@"用戶同意授權相冊");
}else {
NSLog(@"用戶拒絕授權相冊");
}
dispatch_async(dispatch_get_main_queue(), ^{
//do something
});
}];
});
}];
[alert addAction:cancelAction];
[alert addAction:requestAction];
[self presentViewController:alert animated:YES completion:nil];
}
再在需要用到權限的地方加上判斷就好
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized)
后來發現如果調用選擇器時在外部改變了照片(增加,刪除)后collectionview不會改變,就研究了一下photoskit,發現有個- (void)photoLibraryDidChange:(PHChange *)changeInfo
檢測相冊變動,但之前需要注冊為觀察者并實現協議
PHPhotoLibraryChangeObserver
- (void)viewDidLoad{
[super viewDidLoad];
[[PHPhotoLibrary sharedPhotoLibrary]registerChangeObserver:self];
//other code
}
- (void)dealloc{
[[PHPhotoLibrary sharedPhotoLibrary]unregisterChangeObserver:self];
}
然后實現方法,更新ui的話要在主線程里
- (void)photoLibraryDidChange:(PHChange *)changeInfo {
dispatch_async(dispatch_get_main_queue(), ^{
PHFetchResultChangeDetails *changes = [changeInfo changeDetailsForFetchResult:self.imageAssetsResult];
if (changes) {
self.photosDataSource.itemArray = [self getImageAssets];
[self.photosView reloadData];
}
});
}
這個方法默認所有相冊的變更都會通知,但是有些變動是我們不需要的,比如用戶新建了一個新空相冊,刪除了一個舊相冊等,這時我們可以用PHChange里的changeDetails去區分,比如changeDetailsForFetchResult:(PHFetchResult *)object;
就是傳入一組FetchResult,如果這組Result有變化,比如這組Result是Asset的集合,Asset增加減少,那么就會返回一個ChangeDetails,可以用此區分,但是如果是Asset內部的變化,就不會返回一個ChangeDetails。同樣的如果這組Result是Collection的集合,那么Collection內部的變化,比如Collection里的Asset對象增加減少,就不會有返回。
具體可以見蘋果官方的例子
最后
這篇文章篇幅不多,作為一些補充,希望能幫到有需要的人。
如果您覺得有幫助,不妨給個star鼓勵一下,歡迎關注&交流
有任何問題歡迎評論私信或者提issue
QQ:757765420
Email:nemocdz@gmail.com
Github:Nemocdz
微博:@Nemocdz