2023年7月25日发(作者:)
AVCaptureSession部分⽤法AVCaptureSession阻塞主线程问题前阵⼦程序中出现了⼀个奇怪的 bug,在 iOS 系统上,页⾯弹出的时候会卡很久,相机始终⿊屏,⼤概6-7秒钟,跟踪具体每个步骤花费时间的时候发现在viewWillDisappear:中开销最⼤,这其中只调⽤了⼀个相机关闭的代码:if ([[raManager session] isRunning]) { [[raManager session] stopRunning];}仔细看了⽂档之后,发现问题出在stopRunning这⾥,苹果⽂档描述如下:Clients invoke -stopRunning to stop the flow of data from inputs to outputs connected to
the AVCaptureSession instance. This call blocks until the session object has completelystopped.重点是这个函数在 session 完全停⽌下来之前会始终阻塞线程, 同样的,在startRunning中:Clients invoke -startRunning to start the flow of data from inputs to outputs connected to
the AVCaptureSession instance. This call blocks until the session object has completelystarted up or failed. A failure to start running is reported through the AVCaptureSessionRuntimeErrorNotificationmechanism.因此这⾥必须放在后台线程中处理,否则,就会导致界⾯不响应,iOS8之后应该在这⾥做了优化,即使放在主线程做也没有很卡顿的现象,但 iOS7中,尤其是测试设备为4s,界⾯卡死问题很严重。开启和关闭相机部分代码改为:dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ DDLogDebug(@"Function: %s,line : %d 开启相机",__FUNCTION__,__LINE__); [[raManager session] startRunning]; });
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { DDLogDebug(@"Function: %s,line : %d 关闭相机",__FUNCTION__,__LINE__); if ([[raManager session] isRunning]) { [[raManager session] stopRunning]; } });这⾥除了使⽤系统提供的队列以外还可以⾃⼰创建 FIFO 类型后台线程进⾏管理,包括切换前后摄像头、改变闪光灯模式、切换拍照和录像等,都可以放⼊⼦线程操作。相机前后台切换问题另⼀个问题与前后台切花相关,项⽬中在程序进⼊后台时有这么⼀段代码:[self performSelector:@selector(startRunningSession) withObject:nil afterDelay:0.5];当时我很奇怪,这⾥为什么要加延时呢?进⼊到前台时不是应该直接开启相机吗?于是我直接把这⾥改成了:[self startRunningSession];没过多久,问题出现了,多次切换前后台之后发现,相机始终⿊屏,这时,进⼊后台再回来,问题解决了,仔细加了 log 之后发现,出现⿊屏的时候,确实也正确调⽤了启动 session,但是并没有收到系统相机启动成功的消息,反⽽收到了两次相机关闭的通知。那么之前代码中加了0.5秒延时的原因也就清楚了,是为了等待系统关闭相机之后,再调⽤开启相机,以免相机启动失败,但这种⽅式真的合理吗?其实并没有解决本质问题,如果0.5秒钟的时间并没有完全关闭系统相机呢?这⾥仍然会出现⿊屏问题。于是继续查看系统⽂档,发现系统的 sampleCode AVCam-iOS中并没有专门⽤于前后台处理的逻辑,原来这⾥并不需要我们⾃⼰⼿动管理相机,系统会⾃动根据程序状态来判断是否需要关闭或者开启相机,如果按 home 进⼊UIApplicationStateBackground 状态,那么系统⾃动关闭相机并在进⼊UIApplicationStateActive状态时开启相机;如果是进⼊UIApplicationStateInactive状态,例如,双击 home 调出任务管理器,这时,相机并没有被关闭,仍然能够看到 preview 画⾯。我们在程序切换前后台时,仅需要捕获相继开启或者关闭的通知来刷新界⾯即可,否则可能会由于快速开启切换前后台导致系统相机执⾏命令错乱,⽆法正确启动相机。总结AVCaptureSession 中绝⼤部分操作需要在后台线程完成,最好使⽤⼀个 FIFO 的队列来进⾏操作前后台切换时,⽆需⼿动管理 CaptureSession
发布者:admin,转转请注明出处:http://www.yc00.com/web/1690227692a317896.html
评论列表(0条)