// // KSWhiteboardView.m // TeacherDaya // // Created by Kyle on 2019/10/31. // Copyright © 2019 DayaMusic. All rights reserved. // #import "KSWhiteboardView.h" #import #import "ZoomControl.h" #import #import "WhiteUtils.h" #import #define kSceneKey @"/DAYA" #define MAXPHOTONUMBER (1) #define COLUMNNUMBER (3) #import "TZImageManager.h" #import #import #import "TZVideoPlayerController.h" #import "TZImagePickerController.h" #import #import "KSNormalAlertView.h" @interface KSWhiteboardView () { BOOL _isSelectOriginalPhoto; } @property (nonatomic, strong) UIImagePickerController *imagePickerVc; @property (nonatomic, strong) NSMutableArray *imageArray; // 图片数组 @property (nonatomic, strong) NSMutableArray *imageAsset; // 图片 asset //@property (nonatomic, strong) ZoomControl *zoomControl; @property (nonatomic, assign) BOOL isFullScreenMode; @property (nonatomic, weak) id delegate; @property (nonatomic, strong) UIView *backView; @property (nonatomic, strong, nonnull) WhiteSdkConfiguration *sdkConfig; @property (nonatomic, weak, nullable) id roomCallbackDelegate; @property (nonatomic, copy) NSString *roomToken; @property (nonatomic, assign, getter=isReconnecting) BOOL reconnecting; @property (nonatomic, strong) WhiteCameraConfig *defaultConfig; @property (nonatomic, strong) NSString *currentSceneDir; @property (nonatomic, strong) UIView *toobarView; @property (nonatomic, strong) NSMutableArray *sceneArray; @property (nonatomic, assign) BOOL isConnected; // 是否加入房间 @end @implementation KSWhiteboardView - (instancetype)initWithDelegate:(id)delegate frame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.delegate = delegate; [self addSubview:self.boardView]; [self addSubview:self.backView]; [self.boardView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self); }]; [self.backView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self); }]; [self initSDK]; } return self; } - (void)createToolBar { UIButton *preButton = [UIButton buttonWithType:UIButtonTypeCustom]; [preButton setImage:[UIImage imageNamed:@"whiteBoard_left"] forState:UIControlStateNormal]; [preButton setImage:[UIImage imageNamed:@"whiteBoard_left_h"] forState:UIControlStateHighlighted]; [preButton addTarget:self action:@selector(preWhiteBoardPage) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:preButton]; [preButton mas_makeConstraints:^(MASConstraintMaker *make) { make.left.mas_equalTo(self); make.centerY.mas_equalTo(self.mas_centerY); make.width.mas_equalTo(36); make.height.mas_equalTo(36); }]; UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeCustom]; [nextButton setImage:[UIImage imageNamed:@"whiteBoard_right"] forState:UIControlStateNormal]; [nextButton setImage:[UIImage imageNamed:@"whiteBoard_right_h"] forState:UIControlStateHighlighted]; [nextButton addTarget:self action:@selector(nextWhiteBoardPage) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:nextButton]; [nextButton mas_makeConstraints:^(MASConstraintMaker *make) { make.right.mas_equalTo(self); make.centerY.mas_equalTo(self.mas_centerY); make.width.mas_equalTo(36); make.height.mas_equalTo(36); }]; _toobarView = [[UIView alloc] init]; _toobarView.backgroundColor = [UIColor whiteColor]; _toobarView.layer.borderWidth = 1.0f; _toobarView.layer.borderColor = HexRGB(0xe5e5e5).CGColor; _toobarView.layer.cornerRadius = 4.0f; [self addSubview:_toobarView]; [_toobarView mas_makeConstraints:^(MASConstraintMaker *make) { make.centerX.mas_equalTo(self.mas_centerX); make.bottom.mas_equalTo(self.mas_bottom).offset(-15); make.height.mas_equalTo(40); make.width.mas_equalTo(36*7); }]; [self createToolButton]; } - (void)createToolButton { NSArray *imageArray = @[@"whiteboard_pencil",@"whiteboard_eraser",@"whiteboard_ellipse",@"whiteboard_clear",@"whiteboard_delete",@"whiteboard_add",@"whiteboard_upload"]; NSArray *titleArray = @[@"画笔",@"橡皮",@"椭圆",@"清空",@"删除",@"新增",@"上传"]; for (NSInteger i = 0; i < titleArray.count; i++) { UIButton *toolButton = [UIButton buttonWithType:UIButtonTypeCustom]; toolButton.frame = CGRectMake(i*36, 2, 36, 36); [toolButton setImage:[UIImage imageNamed:imageArray[i]] forState:UIControlStateNormal]; [toolButton setImage:[[UIImage imageNamed:imageArray[i]] maskWithColor:THEMECOLOR] forState:UIControlStateSelected]; [toolButton setImage:[[UIImage imageNamed:imageArray[i]] maskWithColor:THEMECOLOR] forState:UIControlStateHighlighted]; toolButton.tag = 1000+i; [toolButton.titleLabel setFont:[UIFont systemFontOfSize:10.0f]]; [toolButton addTarget:self action:@selector(toolButtonClickAction:) forControlEvents:UIControlEventTouchUpInside]; [_toobarView addSubview:toolButton]; } } - (void)toolButtonClickAction:(UIButton *)sender { NSInteger index = sender.tag - 1000; if (index == 0 || index == 1 || index == 2) { UIButton *button = [self.toobarView viewWithTag:1000]; [button setSelected:NO]; UIButton *button1 = [self.toobarView viewWithTag:1001]; [button1 setSelected:NO]; UIButton *button2 = [self.toobarView viewWithTag:1002]; [button2 setSelected:NO]; sender.selected = YES; } switch (index) { case 0: // 铅笔颜色 { WhiteMemberState *memberState = [[WhiteMemberState alloc] init]; //白板初始状态时,教具默认为 pencil memberState.currentApplianceName = AppliancePencil; // memberState.strokeColor = @[@(255),@(0),@(0)]; // memberState.strokeWidth = @2; [self.room setMemberState:memberState]; } break; case 1: // 橡皮 { WhiteMemberState *memberState = [[WhiteMemberState alloc] init]; memberState.currentApplianceName = ApplianceEraser; [self.room setMemberState:memberState]; } break; case 2: // 椭圆 { WhiteMemberState *memberState = [[WhiteMemberState alloc] init]; //白板初始状态时,教具默认为 pencil memberState.currentApplianceName = ApplianceEllipse; [self.room setMemberState:memberState]; } break; case 3: // 清空 { [self.room cleanScene:YES]; } break; case 4: // 删除 { [self deleateWhiteBoard]; } break; case 5: // 新增 { [self createNewWhiteBoard]; } break; case 6: // 上传 { [self pushImagePickerController]; } break; default: break; } } #pragma mark --- 删除白板 - (void)deleateWhiteBoard { if ([self.sceneArray count] <= 1) { [self.room cleanScene:NO]; return; } else { NSInteger delIndex = 0; for (NSInteger i = 0; i < [self.sceneArray count]; i++) { WhiteScene *sc = (WhiteScene *)self.sceneArray[i]; NSString *s = [self whiteBoardPageName:sc.name]; if ([s isEqualToString:self.currentSceneDir]) { delIndex = i; break; } } [self.sceneArray removeObjectAtIndex:delIndex]; WhiteScene *sc; if (delIndex < [self.sceneArray count]) { sc = (WhiteScene *)self.sceneArray[delIndex]; } else { sc = (WhiteScene *)[self.sceneArray lastObject]; } [self.room removeScenes:self.currentSceneDir]; self.currentSceneDir = [self whiteBoardPageName:sc.name]; } } #pragma mark ---- 新增白板 - (void)createNewWhiteBoard { NSString *pageName = [NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970]]; WhitePptPage *pptPage = [[WhitePptPage alloc] init]; WhiteScene *scene = [[WhiteScene alloc] initWithName:pageName ppt:pptPage]; [self.sceneArray addObject:scene]; NSInteger pageCount = [self.sceneArray count]; //插入新页面的 API,现在支持传入 ppt 参数(可选),所以插入PPT和插入新页面的 API,合并成了一个。 [self.room putScenes:kSceneKey scenes:@[scene] index:pageCount]; NSString *newScenePath = [self whiteBoardPageName:pageName]; [self.room setScenePath:newScenePath]; self.currentSceneDir = newScenePath; } #pragma mark ---- 上传图片 - (void)uploadPPt { UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:IS_IPAD ? UIAlertControllerStyleAlert : UIAlertControllerStyleActionSheet]; [alertVC addAction:[UIAlertAction actionWithTitle:@"相机拍摄" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 调用相机 [self takePhoto]; }]]; [alertVC addAction:[UIAlertAction actionWithTitle:@"从手机相册选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { // 调用相册 [self pushImagePickerController]; }]]; [alertVC addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]]; alertVC.modalPresentationStyle = UIModalPresentationFullScreen; [[self getViewController] presentViewController:alertVC animated:true completion:nil]; } #pragma mark ------ 上一页 - (void)preWhiteBoardPage { if (![self.sceneArray count]) { DLog(@"last page return"); return; } else if ([self.sceneArray count] == 1) { WhiteScene *sc = (WhiteScene *)[self.sceneArray firstObject]; self.currentSceneDir = [self whiteBoardPageName:sc.name]; } else { NSString *tmpScName = self.currentSceneDir; for (WhiteScene *sc in self.sceneArray) { NSString *s = [self whiteBoardPageName:sc.name]; if ([s isEqualToString:self.currentSceneDir]) { self.currentSceneDir = tmpScName; break; } else { tmpScName = s; } } } DLog(@"last page: %@", self.currentSceneDir); [self.room setScenePath:self.currentSceneDir]; } #pragma mark ------ 下一页 - (void)nextWhiteBoardPage { if (![self.sceneArray count]) { DLog(@"next page return"); return; } else if ([self.sceneArray count] == 1) { WhiteScene *sc = (WhiteScene *)[self.sceneArray firstObject]; self.currentSceneDir = [self whiteBoardPageName:sc.name]; } else { NSInteger matchIndex = 0; for (NSInteger i = 0; i < [self.sceneArray count]; i++) { WhiteScene *sc = (WhiteScene *)self.sceneArray[i]; NSString *s = [self whiteBoardPageName:sc.name]; if ([s isEqualToString:self.currentSceneDir]) { matchIndex = i + 1; break; } } WhiteScene *tsc; if (matchIndex < [self.sceneArray count]) { tsc = (WhiteScene *)self.sceneArray[matchIndex]; } else { tsc = (WhiteScene *)[self.sceneArray lastObject]; } self.currentSceneDir = [self whiteBoardPageName:tsc.name]; } DLog(@"next page: %@", self.currentSceneDir); [self.room setScenePath:self.currentSceneDir]; } - (void)reloadWhiteBoardWithName:(NSString *)name { self.currentSceneDir = [self whiteBoardPageName:name]; [self.room setScenePath:self.currentSceneDir]; } - (void)destroy { [self.boardView stopLoading]; [self removeFromSuperview]; } - (void)setCurrentFrame:(CGRect)currentFrame { _currentFrame = currentFrame; if (!self.isFullScreenMode) { self.frame = currentFrame; } [self.room refreshViewSize]; } #pragma mark - ZoomControlDelegate - (void)zoomControlDelegate:(CGFloat)scale{ self.clipsToBounds = YES; CGSize baseSize = self.frame.size; baseSize.height *= scale; baseSize.width *= scale; CGPoint center = self.boardView.center; CGRect frame = self.frame; frame.size = baseSize; self.boardView.frame = frame; self.boardView.center = center; if (self.delegate && [self.delegate respondsToSelector:@selector(whiteboardViewDidChangeZoomScale:)]) { [self.delegate whiteboardViewDidChangeZoomScale:scale]; } } - (void)fullScreenDidUpdate:(BOOL)isFull{ self.isFullScreenMode = isFull; UIView *superView = self.superview; if (self.isFullScreenMode) { [superView bringSubviewToFront:self]; [UIView animateWithDuration:0.3 animations:^{ self.frame = CGRectMake(0, 0, UIScreenWidth, UIScreenHeight); }]; }else{ [UIView animateWithDuration:0.3 animations:^{ self.frame = self.currentFrame; }]; } } - (WhiteBoardView *)boardView { if (!_boardView) { _boardView = [[WhiteBoardView alloc] init]; } return _boardView; } - (UIView *)backView { if (!_backView) { _backView = [[UIView alloc] init]; _backView.backgroundColor = [UIColor whiteColor]; _backView.hidden = YES; } return _backView; } //- (ZoomControl *)zoomControl{ // if (!_zoomControl) { // _zoomControl = [[ZoomControl alloc] init]; // _zoomControl.delegate = self; // _zoomControl.increaseScaleBtn.hidden = YES; // _zoomControl.reduceScaleBtn.hidden = YES; // } // return _zoomControl; //} #pragma mark - CallbackDelegate - (id)roomCallbackDelegate { if (!_roomCallbackDelegate) { _roomCallbackDelegate = self; } return _roomCallbackDelegate; } - (id)commonDelegate { if (!_commonDelegate) { _commonDelegate = self; } return _commonDelegate; } #pragma mark - WhiteCommonCallbackDelegate - (void)sdkSetupFail:(NSError *)error { if (self.delegate && [self.delegate respondsToSelector:@selector(joinWhiteboardRoomStatus:)]) { [self.delegate joinWhiteboardRoomStatus:JOINROOMSTATUS_FAILED]; } } - (void)throwError:(NSError *)error { NSLog(@"throwError: %@", error.userInfo); } - (NSString *)urlInterrupter:(NSString *)url { return @"https://white-pan.oss-cn-shanghai.aliyuncs.com/124/image/beauty2.png"; } #pragma mark - WhiteSDK - (WhiteSdkConfiguration *)sdkConfig { if (!_sdkConfig) { // 4. 初始化 SDK 配置项,根据需求配置属性 WhiteSdkConfiguration *config = [[WhiteSdkConfiguration alloc] initWithApp:@"614/YXPRtKkVCBOBjQ"]; //如果不需要拦截图片API,则不需要开启,页面内容较为复杂时,可能会有性能问题 config.enableInterrupterAPI = NO; //打开用户头像显示信息 config.userCursor = NO; _sdkConfig = config; } return _sdkConfig; } - (void)initSDK { // 5.初始化 SDK,传入 commomDelegate self.sdk = [[WhiteSDK alloc] initWithWhiteBoardView:self.boardView config:self.sdkConfig commonCallbackDelegate:self.commonDelegate]; } #pragma mark - Room Action - (void)joinWhiteRoom { if (self.isConnected) { return; } [WhiteUtils getRoomTokenWithRoomId:self.roomId completionHandler:^(NSString * _Nullable uuid, NSString * _Nullable roomToken, NSString * _Nonnull randomRoom, NSString * _Nullable randomNumeric, NSError * _Nullable error) { if (error) { NSLog(NSLocalizedString(@"创建房间失败,error:", nil), [error localizedDescription]); if (self.delegate && [self.delegate respondsToSelector:@selector(joinWhiteboardRoomStatus:)]) { [self.delegate joinWhiteboardRoomStatus:JOINROOMSTATUS_PARAMERROR]; } } else { self.roomUuid = uuid; if (self.roomUuid && roomToken) { [self joinRoomWithToken:roomToken]; } else { NSLog(NSLocalizedString(@"连接房间失败,room uuid:%@ roomToken:%@", nil), self.roomUuid, roomToken); if (self.delegate && [self.delegate respondsToSelector:@selector(joinWhiteboardRoomStatus:)]) { [self.delegate joinWhiteboardRoomStatus:JOINROOMSTATUS_PARAMERROR]; } } } }]; } - (void)joinRoomWithToken:(NSString *)roomToken { NSDictionary *payload = @{@"avatar": @"https://white-pan.oss-cn-shanghai.aliyuncs.com/40/image/mask.jpg"}; WhiteRoomConfig *config = [[WhiteRoomConfig alloc] initWithUUID:self.roomUuid roomToken:self.roomToken uid:UserDefault(UIDKey)]; config.isWritable = NO; // 设置学生只读 config.disableEraseImage = YES; // 设置WhiteCameraBound [self.sdk joinRoomWithConfig:config callbacks:self.roomCallbackDelegate completionHandler:^(BOOL success, WhiteRoom * _Nonnull room, NSError * _Nonnull error) { if (success) { // 标记已加入房间 self.isConnected = YES; self.roomToken = roomToken; self.room = room; // 设置主播模式 [self.room setViewMode:WhiteViewModeBroadcaster]; [self.room disableCameraTransform:NO]; if (self.defaultConfig) { [self.room moveCamera:self.defaultConfig]; } [self.room getSceneStateWithResult:^(WhiteSceneState * _Nonnull state) { if (state.scenes) { for (WhiteScene *tmpScene in state.scenes) { if (![tmpScene.name isEqualToString:@"init"]) { [self.sceneArray addObject:tmpScene]; } } } DLog(@"state.scenePath: %@", state.scenePath); if ([state.scenePath isEqualToString:@"/init"]) { [self createNewWhiteBoard]; } else { self.currentSceneDir = state.scenePath; } }]; } else { if (self.delegate && [self.delegate respondsToSelector:@selector(joinWhiteboardRoomStatus:)]) { [self.delegate joinWhiteboardRoomStatus:JOINROOMSTATUS_FAILED]; } NSLog(@"错误信息:%@",[error localizedDescription]); } }]; } - (void)leaveRoom { if (self.room && self.isConnected) { [self.room disconnect:^{ self.isConnected = NO; }]; } } #pragma mark - Keyboard - (void)setRectangle { [self.room getSceneStateWithResult:^(WhiteSceneState * _Nonnull state) { if (state.scenes) { WhitePptPage *ppt = state.scenes[state.index].ppt; WhiteRectangleConfig *rectangle = [[WhiteRectangleConfig alloc] initWithInitialPosition:ppt.width height:ppt.height]; [self.room moveCameraToContainer:rectangle]; } }]; } /** 处理文字教具键盘隐藏时,内容偏移。 可以 @param n 键盘通知 */ - (void)keyboardDidDismiss:(NSNotification *)n { [self.boardView.scrollView setContentOffset:CGPointZero animated:YES]; } #pragma mark - WhiteRoomCallbackDelegate - (void)firePhaseChanged:(WhiteRoomPhase)phase { NSLog(@"%s, %ld", __FUNCTION__, (long)phase); if (self.room.disconnectedBySelf || self.isReconnecting || !self.sdk) { return; } if (phase == WhiteRoomPhaseDisconnected && self.roomUuid && self.roomToken) { self.reconnecting = YES; WhiteRoomConfig *config = [[WhiteRoomConfig alloc] initWithUUID:self.roomUuid roomToken:self.roomToken uid:UserDefault(UIDKey)]; [self.sdk joinRoomWithConfig:config callbacks:self.roomCallbackDelegate completionHandler:^(BOOL success, WhiteRoom * _Nullable room, NSError * _Nullable error) { self.reconnecting = NO; NSLog(@"reconnected"); if (error) { NSLog(@"error:%@", [error localizedDescription]); dispatch_main_async_safe(^{ [LOADING_MANAGER MBShowAUTOHidingInWindow:@"白板连接失败"]; self.isConnected = NO; }); } else { self.room = room; self.isConnected = YES; } }]; } } - (void)fireRoomStateChanged:(WhiteRoomState *)magixPhase; { NSLog(@"%s, %@", __func__, [magixPhase jsonString]); } - (void)fireBeingAbleToCommitChange:(BOOL)isAbleToCommit { NSLog(@"%s, %d", __func__, isAbleToCommit); } - (void)fireDisconnectWithError:(NSString *)error { dispatch_main_async_safe(^{ [LOADING_MANAGER MBShowAUTOHidingInWindow:@"白板断开连接"]; self.isConnected = NO; }); NSLog(@"%s, %@", __func__, error); } - (void)fireKickedWithReason:(NSString *)reason { NSLog(@"%s, %@", __func__, reason); } - (void)fireCatchErrorWhenAppendFrame:(NSUInteger)userId error:(NSString *)error { NSLog(@"%s, %lu %@", __func__, (unsigned long)userId, error); } - (void)fireMagixEvent:(WhiteEvent *)event { NSLog(@"fireMagixEvent: %@", [event jsonString]); } - (void)fireHighFrequencyEvent:(NSArray*)events { NSLog(@"%s", __func__); } - (NSMutableArray *)sceneArray { if (!_sceneArray) { _sceneArray = [NSMutableArray array]; } return _sceneArray; } - (NSString *)whiteBoardPageName:(NSString *)name { return [NSString stringWithFormat:@"%@/%@", kSceneKey, name]; } - (void)setRoomId:(NSString *)roomId { _roomId = roomId; // [self joinWhiteRoom]; } // 图片选择回调 - (void)evaluateWithChooseImage:(UIImage *)image { dispatch_async(dispatch_get_main_queue(), ^{ [self uploadImage:image]; }); } - (void)uploadImage:(UIImage *)image { // 上传图片 回调显示 // 如果需要旋转图片 if (self.isRotationImage) { image = [UIImage rotationImage:image rotation:UIImageOrientationLeft]; } NSData *imgData = [UIImage compressImage:image maxLength:5]; [UPLOAD_MANAGER configWithfilePath:@"/whiteboard/"]; [UPLOAD_MANAGER uploadImage:imgData fileName:@"classroomPic" successCallback:^(NSMutableArray * _Nonnull fileUrlArray) { NSString *imgUrl = [fileUrlArray lastObject]; [self insertImageWithUrl:imgUrl size:image.size]; } faliure:^(NSError * _Nullable error, NSString * _Nullable descMessaeg) { if (![NSString isEmptyString:descMessaeg]) { [LOADING_MANAGER MBShowAUTOHidingInWindow:descMessaeg]; } }]; } - (void)insertImageWithUrl:(NSString *)imageUrl size:(CGSize)imageSize { WhiteImageInformation *info = [[WhiteImageInformation alloc] init]; info.width = imageSize.width; info.height = imageSize.height; info.uuid = self.roomUuid; [self.room insertImage:info src:imageUrl]; } #pragma mark - TZImagePickerController - (void)pushImagePickerController { TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:MAXPHOTONUMBER columnNumber:COLUMNNUMBER delegate:self]; #pragma mark - 四类个性化设置,这些参数都可以不传,此时会走默认设置 imagePickerVc.isSelectOriginalPhoto = NO; // 1.设置目前已经选中的图片数组 imagePickerVc.selectedAssets = self.imageAsset; // 目前已经选中的图片数组 imagePickerVc.allowTakePicture = YES; // 在内部显示拍照按钮 // 2. Set the appearance // 2. 在这里设置imagePickerVc的外观 [imagePickerVc.navigationBar setBarTintColor:THEMECOLOR]; // 3. Set allow picking video & photo & originalPhoto or not // 3. 设置是否可以选择视频/图片/原图 imagePickerVc.allowPickingVideo = NO; imagePickerVc.allowPickingImage = YES; imagePickerVc.allowPickingOriginalPhoto = NO; imagePickerVc.allowCrop = NO; imagePickerVc.needCircleCrop = NO; imagePickerVc.showSelectBtn = YES; NSInteger left = 30; NSInteger widthHeight = kScreenWidth - 2 * left; NSInteger top = (kScreenHeight - widthHeight) / 2; imagePickerVc.cropRect = CGRectMake(left, top, widthHeight, widthHeight); // 4. 照片排列按修改时间升序 imagePickerVc.sortAscendingByModificationDate = NO; #pragma mark - 到这里为止 // You can get the photos by block, the same as by delegate. // 你可以通过block或者代理,来得到用户选择的照片. [imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray *photos, NSArray *assets, BOOL isSelectOriginalPhoto) { // 赋值 [self evaluateWithChooseImage:[photos lastObject]]; }]; imagePickerVc.modalPresentationStyle = UIModalPresentationFullScreen; [[self getViewController] presentViewController:imagePickerVc animated:YES completion:nil]; } #pragma mark - UIImagePickerController - (void)takePhoto { AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; if ((authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) && kiOS7Later) { [KSNormalAlertView ks_showAlertWithTitle:@"请在iPhone的""设置-隐私-相机""中允许访问相机" leftTitle:@"取消" rightTitle:@"设置" inView:self cancel:^{ } confirm:^{ [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; }]; } else if (authStatus == AVAuthorizationStatusNotDetermined) { // 防止用户首次拍照拒绝授权时相机页黑屏 [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { if (granted) { dispatch_async(dispatch_get_main_queue(), ^{ [self takePhoto]; }); } }]; } else if ([PHPhotoLibrary authorizationStatus] == 2) { // 已被拒绝,没有相册权限,将无法保存拍的照片 [KSNormalAlertView ks_showAlertWithTitle:@"请在iPhone的""设置-隐私-相册""中允许访问相册" leftTitle:@"取消" rightTitle:@"设置" inView:self cancel:^{ } confirm:^{ [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; }]; } else if ([PHPhotoLibrary authorizationStatus] == 0) { // 未请求过相册权限 [[TZImageManager manager] requestAuthorizationWithCompletion:^{ [self takePhoto]; }]; } else { // 调用相机 UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera; if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) { self.imagePickerVc.sourceType = sourceType; if(kiOS8Later) { _imagePickerVc.modalPresentationStyle = UIModalPresentationFullScreen; } _imagePickerVc.modalPresentationStyle = UIModalPresentationFullScreen; [[self getViewController] presentViewController:_imagePickerVc animated:YES completion:nil]; } else { NSLog(@"模拟器中无法打开照相机,请在真机中使用"); } } } // 外部拍照进入的方法 - (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { [picker dismissViewControllerAnimated:YES completion:nil]; NSString *type = [info objectForKey:UIImagePickerControllerMediaType]; if ([type isEqualToString:@"public.image"]) { TZImagePickerController *tzImagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:MAXPHOTONUMBER delegate:self]; tzImagePickerVc.allowCrop = YES; tzImagePickerVc.needCircleCrop = NO; tzImagePickerVc.showSelectBtn = YES; tzImagePickerVc.sortAscendingByModificationDate = NO; [tzImagePickerVc showProgressHUD]; UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage]; // save photo and get asset / 保存图片,获取到asset [[TZImageManager manager] savePhotoWithImage:image completion:^(PHAsset *asset,NSError *error){ if (error) { // 如果保存失败,基本是没有相册权限导致的... [tzImagePickerVc hideProgressHUD]; NSLog(@"图片保存失败 %@",error); [KSNormalAlertView ks_showAlertWithTitle:@"请在iPhone的""设置-隐私-相册""中允许访问相册" leftTitle:@"取消" rightTitle:@"设置" inView:self cancel:^{ } confirm:^{ [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; }]; } else { TZAssetModel *assetModel = [[TZImageManager manager] createModelWithAsset:asset]; TZImagePickerController *imagePicker = [[TZImagePickerController alloc] initCropTypeWithAsset:assetModel.asset photo:image completion:^(UIImage *cropImage, id asset) { // 回调 [self evaluateWithChooseImage:cropImage]; }]; imagePicker.allowPickingImage = YES; imagePicker.allowCrop = YES; imagePicker.needCircleCrop = NO; NSInteger left = 30; NSInteger widthHeight = kScreenWidth - 2 * left; NSInteger top = (kScreenHeight - widthHeight) / 2; imagePicker.cropRect = CGRectMake(left, top, widthHeight, widthHeight); imagePicker.modalPresentationStyle = UIModalPresentationFullScreen; [[self getViewController] presentViewController:imagePicker animated:YES completion:nil]; } }]; } } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { if ([picker isKindOfClass:[UIImagePickerController class]]) { [picker dismissViewControllerAnimated:YES completion:nil]; } } #pragma mark - getter - (NSMutableArray *)imageArray { if (!_imageArray) { _imageArray = [NSMutableArray array]; } return _imageArray; } - (NSMutableArray *)imageAsset { if (!_imageAsset) { _imageAsset = [NSMutableArray array]; } return _imageAsset; } - (UIImagePickerController *)imagePickerVc { if (_imagePickerVc == nil) { _imagePickerVc = [[UIImagePickerController alloc] init]; _imagePickerVc.delegate = self; // set appearance / 改变相册选择页的导航栏外观 // _imagePickerVc.navigationBar.barTintColor = THEMECOLOR; // _imagePickerVc.navigationBar.tintColor = THEMECOLOR; UIBarButtonItem *tzBarItem, *BarItem; if (kiOS9Later) { tzBarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[TZImagePickerController class]]]; BarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UIImagePickerController class]]]; } else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" tzBarItem = [UIBarButtonItem appearanceWhenContainedIn:[TZImagePickerController class], nil]; BarItem = [UIBarButtonItem appearanceWhenContainedIn:[UIImagePickerController class], nil]; #pragma clang diagnostic pop } NSDictionary *titleTextAttributes = [tzBarItem titleTextAttributesForState:UIControlStateNormal]; [BarItem setTitleTextAttributes:titleTextAttributes forState:UIControlStateNormal]; } return _imagePickerVc; } - (UIViewController *)getViewController { for (UIView *view = self; view; view = view.superview) { UIResponder *nextResponder = [view nextResponder]; if ([nextResponder isKindOfClass:[UIViewController class]]) { return (UIViewController *)nextResponder; } } return nil; } /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ @end