iOS-視頻錄制

最近開發(fā)中遇到一個(gè)需求刨摩,就是想微信那樣錄制一個(gè)小視頻寺晌,然后在錄制視頻的圖層上播放,然后發(fā)布到朋友圈码邻,無聲播放折剃,但有滾動(dòng)起來不影響性能。一開始接到這個(gè)需求的時(shí)候我是很興奮的像屋,可以好好研究一番 AVFoundation 的東西了。但是在研究中不斷的高潮迭起边篮,也是讓我心力交瘁呀己莺。但是奏甫,做程序猿的成長(zhǎng)就是這樣的嘛。題外話了凌受,好了阵子,今天我們就說一下怎么用AVCaptureSession+AVCaptureMovieFileOutput來錄制視頻,并通過AVAssetExportSeeion手段來壓縮視頻并轉(zhuǎn)換為 MP4 格式

一開始我們要了解一下 AVFoundation 做視頻的類應(yīng)該有那些胜蛉,并且他們有什么用呢挠进?

AVCaptureSession

AVCaptureSession:媒體(音、視頻)捕獲會(huì)話誊册,負(fù)責(zé)把捕獲的音視頻數(shù)據(jù)輸出到輸出設(shè)備中领突。一個(gè)AVCaptureSession可以有多個(gè)輸入輸出。AVCaptureDevice:輸入設(shè)備案怯,包括麥克風(fēng)君旦、攝像頭,通過該對(duì)象可以設(shè)置物理設(shè)備的一些屬性(例如相機(jī)聚焦嘲碱、白平衡等)金砍。AVCaptureDeviceInput:設(shè)備輸入數(shù)據(jù)管理對(duì)象,可以根據(jù)AVCaptureDevice創(chuàng)建對(duì)應(yīng)的AVCaptureDeviceInput對(duì)象麦锯,該對(duì)象將會(huì)被添加到AVCaptureSession中管理恕稠。AVCaptureVideoPreviewLayer:相機(jī)拍攝預(yù)覽圖層,是CALayer的子類扶欣,使用該對(duì)象可以實(shí)時(shí)查看拍照或視頻錄制效果谱俭,創(chuàng)建該對(duì)象需要指定對(duì)應(yīng)的AVCaptureSession對(duì)象。AVCaptureOutput:輸出數(shù)據(jù)管理對(duì)象宵蛀,用于接收各類輸出數(shù)據(jù)昆著,通常使用對(duì)應(yīng)的子類AVCaptureAudioDataOutput、AVCaptureStillImageOutput术陶、AVCaptureVideoDataOutput凑懂、AVCaptureFileOutput, 該對(duì)象將會(huì)被添加到AVCaptureSession中管理。 注意:前面幾個(gè)對(duì)象的輸出數(shù)據(jù)都是NSData類型梧宫,而AVCaptureFileOutput代表數(shù)據(jù)以文件形式輸出接谨,類似的,AVCcaptureFileOutput也不會(huì)直接創(chuàng)建使用塘匣,通常會(huì)使用其子類:AVCaptureAudioFileOutput脓豪、AVCaptureMovieFileOutput。當(dāng)把一個(gè)輸入或者輸出添加到AVCaptureSession之后AVCaptureSession就會(huì)在所有相符的輸入忌卤、輸出設(shè)備之間 建立連接(AVCaptionConnection)扫夜。

那么建立視頻拍攝的步驟如下 :

1.創(chuàng)建AVCaptureSession對(duì)象。

// 創(chuàng)建會(huì)話 (AVCaptureSession) 對(duì)象。_captureSession = [[AVCaptureSessionalloc] init];if([_captureSession canSetSessionPreset:AVCaptureSessionPreset640x480]) {// 設(shè)置會(huì)話的 sessionPreset 屬性, 這個(gè)屬性影響視頻的分辨率[_captureSession setSessionPreset:AVCaptureSessionPreset640x480];}

