原文链接

AVCaptureSession阻塞主线程问题

前阵子程序中出现了一个奇怪的 bug,在 iOS 系统上,页面弹出的时候会卡很久,相机始终黑屏,大概6-7秒钟,跟踪具体每个步骤花费时间的时候发现在viewWillDisappear:中开销最大,这其中只调用了一个相机关闭的代码:

if ([[self.avCameraManager session] isRunning]) {
[[self.avCameraManager 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 completely

stopped.

重点是这个函数在 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 completely

started up or failed. A failure to start running is reported through the AVCaptureSessionRuntimeErrorNotification

mechanism.

因此这里必须放在后台线程中处理,否则,就会导致界面不响应,iOS8之后应该在这里做了优化,即使放在主线程做也没有很卡顿的现象,但 iOS7中,尤其是测试设备为4s,界面卡死问题很严重。

开启和关闭相机部分代码改为:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
DDLogDebug(@"Function: %s,line : %d 开启相机",__FUNCTION__,__LINE__);
[[self.avCameraManager session] startRunning];
}); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
DDLogDebug(@"Function: %s,line : %d 关闭相机",__FUNCTION__,__LINE__);
if ([[self.avCameraManager session] isRunning]) {
[[self.avCameraManager 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

AVCaptureSession部分用法的更多相关文章

  1. EditText 基本用法

    title: EditText 基本用法 tags: EditText,编辑框,输入框 --- EditText介绍: EditText 在开发中也是经常用到的控件,也是一个比较必要的组件,可以说它是 ...

  2. jquery插件的用法之cookie 插件

    一.使用cookie 插件 插件官方网站下载地址:http://plugins.jquery.com/cookie/ cookie 插件的用法比较简单,直接粘贴下面代码示例: //生成一个cookie ...

  3. Java中的Socket的用法

                                   Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...

  4. [转载]C#中MessageBox.Show用法以及VB.NET中MsgBox用法

    一.C#中MessageBox.Show用法 MessageBox.Show (String) 显示具有指定文本的消息框. 由 .NET Compact Framework 支持. MessageBo ...

  5. python enumerate 用法

    A new built-in function, enumerate() , will make certain loops a bit clearer. enumerate(thing) , whe ...

  6. [转载]Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结

    本文对Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法进行了详细的总结,需要的朋友可以参考下,希望对大家有所帮助. 详细解读Jquery各Ajax函数: ...

  7. 【JavaScript】innerHTML、innerText和outerHTML的用法区别

    用法: <div id="test">   <span style="color:red">test1</span> tes ...

  8. chattr用法

    [root@localhost tmp]# umask 0022 一.chattr用法 1.创建空文件attrtest,然后删除,提示无法删除,因为有隐藏文件 [root@localhost tmp] ...

  9. 萌新笔记——vim命令“=”、“d”、“y”的用法(结合光标移动命令,一些场合会非常方便)

    vim有许多命令,网上搜有一堆贴子.文章列举出各种功能的命令. 对于"="."d"."y",我在无意中发现了它们所具有的相同的一些用法,先举 ...

随机推荐

  1. java中构造函数和一般函数的区别

    构造方法 特点: 1.方法名称和类名相同 2.不用定义返回值类型 3.不可以写return语句 作用: 给对象初始化 构造方法的细节: 当一个类中没有定义构造函数时,系统会默认添加一个无参的构造方法. ...

  2. Java里的new

    java里的new的英文意思就是"新的"的意思.在JAVA里就是创建一个新的实例,或者说一个新的对象,一个普通类在没有实例化之前,就是new之前,它的属性,方法等等在内存中都是不存 ...

  3. Docker容器启动失败 Failed to start Docker Application Container Engine

    1.在k8s mster节点执行 1.kubectl get nodes 发现node节点没起来 [root@guanbin-k8s-master ~]# kubectl get nodes NAME ...

  4. docker容器编排 (4)

    容器编排 我们的项目可能会使用了多个容器,容器多了之后管理容器的工作就会变得麻烦.如果要对多个容器进行自动配置使得容器可以相互协作甚至实现复杂的调度,这就需要进行容器编排.Docker原生对容器编排的 ...

  5. 利用系统APP实现导航---By张秀清

    苹果系统本身自带一个地图APP,但是功能并不是很强大,但是一些简单的导航功能还是能做出来的,下面贴上我的代码 // // ViewController.m // 系统APP导航 // // Creat ...

  6. 乐动ld06激光雷达sdk改bug记录分享

    前言: 工作中,有使用过乐动ld06款激光雷达,此款雷达将常规雷达的转动的电机部分内置于自己的保护罩内,减少了雷达本身转动积灰等其他外界影响,探测半径是12m,是一款不错的雷达. 不过今天的主要内容不 ...

  7. 3、前端--伪元素选择器、选择器优先级、字体、背景、边框、display、盒子模型

    伪元素选择器 # 首字调整>>>:也是一种文档布局的方式 p:first-letter { font-size: 48px; /*字体大小*/ color: red; } # 在文本 ...

  8. 34、python并发编程之多进程(操作篇)

    目录: 一 multiprocessing模块介绍 二 Process类的介绍 三 Process类的使用 四 守护进程 五 进程同步(锁) 六 队列(推荐使用) 七 管道 八 共享数据 九 信号量( ...

  9. CentOS8 固定IP无法访问外网问题解决(ping: www.hao123.com: Name or service not known)

    CentOS8虚拟机用了一段时间后,需要安装telnet-server服务,却无法正常安装.之前安装ftp服务是没有问题的,安装问题如下: 错误提示,无法下载相关元数据:网上也是0.0B/s.那么可能 ...

  10. HTTP协议和HTTPS协议的那些事

    文章目录 HTTPS VS HTTP HTTPS=HTTP+加密+证书+完整性保护 加密 对称加密 非对称加密 混合加密 证书 完整性保护 HTTPS并不能取代HTTP SSL是把双刃剑 HTTPS的 ...