如何學習新架構(儲存圖片到相簿),架構相簿
一.點擊查看大圖1.點擊圖片或按鈕(點擊查看大圖按鈕),modal出來一個控制器,顯示大圖片 2.怎麼處理能讓點擊圖片就能查看大圖? 兩種方法:1.給圖片添加點按手勢 2.給圖片所在的view上添加 - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 2.1 添加點按手勢 優點:適用於任何情境下,不受限制 缺點:代碼量大 2.2 給圖片所在view添加touchesEnded:方法 優點:能快速達到點擊查看大圖效果,代碼量小 缺點:只有當圖片所在view和圖片一樣大的時候,方法才好用,應用情境有限 3.怎麼快速拿到控制器,來modal? 能快速拿到的控制器,就是視窗的根控制器 4.建立一個控制器,點擊圖片的時候就把控制器modal出來 4.1 在控制器上添加一個scrollView,佔據全屏 因為大圖片能夠上下滾動查看 4.2 scrollView上面還要添加一個UIImageView 我們需要手動建立UIImageView,然後手動添加到scrollView上 因為圖片尺寸不固定,大圖佔據全屏,小圖置中 4.3 在控制器上添加兩個按鈕 一個返回按鈕,一個儲存圖片按鈕 4.4 所以,我們建立的控制器應該為UIViewController 5.在moadl出來的控制器顯示大圖片 5.1 要想在控制器中查看大圖,首先要拿到大圖,怎麼拿? 5.1.1可以建立一個通知,把圖片當做通知參數傳遞 5.1.2因為控制器是在圖片的uiview中modal出來的,可以用順傳的方法,把模型傳遞給控制器 順傳: 1.上一級拿到下一級的控制器 2.在下一級控制器中定義屬性接收資料 3.在上一級中給下一級定義的屬性賦值 5.2 在查看大圖控制器中用代碼建立一個UIImageView控制項,biang添加到scrollView上面 5.3 判斷是否是大圖 5.3.1 是大圖,就設定UIImageView的frame從0,0(座標原點)開始顯示 寬度等於螢幕寬度,高度就按照寬度的縮放比例進行縮放 5.3.2 不是大圖,就設定UIImageView的中心為螢幕的中心 6.顯示大圖的時候,讓大圖能夠縮放 6.1如何縮放? 6.1.1 添加捏合手勢,使用transform對圖片縮放 優點:適用於任何情境 缺點:代碼比較複雜 6.1.2 使用scrollView的代理方法 優點:代碼相對來說,比較簡單 缺點:只有才能使用 6.2 怎麼用scrollView代理.進行縮放 6.2.1 遵守協議,實現代理方法 6.2.2 在代理方法裡面返回需要縮放的view 6.2.3 在外界設定最大(最小的縮放比例) 查看大圖並進行縮放原始碼
1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 4 UIImage *image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:_item.image0]; 5 6 UIImageView *imageView = [[UIImageView alloc] init]; 7 _imageView = imageView; 8 [imageView sd_setImageWithURL:[NSURL URLWithString:_item.image1] placeholderImage:image]; 9 CGFloat h = XMGScreenW / _item.width * _item.height;10 imageView.frame = CGRectMake(0, 0, XMGScreenW, h);11 [_scroolView addSubview:imageView];12 13 if (_item.is_bigPicture) {14 _scroolView.contentSize = CGSizeMake(0, h);15 16 if (_item.height > h) {17 CGFloat scale = _item.height / h;18 //2.設定縮放比例19 _scroolView.maximumZoomScale = scale;20 _scroolView.minimumZoomScale = 1; 21 }22 } else {23 imageView.center = CGPointMake(XMGScreenW * 0.5, XMGScreenH * 0.5);24 }25 // 縮放26 //1.設定代理,告訴它哪個View需要做縮放27 //2.設定縮放比例28 _scroolView.delegate = self;29 }30 #pragma mark - UIScrollViewDelegate31 // 作用:返回需要做縮放的view32 // 調用:每次縮放的時候才會調用33 - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView34 {35 return _imageView;36 }
二.儲存圖片到相簿1.儲存圖片到相簿也有兩種方法 1.1 調用系統方法儲存到相簿 優點:簡單快捷,兩個方法就能實現 缺點:只能儲存到系統相簿下,不能儲存到自訂的相簿下 注意:監聽圖片是否儲存完成的方法,必須是系統指定的方法,可以跳進儲存圖片到相簿的方法裡面查看該方法 1.2 用 Photos架構,自訂相簿儲存圖片 優點:能把圖片儲存到指定的相簿 缺點:diamante量大,需要學習新的架構 儲存到系統相簿原始碼
1 // 點擊儲存調用 2 - (IBAction)save:(id)sender { 3 // 儲存系統相簿 4 UIImageWriteToSavedPhotosAlbum(_imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 5 } 6 // 詢問下使用者是否允許當前app訪問相簿 7 // 監聽圖片是否儲存完成 8 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo 9 {10 if (error) {11 [SVProgressHUD showErrorWithStatus:@"儲存失敗"];12 } else {13 [SVProgressHUD showSuccessWithStatus:@"儲存成功"];14 }15 }
2.如何學習一個新的架構 2.1 首先搞清楚這個架構常用的類 2.2 怎麼搞清楚,哪些類常用? 2.2.1 百度(天朝的度娘太複雜,多變) 2.2.2 查看官方文檔 2.3 怎麼能快速定位相關架構的官方文檔? 搜尋索引鍵: 架構名稱 + FrameWork Reference
2.4 如何學習去使用一個類(方法)? 按住 option 點擊類名 或方法名 總結:1.如果想瞭解類,有哪些東西,跳標頭檔 2.如果想瞭解怎麼使用,用option
3.用 Photos架構,自訂相簿儲存圖片 3.1 儲存圖片到相簿原理 3.1.1 建立新的相簿 3.1.2 先把圖片儲存到系統相簿 3.1.3 把圖片從系統相簿拷貝到新的相簿 Photos常用5個類,操作相簿
擁有的時候
PHPhotoLibrary:相簿:(所有相簿集合)
PHAssetCollection:相簿(圖片集合)
PHAsset:圖片
建立的時候:
PHAssetCreationRequest:建立新圖片,刪除圖片,修改圖片 PHAssetCollectionChangeRequest:建立相簿,刪除相簿,修改相簿 3.2 如何儲存圖片到自己的相簿? 使用 Photos架構 3.3 Photos架構儲存圖片到自己相簿步驟 3.3.1 建立圖片請求類(給系統相簿建立一張新的圖片) 3.3.2 建立相簿請求類(修改相簿) 3.3.3 把圖片拷貝到自己相簿中 3.3.4 步驟在類的介紹中有樣本 3.3.5 注意:建立圖片和相簿請求類必須封裝在一個方法裡面,這個方法在標頭檔裡面能查看到,這個方法又分為同步和非同步兩種,一般用非同步 3.4 怎麼拷貝到自己的相簿? 3.4.1用相簿請求類對象 調用 [assetCollectionChangeRequest addAssets:<#(nonnull id<NSFastEnumeration>)#>] 方法 3.4.2(nonnull id<NSFastEnumeration>)參數是什麼意思? 表示可以傳一個對象,但要遵守 NSFastEnumeration 協議 遵守這個協議的一般是數組,因為 Enumeration 是遍曆的意思,一般數組才能遍曆 3.4.3 不知道參數怎麼寫,怎麼辦? 按住option 點擊方法,查看方法介紹,裡面有介紹參數怎麼寫 3.4.4 以後只要看到這個NSFastEnumeration協議,就可以表示數組 4.功能做好後我們還發現兩個問題 4.1 儲存前要查看app是否有許可權訪問相簿(如果沒授權,就詢問使用者是否允許訪問) 4.2 每次儲存都會建立新的相簿 5.許可權問題解決方案 5.1每次儲存前都先查看app許可權,如果允許訪問,直接儲存 5.2不允許訪問,就提示使用者,去設定裡面設定許可權 5.3如果沒有授權,就彈出許可權框,讓使用者授權 許可權的四種狀態: (第一次)PHAuthorizationStatusNotDetermined = 0, 不確定是否允許當前app訪問系統相簿
PHAuthorizationStatusRestricted, 家長監護
PHAuthorizationStatusDenied, (拒絕)不允許當前app訪問系統相簿 PHAuthorizationStatusAuthorized (授權)允許當前app訪問系統相簿 6.每次都建立新的相簿解決方案 6.1 儲存之前,先查看系統相簿是否存在同名的相簿 6.2 如果存在,就儲存到這個相簿中 6.3 不存在,就建立相簿儲存 7. 怎麼確定是否存在相簿? 7.1思考:用一個屬性來決定相簿是否存在可以嗎? 不可以,下次啟動屬性就為空白了 7.2 把屬性存到沙箱可以嗎? 不可以,如果把app卸載,又重新安裝,沙箱也為空白,但相簿存在 7.3 最終方案:擷取所有相簿,查看是否存在同名相簿 8.怎麼擷取所有相簿? 8.1 先查看相簿類 是否有這樣的方法 找關鍵字PHAssetCollection相簿 發現沒有 8.2 去查看相簿類 是否有這樣的方法 可能是相簿自己管理自己 找到一個方法 + (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsWithType:(PHAssetCollectionType)type subtype:(PHAssetCollectionSubtype)subtype options:(nullable PHFetchOptions *)options; fetch尋找的意思 8.3 PHFetchResult這個傳回值類型不知道是什麼,怎麼辦? 點進去看一下,發現 8.4 參數不會傳,可以用option 或者先傳空,如果有問題,在回來解決參數問題,如果是枚舉參數,一般先傳預設值 儲存到圖片到自訂相簿原始碼
1 // 點擊儲存調用 2 - (IBAction)save:(id)sender { 3 //查看當前app授權狀態 4 PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; 5 switch (status) { 6 case PHAuthorizationStatusNotDetermined: 7 { // 未授權,彈出授權框 8 [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { 9 // 使用者選擇完畢就會調用—選擇允許,直接儲存10 if (status == PHAuthorizationStatusAuthorized) {11 [self savePhoto];12 }13 }];14 選擇不允許訪問,就不儲存15 break;16 }17 case PHAuthorizationStatusAuthorized:18 { // 授權,就直接儲存19 [self savePhoto];20 break;21 }22 default:23 {// 拒絕 告知使用者去哪開啟授權24 [SVProgressHUD showInfoWithStatus:@"開啟設定 -> 尋找百思不得姐 -> 開啟照片開關 -> 允許當前app訪問系統相簿就可以儲存圖片"];25 break;26 }27 }28 }29 30 // 添加圖片到自己相簿31 - (void)savePhoto32 {33 [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{34 // 1.建立圖片請求類(建立系統相簿中新的圖片)PHAssetCreationRequest35 // 把圖片放在系統相簿36 PHAssetCreationRequest *assetCreationRequest = [PHAssetCreationRequest creationRequestForAssetFromImage:_imageView.image];37 38 // 2.建立相簿請求類(修改相簿)PHAssetCollectionChangeRequest39 PHAssetCollectionChangeRequest *assetCollectionChangeRequest = nil;40 41 // 擷取之前相簿42 PHAssetCollection *assetCollection = [self fetchAssetCollection:@"百思不得姐"];43 44 // 判斷是否已有相簿45 if (assetCollection) {46 // 如果存在已有同名相簿 指定這個相簿,建立相簿請求修改類 47 assetCollectionChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];48 } else { //不存在,建立新的相簿49 assetCollectionChangeRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:@"百思不得姐"];50 } 51 // 3.把圖片添加到相簿中52 // NSFastEnumeration:以後只要看到這個,就可以表示數組53 //assetCreationRequest.placeholderForCreatedAsset 圖片請求類預留位置(相當於一個記憶體位址) 54 //因為creationRequestForAssetFromImage方法是非同步實行的,在這裡不能保證 assetCreationRequest有值55 56 [assetCollectionChangeRequest addAssets:@[assetCreationRequest.placeholderForCreatedAsset]];57 58 } completionHandler:^(BOOL success, NSError * _Nullable error) {59 60 if (success) {61 [SVProgressHUD showSuccessWithStatus:@"儲存成功"];62 } else {63 [SVProgressHUD showErrorWithStatus:@"儲存失敗"];64 }65 66 }];67 }68 69 // 指定相簿名稱,擷取相簿70 - (PHAssetCollection *)fetchAssetCollection:(NSString *)title71 {72 // 擷取相簿中所有自訂相簿73 PHFetchResult *result = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];74 遍曆相簿,判斷是否存在同名的相簿75 for (PHAssetCollection *assetCollection in result) {76 if ([title isEqualToString:assetCollection.localizedTitle]) { 存在,就返回這個相簿77 return assetCollection;78 }79 } 80 return nil;81 }