2.使用AVCaptureDevice的靜態(tài)方法獲得需要使用的設(shè)備笤闯,例如拍照和錄像就需要獲得攝像頭設(shè)備堕阔,錄音就要獲得麥克風(fēng)設(shè)備。

// 獲取攝像頭輸入設(shè)備颗味, 創(chuàng)建 AVCaptureDeviceInput 對(duì)象// 在獲取攝像頭的時(shí)候超陆,攝像頭分為前后攝像頭,我們創(chuàng)建了一個(gè)方法通過用攝像頭的位置來獲取攝像頭AVCaptureDevice*videoCaptureDevice = [selfgetCameraDeviceWithPosition:AVCaptureDevicePositionBack];if(!captureDevice) {NSLog(@"---- 取得后置攝像頭時(shí)出現(xiàn)問題---- ");return;}// 添加一個(gè)音頻輸入設(shè)備// 直接可以拿數(shù)組中的數(shù)組中的第一個(gè)AVCaptureDevice*audioCaptureDevice = [[AVCaptureDevicedevicesWithMediaType:AVMediaTypeAudio] firstObject];

3.利用輸入設(shè)備AVCaptureDevice初始化AVCaptureDeviceInput對(duì)象浦马。

// 視頻輸入對(duì)象// 根據(jù)輸入設(shè)備初始化輸入對(duì)象时呀,用戶獲取輸入數(shù)據(jù)_videoCaptureDeviceInput = [[AVCaptureDeviceInputalloc] initWithDevice:captureDevice error:&error];if(error) {NSLog(@"---- 取得設(shè)備輸入對(duì)象時(shí)出錯(cuò) ------ %@",error);return;}//? 音頻輸入對(duì)象//根據(jù)輸入設(shè)備初始化設(shè)備輸入對(duì)象,用于獲得輸入數(shù)據(jù)_audioCaptureDeviceInput = [[AVCaptureDeviceInputalloc] initWithDevice:audioCaptureDevice error:&error];if(error) {NSLog(@"取得設(shè)備輸入對(duì)象時(shí)出錯(cuò) ------ %@",error);return;}

4.初始化輸出數(shù)據(jù)管理對(duì)象晶默,如果要拍照就初始化AVCaptureStillImageOutput對(duì)象;如果拍攝視頻就初始化AVCaptureMovieFileOutput對(duì)象荤胁。

// 拍攝視頻輸出對(duì)象// 初始化輸出設(shè)備對(duì)象瞧预,用戶獲取輸出數(shù)據(jù)_caputureMovieFileOutput = [[AVCaptureMovieFileOutputalloc] init];

5.將數(shù)據(jù)輸入對(duì)象AVCaptureDeviceInput、數(shù)據(jù)輸出對(duì)象AVCaptureOutput添加到媒體會(huì)話管理對(duì)象AVCaptureSession中仅政。

// 將視頻輸入對(duì)象添加到會(huì)話 (AVCaptureSession) 中if([_captureSession canAddInput:_videoCaptureDeviceInput]) {? ? [_captureSession addInput:_videoCaptureDeviceInput];}// 將音頻輸入對(duì)象添加到會(huì)話 (AVCaptureSession) 中if([_captureSession canAddInput:_captureDeviceInput]) {? ? [_captureSession addInput:audioCaptureDeviceInput];AVCaptureConnection*captureConnection = [_caputureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];// 標(biāo)識(shí)視頻錄入時(shí)穩(wěn)定音頻流的接受垢油,我們這里設(shè)置為自動(dòng)if([captureConnection isVideoStabilizationSupported]) {? ? ? ? captureConnection.preferredVideoStabilizationMode=AVCaptureVideoStabilizationModeAuto;? ? }}

6.創(chuàng)建視頻預(yù)覽圖層AVCaptureVideoPreviewLayer并指定媒體會(huì)話,添加圖層到顯示容器中圆丹,調(diào)用AVCaptureSession的startRuning方法開始捕獲滩愁。

