原文链接

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. PHP中英文混合字符串处理

    转载请注明来源:https://www.cnblogs.com/hookjc/ function cut_str($string, $sublen, $start = 0, $code = 'utf- ...

  2. 利用babel将es6语法转es5的简单示例

    前言 Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行. 这意味着,你可以现在就用ES6编写程序,而不用担心现有环境是否支持. 文件目录结构 生成包管理配置文件pa ...

  3. jdk1.5新特性之-----自动装箱与自动拆箱

    import java.util.ArrayList; /* jdk1.5新特性之-----自动装箱与自动拆箱. java是面向对象 的语言,任何事物都可以使用类进行描述,sun就使用了 一些类描述j ...

  4. Tomcat服务部署及优化

    Tomcat 服务部署及优化 1.Tomcat简介 2.Tomcat 服务安装及部署 3.Tomcat虚拟主机配置 4.Tomcat 优化 1.Tomcat简介: 概述: Tomcat是Java语言开 ...

  5. 替小白整理的 linux基操命令 切勿扣6 不用感谢

    Linux --------小白必会的基本命令 命令行提示字符[root@localhost ~]#[当前登录系统的用户@主机名称 当前所在的目录]## 表示为管理员登录$ 表示为普通用户登录   切 ...

  6. 数组中包含多个对象 按照对象中的时间进行排序 适用与Angular.js、Jquery、微信小程序等

         LiveList.sort(this.compare('StartDate'))   //StartData:需要排序的时间   compare: function (property) { ...

  7. 【Gym100837F】Controlled Tournament(状压Dp 搜索剪枝)

    题目链接 大意 现有\(N\)个人要打比赛,知道任意两个人间打比赛的胜负关系. 要求在 深度最小 的情况下,根为\(M\)的 竞赛树 的个数. 满足\(1\le M\le N\le 16\) 思路 虑 ...

  8. 蟒蛇书学习笔记——Chapter 09 Section 01 创建和使用类

    9.1 创建和使用类 9.1.1 创建Dog类   根据Dog类创建的每个实例都将存储名字和年龄,我们赋予了每条小狗蹲下(sit( ))和打滚(roll_over( ))的能力: class Dog: ...

  9. gitlab登录时出现402的错误

    当登录gitlab时出现402的错误提示,可进行以下操作 重新设置一下系统时间 在new project 时若还出现同样的402问题,则清除一下浏览器的cookie即可

  10. Solution -「BJWC 2018」「洛谷 P4486」Kakuro

    \(\mathcal{Description}\)   Link.   有一个 \(n\times m\) 的网格图,其中某些格子被主对角线划成两个三角形,称这样的格子为特殊格:初始时,除了一些障碍格 ...