replaykit是ios9後出的,所以replaykit支持ios9+錄屏,
//開始錄屏 - (void)StartRecoder { //將開啟錄屏功能的代碼放在主線程執行 dispatch_async(dispatch_get_main_queue(), ^{ if ([[RPScreenRecorder sharedRecorder] isAvailable] && [self isSystemVersionOk]) { //判斷硬件和ios版本是否支持錄屏 NSLog(@"支持ReplayKit錄制"); //這是錄屏的類 RPScreenRecorder* recorder = RPScreenRecorder.sharedRecorder; recorder.delegate = self; __weak typeof (self)weakSelf = self; MBProgressHUD *hud; hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; hud.maskView.hidden = NO; hud.labelText = NSLocalizedString(@"正在啟動錄屏...", @"HUD loading title"); [self delay:8 execute:^{ if (hud.hidden == NO) { hud.hidden = YES; [self showAlert:@"錄屏啟動失敗" andMessage:@"請重試"]; } }]; //在此可以設置是否允許麥克風(傳YES即是使用麥克風,傳NO則不是用麥克風) recorder.microphoneEnabled = YES; recorder.cameraEnabled = YES; //開起錄屏功能 [recorder startRecordingWithHandler:^(NSError * _Nullable error) { //在此可以設置是否允許麥克風(傳YES即是使用麥克風,傳NO則不是用麥克風)(ios 後被廢棄了 下面的這個開始錄屏) // [recorder startRecordingWithMicrophoneEnabled:YES handler:^(NSError * _Nullable error) { recorder.microphoneEnabled = YES; if (error) { hud.hidden = YES; IsDecoderScreen = 0; MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; hud.mode = MBProgressHUDModeText; hud.labelText = @"錄屏啟動失敗!\n請重試"; hud.margin = 10.f; hud.yOffset = 150.f; hud.removeFromSuperViewOnHide = YES; [hud hide:YES afterDelay:4]; NSLog(@"========%@",error.description); _DecoderButton.selected = NO; } else { if (recorder.recording) { _DecoderButton.selected = YES; //記錄是否開始錄屏 系統也有一個再帶的檢測是否在錄屏的方法 (@property (nonatomic, readonly, getter=isRecording) BOOL recording;) IsDecoderScreen = 1; hud.hidden = YES; } } }]; } else { [self showAlert:@"設備不支持錄制" andMessage:@"升級ios系統"]; return; } }); }
//結束錄屏 - (void)stopDecoder { __weak typeof (self)weakSelf = self; [[RPScreenRecorder sharedRecorder] stopRecordingWithHandler:^(RPPreviewViewController *previewViewController, NSError * error){ _RPPreview = previewViewController; if (error) { NSLog(@"這裡關閉有誤%@",error.description); } else { [_RPPreview setPreviewControllerDelegate:self]; _DecoderButton.selected = NO; IsDecoderScreen = 0; //在結束錄屏時顯示預覽畫面 [weakSelf showVideoPreviewController:_RPPreview withAnimation:YES]; } }]; }
//顯示視頻預覽頁面,animation=是否要動畫顯示 - (void)showVideoPreviewController:(RPPreviewViewController *)previewController withAnimation:(BOOL)animation { __weak typeof (self) weakSelf = self; //UI需要放到主線程 dispatch_async(dispatch_get_main_queue(), ^{ CGRect rect = previewController.view.frame; if (animation) { rect.origin.x += rect.size.width; previewController.view.frame = rect; rect.origin.x -= rect.size.width; [UIView animateWithDuration:0.3 animations:^(){ previewController.view.frame = rect; } completion:^(BOOL finished){ }]; } else { previewController.view.frame = rect; } [weakSelf.view addSubview:previewController.view]; [weakSelf addChildViewController:previewController]; }); }
//關閉視頻預覽頁面,animation=是否要動畫顯示 - (void)hideVideoPreviewController:(RPPreviewViewController *)previewController withAnimation:(BOOL)animation { //UI需要放到主線程 dispatch_async(dispatch_get_main_queue(), ^{ CGRect rect = previewController.view.frame; if (animation) { rect.origin.x += rect.size.width; [UIView animateWithDuration:0.3 animations:^(){ previewController.view.frame = rect; } completion:^(BOOL finished){ //移除頁面 [previewController.view removeFromSuperview]; [previewController removeFromParentViewController]; }]; } else { //移除頁面 [previewController.view removeFromSuperview]; [previewController removeFromParentViewController]; } }); }
#pragma mark -RPPreviewViewControllerDelegate //關閉的回調 - (void)previewControllerDidFinish:(RPPreviewViewController *)previewController { if (isSave == 1) { //這個地方我添加了一個延時,我發現這樣保存不到系統相冊的情況好多了 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self hideVideoPreviewController:_RPPreview withAnimation:YES]; }); isSave = 0; }else { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertAction *queding = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self hideVideoPreviewController:_RPPreview withAnimation:YES]; // dispatch_async(dispatch_get_main_queue(), ^{ // [weakSelf.RPPreview dismissViewControllerAnimated:YES completion:nil]; // }); isSave = 0; }]; UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"錄制未保存\n確定要取消嗎" preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:actionCancel]; [alert addAction:queding]; [self presentViewController:alert animated:NO completion:nil]; }); } } //選擇了某些功能的回調(如分享和保存) - (void)previewController:(RPPreviewViewController *)previewController didFinishWithActivityTypes:(NSSet*)activityTypes { __weak typeof (self)weakSelf = self; if ([activityTypes containsObject:@"com.apple.UIKit.activity.SaveToCameraRoll"]) { isSave = 1; NSLog(@"***************************"); //這個地方我延時執行,等預覽畫面移除後再顯示提示框 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf showAlert:@"保存成功" andMessage:@"已經保存到系統相冊"]; }); }); } if ([activityTypes containsObject:@"com.apple.UIKit.activity.CopyToPasteboard"]) { dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf showAlert:@"復制成功" andMessage:@"已經復制到粘貼板"]; }); } }
#pragma mark ====RPScreenDelegate=== - (void)screenRecorderDidChangeAvailability:(RPScreenRecorder *)screenRecorder { // [screenRecorder addObserver:self forKeyPath:@"recording" options:NSKeyValueObservingOptionNew context:nil]; // [screenRecorder setValue:@"1" forKey:@"recording"]; NSLog(@" delegate ======%@",screenRecorder); } - (void)screenRecorder:(RPScreenRecorder *)screenRecorder didStopRecordingWithError:(NSError *)error previewViewController:(nullable RPPreviewViewController *)previewViewController { [_RPPreview setPreviewControllerDelegate:self]; _DecoderButton.selected = NO; IsDecoderScreen = 0; [self showVideoPreviewController:_RPPreview withAnimation:YES]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void *)context { if ([keyPath isEqualToString:@"recording"]) { NSLog(@"keyPath === %@",object); if ([change valueForKey:@"recording"] == 0) { NSLog(@"可以錄制"); }else { NSLog(@"++++++++++++不可以"); } } }
//顯示彈框提示 - (void)showAlert:(NSString *)title andMessage:(NSString *)message { if (!title) { title = @""; } if (!message) { message = @""; } UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleCancel handler:nil]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:actionCancel]; [self presentViewController:alert animated:NO completion:nil]; }
//判斷對應系統版本是否支持ReplayKit - (BOOL)isSystemVersionOk { if ([[UIDevice currentDevice].systemVersion floatValue] < 9.0) { return NO; } else { return YES; } }