// 通過會(huì)話 (AVCaptureSession) 創(chuàng)建預(yù)覽層_captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayeralloc] initWithSession:_captureSession];// 顯示在視圖表面的圖層CALayer*layer =self.viewContrain.layer;layer.masksToBounds=true;_captureVideoPreviewLayer.frame= layer.bounds;_captureVideoPreviewLayer.masksToBounds=true;_captureVideoPreviewLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;//填充模式[layer addSublayer:_captureVideoPreviewLayer];// 讓會(huì)話(AVCaptureSession)勾搭好輸入輸出,然后把視圖渲染到預(yù)覽層上[_captureSession startRunning];

7.將捕獲的音頻或視頻數(shù)據(jù)輸出到指定文件辫封。

創(chuàng)建一個(gè)拍攝的按鈕硝枉,當(dāng)我們點(diǎn)擊這個(gè)按鈕就會(huì)觸發(fā)視頻錄制,并將這個(gè)錄制的視頻放到 temp 文件夾中- (IBAction)takeMovie:(id)sender {[(UIButton*)sender setSelected:![(UIButton*)sender isSelected]];if([(UIButton*)sender isSelected]) {AVCaptureConnection*captureConnection=[self.caputureMovieFileOutputconnectionWithMediaType:AVMediaTypeVideo];// 開啟視頻防抖模式AVCaptureVideoStabilizationModestabilizationMode =AVCaptureVideoStabilizationModeCinematic;if([self.captureDeviceInput.device.activeFormatisVideoStabilizationModeSupported:stabilizationMode]) {? ? ? ? [captureConnection setPreferredVideoStabilizationMode:stabilizationMode];? ? }//如果支持多任務(wù)則則開始多任務(wù)if([[UIDevicecurrentDevice] isMultitaskingSupported]) {self.backgroundTaskIdentifier= [[UIApplicationsharedApplication] beginBackgroundTaskWithExpirationHandler:nil];? ? }// 預(yù)覽圖層和視頻方向保持一致,這個(gè)屬性設(shè)置很重要倦微,如果不設(shè)置妻味,那么出來的視頻圖像可以是倒向左邊的。captureConnection.videoOrientation=[self.captureVideoPreviewLayerconnection].videoOrientation;// 設(shè)置視頻輸出的文件路徑欣福,這里設(shè)置為 temp 文件NSString*outputFielPath=[NSTemporaryDirectory() stringByAppendingString:MOVIEPATH];// 路徑轉(zhuǎn)換成 URL 要用這個(gè)方法责球,用 NSBundle 方法轉(zhuǎn)換成 URL 的話可能會(huì)出現(xiàn)讀取不到路徑的錯(cuò)誤NSURL*fileUrl=[NSURLfileURLWithPath:outputFielPath];// 往路徑的 URL 開始寫入錄像 Buffer ,邊錄邊寫[self.caputureMovieFileOutputstartRecordingToOutputFileURL:fileUrl recordingDelegate:self];}else{// 取消視頻拍攝[self.caputureMovieFileOutputstopRecording];? ? [self.captureSessionstopRunning];? ? [selfcompleteHandle];}}

當(dāng)然我們錄制的開始與結(jié)束都是有監(jiān)聽方法的,AVCaptureFileOutputRecordingDelegate這個(gè)代理里面就有我們想要做的

- (void)captureOutput:(AVCaptureFileOutput*)captureOutput didStartRecordingToOutputFileAtURL:(NSURL*)fileURL fromConnections:(NSArray*)connections{NSLog(@"---- 開始錄制 ----");}- (void)captureOutput:(AVCaptureFileOutput*)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL*)outputFileURL fromConnections:(NSArray*)connections error:(NSError*)error{NSLog(@"---- 錄制結(jié)束 ----");}

到此拓劝,我們錄制視頻就結(jié)束了雏逾,那么是不是我們錄制好了視頻,就可以馬上把這個(gè)視頻上傳給服務(wù)器分享給你的小伙伴們看了呢郑临?

我們可以用如下方法測(cè)試一下我們錄制出來的視頻有多大 (m)

- (CGFloat)getfileSize:(NSString*)path{NSDictionary*outputFileAttributes = [[NSFileManagerdefaultManager] attributesOfItemAtPath:path error:nil];NSLog(@"file size: %f", (unsignedlonglong)[outputFileAttributes fileSize]/1024.00/1024.00);return(CGFloat)[outputFileAttributes fileSize]/1024.00/1024.00;}

個(gè)人在這里做過測(cè)試栖博,錄制了 10s 的小視頻得到的文件大小為 4.1M 左右,而且我用的分辨率還是640x480。厢洞。仇让。很無語(yǔ)了是不是典奉?

如果我們錄制的視頻,錄制完成后要與服務(wù)器進(jìn)行必要的上傳妹孙,那么秋柄,我們肯定不能把這個(gè)剛剛錄制出來的視頻上傳給服務(wù)器的获枝,我們有必要對(duì)這個(gè)視頻進(jìn)行壓縮了蠢正。那么我們的壓縮方法,就要用到AVAssetExportSeeion這個(gè)類了省店。

// 這里我們創(chuàng)建一個(gè)按鈕嚣崭,當(dāng)點(diǎn)擊這個(gè)按鈕,我們就會(huì)調(diào)用壓縮視頻的方法懦傍,然后再去重新計(jì)算大小雹舀,這樣就會(huì)跟未被壓縮前的大小有個(gè)明顯的對(duì)比了// 壓縮視頻- (IBAction)compressVideo:(id)sender{NSString*cachePath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) lastObject];NSString*savePath=[cachePath stringByAppendingPathComponent:MOVIEPATH];NSURL*saveUrl=[NSURLfileURLWithPath:savePath];// 通過文件的 url 獲取到這個(gè)文件的資源AVURLAsset*avAsset = [[AVURLAssetalloc] initWithURL:saveUrl options:nil];// 用 AVAssetExportSession 這個(gè)類來導(dǎo)出資源中的屬性NSArray*compatiblePresets = [AVAssetExportSessionexportPresetsCompatibleWithAsset:avAsset];// 壓縮視頻if([compatiblePresets containsObject:AVAssetExportPresetLowQuality]) {// 導(dǎo)出屬性是否包含低分辨率// 通過資源(AVURLAsset)來定義 AVAssetExportSession,得到資源屬性來重新打包資源 (AVURLAsset, 將某一些屬性重新定義AVAssetExportSession*exportSession = [[AVAssetExportSessionalloc] initWithAsset:avAsset presetName:AVAssetExportPresetLowQuality];// 設(shè)置導(dǎo)出文件的存放路徑NSDateFormatter*formatter = [[NSDateFormatteralloc] init];? ? [formatter setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];NSDate*date = [[NSDatealloc] init];NSString*outPutPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,true) lastObject] stringByAppendingPathComponent:[NSStringstringWithFormat:@"output-%@.mp4",[formatter stringFromDate:date]]];? ? exportSession.outputURL= [NSURLfileURLWithPath:outPutPath];// 是否對(duì)網(wǎng)絡(luò)進(jìn)行優(yōu)化exportSession.shouldOptimizeForNetworkUse=true;// 轉(zhuǎn)換成MP4格式exportSession.outputFileType=AVFileTypeMPEG4;// 開始導(dǎo)出,導(dǎo)出后執(zhí)行完成的block[exportSession exportAsynchronouslyWithCompletionHandler:^{// 如果導(dǎo)出的狀態(tài)為完成if([exportSession status] ==AVAssetExportSessionStatusCompleted) {dispatch_async(dispatch_get_main_queue(), ^{// 更新一下顯示包的大小self.videoSize.text= [NSStringstringWithFormat:@"%f MB",[selfgetfileSize:outPutPath]];? ? ? ? ? ? });? ? ? ? }? ? }];}}

經(jīng)過我們的壓縮粗俱,這個(gè)時(shí)候10s 的 4M 視頻就只剩下不夠 1M 了说榆。

以下是一些擴(kuò)展

自動(dòng)閃光燈開啟

- (IBAction)flashAutoClick:(UIButton*)sender {? ? [selfsetFlashMode:AVCaptureFlashModeAuto];? ? [selfsetFlashModeButtonStatus];}

打開閃光燈

- (IBAction)flashOnClick:(UIButton*)sender {? ? [selfsetFlashMode:AVCaptureFlashModeOn];? ? [selfsetFlashModeButtonStatus];}

關(guān)閉閃光燈

- (IBAction)flashOffClick:(UIButton*)sender {? ? [selfsetFlashMode:AVCaptureFlashModeOff];? ? [selfsetFlashModeButtonStatus];}

通知

/**

*? 給輸入設(shè)備添加通知

*/-(void)addNotificationToCaptureDevice:(AVCaptureDevice*)captureDevice{//注意添加區(qū)域改變捕獲通知必須首先設(shè)置設(shè)備允許捕獲[selfchangeDeviceProperty:^(AVCaptureDevice*captureDevice) {? ? captureDevice.subjectAreaChangeMonitoringEnabled=YES;}];NSNotificationCenter*notificationCenter= [NSNotificationCenterdefaultCenter];//捕獲區(qū)域發(fā)生改變[notificationCenter addObserver:selfselector:@selector(areaChange:) name:AVCaptureDeviceSubjectAreaDidChangeNotificationobject:captureDevice];}-(void)removeNotificationFromCaptureDevice:(AVCaptureDevice*)captureDevice{NSNotificationCenter*notificationCenter= [NSNotificationCenterdefaultCenter];[notificationCenter removeObserver:selfname:AVCaptureDeviceSubjectAreaDidChangeNotificationobject:captureDevice];}/**

*? 移除所有通知

*/-(void)removeNotification{NSNotificationCenter*notificationCenter= [NSNotificationCenterdefaultCenter];? ? [notificationCenter removeObserver:self];}-(void)addNotificationToCaptureSession:(AVCaptureSession*)captureSession{NSNotificationCenter*notificationCenter= [NSNotificationCenterdefaultCenter];//會(huì)話出錯(cuò)[notificationCenter addObserver:selfselector:@selector(sessionRuntimeError:) name:AVCaptureSessionRuntimeErrorNotificationobject:captureSession];}/**

*? 設(shè)備連接成功

*

*? @param notification 通知對(duì)象

*/-(void)deviceConnected:(NSNotification*)notification{NSLog(@"設(shè)備已連接...");}/**

*? 設(shè)備連接斷開

*

*? @param notification 通知對(duì)象

*/-(void)deviceDisconnected:(NSNotification*)notification{NSLog(@"設(shè)備已斷開.");}/**

*? 捕獲區(qū)域改變

*

*? @param notification 通知對(duì)象

*/-(void)areaChange:(NSNotification*)notification{NSLog(@"捕獲區(qū)域改變...");}/**

*? 會(huì)話出錯(cuò)

*

*? @param notification 通知對(duì)象

*/-(void)sessionRuntimeError:(NSNotification*)notification{NSLog(@"會(huì)話發(fā)生錯(cuò)誤.");

}

私有方法

/**

*? 取得指定位置的攝像頭

*

*? @param position 攝像頭位置

*

*? @return 攝像頭設(shè)備

*/-(AVCaptureDevice*)getCameraDeviceWithPosition:(AVCaptureDevicePosition)position{NSArray*cameras= [AVCaptureDevicedevicesWithMediaType:AVMediaTypeVideo];for(AVCaptureDevice*cameraincameras) {if([camera position]==position) {returncamera;? ? ? ? }? ? }returnnil;}/**

*? 改變?cè)O(shè)備屬性的統(tǒng)一操作方法

*

*? @param propertyChange 屬性改變操作

*/-(void)changeDeviceProperty:(PropertyChangeBlock)propertyChange{AVCaptureDevice*captureDevice= [self.captureDeviceInputdevice];NSError*error;//注意改變?cè)O(shè)備屬性前一定要首先調(diào)用lockForConfiguration:調(diào)用完之后使用unlockForConfiguration方法解鎖if([captureDevice lockForConfiguration:&error]) {? ? ? ? propertyChange(captureDevice);? ? ? ? [captureDevice unlockForConfiguration];? ? }else{NSLog(@"設(shè)置設(shè)備屬性過程發(fā)生錯(cuò)誤,錯(cuò)誤信息:%@",error.localizedDescription);? ? }}/**

*? 設(shè)置閃光燈模式

*

*? @param flashMode 閃光燈模式

*/-(void)setFlashMode:(AVCaptureFlashMode)flashMode{? ? [selfchangeDeviceProperty:^(AVCaptureDevice*captureDevice) {if([captureDevice isFlashModeSupported:flashMode]) {? ? ? ? ? ? [captureDevice setFlashMode:flashMode];? ? ? ? }? ? }];}/**

*? 設(shè)置聚焦模式

*

*? @param focusMode 聚焦模式

*/-(void)setFocusMode:(AVCaptureFocusMode)focusMode{? ? [selfchangeDeviceProperty:^(AVCaptureDevice*captureDevice) {if([captureDevice isFocusModeSupported:focusMode]) {? ? ? ? ? ? [captureDevice setFocusMode:focusMode];? ? ? ? }? ? }];}/**

*? 設(shè)置曝光模式

*

*? @param exposureMode 曝光模式

*/-(void)setExposureMode:(AVCaptureExposureMode)exposureMode{? ? [selfchangeDeviceProperty:^(AVCaptureDevice*captureDevice) {if([captureDevice isExposureModeSupported:exposureMode]) {? ? ? ? ? ? [captureDevice setExposureMode:exposureMode];? ? ? ? }? ? }];}/**

*? 設(shè)置聚焦點(diǎn)

*

*? @param point 聚焦點(diǎn)

*/-(void)focusWithMode:(AVCaptureFocusMode)focusMode exposureMode:(AVCaptureExposureMode)exposureMode atPoint:(CGPoint)point{? ? [selfchangeDeviceProperty:^(AVCaptureDevice*captureDevice) {if([captureDevice isFocusModeSupported:focusMode]) {? ? ? ? ? ? [captureDevice setFocusMode:AVCaptureFocusModeAutoFocus];? ? ? ? }if([captureDevice isFocusPointOfInterestSupported]) {? ? ? ? ? ? [captureDevice setFocusPointOfInterest:point];? ? ? ? }if([captureDevice isExposureModeSupported:exposureMode]) {? ? ? ? ? ? [captureDevice setExposureMode:AVCaptureExposureModeAutoExpose];? ? ? ? }if([captureDevice isExposurePointOfInterestSupported]) {? ? ? ? ? ? [captureDevice setExposurePointOfInterest:point];? ? ? ? }? ? }];}/**

*? 添加點(diǎn)按手勢(shì)寸认,點(diǎn)按時(shí)聚焦

*/-(void)addGenstureRecognizer{UITapGestureRecognizer*tapGesture=[[UITapGestureRecognizeralloc]initWithTarget:selfaction:@selector(tapScreen:)];? ? [self.viewContaineraddGestureRecognizer:tapGesture];}-(void)tapScreen:(UITapGestureRecognizer*)tapGesture{CGPointpoint= [tapGesture locationInView:self.viewContainer];//將UI坐標(biāo)轉(zhuǎn)化為攝像頭坐標(biāo)CGPointcameraPoint= [self.captureVideoPreviewLayercaptureDevicePointOfInterestForPoint:point];? ? [selfsetFocusCursorWithPoint:point];? ? [selffocusWithMode:AVCaptureFocusModeAutoFocusexposureMode:AVCaptureExposureModeAutoExposeatPoint:cameraPoint];}/**

*? 設(shè)置閃光燈按鈕狀態(tài)

*/-(void)setFlashModeButtonStatus{AVCaptureDevice*captureDevice=[self.captureDeviceInputdevice];AVCaptureFlashModeflashMode=captureDevice.flashMode;if([captureDevice isFlashAvailable]){self.flashAutoButton.hidden=NO;self.flashOnButton.hidden=NO;self.flashOffButton.hidden=NO;self.flashAutoButton.enabled=YES;self.flashOnButton.enabled=YES;self.flashOffButton.enabled=YES;switch(flashMode) {caseAVCaptureFlashModeAuto:self.flashAutoButton.enabled=NO;break;caseAVCaptureFlashModeOn:self.flashOnButton.enabled=NO;break;caseAVCaptureFlashModeOff:self.flashOffButton.enabled=NO;break;default:break;? ? }}else{self.flashAutoButton.hidden=YES;self.flashOnButton.hidden=YES;self.flashOffButton.hidden=YES;}}/**

*? 設(shè)置聚焦光標(biāo)位置

*

*? @param point 光標(biāo)位置

*/-(void)setFocusCursorWithPoint:(CGPoint)point{self.focusCursor.center=point;self.focusCursor.transform=CGAffineTransformMakeScale(1.5,1.5);self.focusCursor.alpha=1.0;? ? [UIViewanimateWithDuration:1.0animations:^{self.focusCursor.transform=CGAffineTransformIdentity;? ? } completion:^(BOOLfinished) {self.focusCursor.alpha=0;? ? }];}

@end

文/止于浮水(簡(jiǎn)書作者)

原文鏈接:http://www.reibang.com/p/7c57c58c253d/comments/1184468

著作權(quán)歸作者所有签财,轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),并標(biāo)注“簡(jiǎn)書作者”偏塞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末唱蒸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子灸叼,更是在濱河造成了極大的恐慌神汹,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件古今,死亡現(xiàn)場(chǎng)離奇詭異屁魏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)捉腥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門氓拼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人但狭,你說我怎么就攤上這事披诗。” “怎么了立磁?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵呈队,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我唱歧,道長(zhǎng)宪摧,這世上最難降的妖魔是什么粒竖? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮几于,結(jié)果婚禮上蕊苗,老公的妹妹穿的比我還像新娘。我一直安慰自己沿彭,他們只是感情好朽砰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著喉刘,像睡著了一般瞧柔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上睦裳,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天造锅,我揣著相機(jī)與錄音,去河邊找鬼廉邑。 笑死哥蔚,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛛蒙。 我是一名探鬼主播糙箍,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼宇驾!你這毒婦竟也來了倍靡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤课舍,失蹤者是張志新(化名)和其女友劉穎塌西,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筝尾,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捡需,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了筹淫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片站辉。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖损姜,靈堂內(nèi)的尸體忽然破棺而出饰剥,到底是詐尸還是另有隱情,我是刑警寧澤摧阅,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布汰蓉,位于F島的核電站,受9級(jí)特大地震影響棒卷,放射性物質(zhì)發(fā)生泄漏顾孽。R本人自食惡果不足惜祝钢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望若厚。 院中可真熱鬧拦英,春花似錦、人聲如沸测秸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)乞封。三九已至做裙,卻和暖如春岗憋,著一層夾襖步出監(jiān)牢的瞬間肃晚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工仔戈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留关串,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓监徘,卻偏偏與公主長(zhǎng)得像晋修,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凰盔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容