设为首页 加入收藏

TOP

iOS10 语音播报填坑详解(解决串行播报中断问题)(二)
2019-08-31 01:03:38 】 浏览:153
Tags:iOS10 语音 播报 详解 解决 串行 中断 问题
eliver your "best attempt" at modified content, otherwise the original push payload will be used. self.contentHandler(self.bestAttemptContent); } - (AVSpeechSynthesisVoice *)synthesisVoice { if (!_synthesisVoice) { _synthesisVoice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"]; } return _synthesisVoice; } - (AVSpeechSynthesizer *)synthesizer { if (!_synthesizer) { _synthesizer = [[AVSpeechSynthesizer alloc] init]; _synthesizer.delegate = self; } return _synthesizer; } @end

下面我们来逐一对这个 .m 文件中的每一个函数做下解释

  • - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {}

这个函数是通知扩展类的最为核心的函数了,你可以理解为这个就是接受到苹果APNS 通知的一个钩子函数,每次当推送一条通知过来,都会执行到这个函数体内,所以说我们的语音播报逻辑也是在这个钩子函数中进行处理的。

  • - (void)playVoiceWithContent:(NSString *)content {}

这个函数很简单了,就是我们抽离出来的进行语音合成并播放出语音的函数,我们传递一个语音文案作为此函数的参数即可。

*- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance {}

这个函数就是我们今天的主角了,我们之所以能够实现当同时有多条通知同时推送,我们还能够一条一条的串行逐条播放,主要的功能就归功到这个函数了,这个函数是 AVSpeechSynthesizer 类的代理函数,就是一段语音播放完成后执行这个函数,每次当一条语音播放完成,都会被此函数勾住,我们在函数体内实现我们的处理逻辑。

  • - (void)serviceExtensionTimeWillExpire {}

此函数是扩展类自带的一个函数,从这个函数解释我们可以看出,这个函数是当扩展被系统终止之前,会调用到这个函数。

好了,.m文件的几个关键的函数我们都做了相应的解释了,可能还有些小伙伴不是很明白,这些和解决通知串行逐一播报有什么关系尼,下面我就来根据自己的经验给大家做下详细的解释。

先来说下苹果通知的通知栏问题

在苹果通知中,当来一条通知时,我们的手机会叮一下,然后手机通知栏弹出通知。这里大家注意下,其实这个叮一下出来的通知栏也是有生命周期的。从通知栏被弹出来,到通知栏最终被收起,其实中间苹果给了限制时间,大概就6秒左右的时长

说到6秒左右的时长,对于那些多条通知同时到达,需要串行来逐一播报,但是很多小伙伴们会遇到这样一个问题:就是当同时来了多条通知,总是只能播报2-3条,然后就语音中断了,后面的通知不会播报了,遇到这些问题的小伙伴们有没有注意到,其实只能播报2-3条,这个时间差其实就是6秒左右,也就是通知栏的生命周期时长。

出现上面的问题的原因就是:当第一条通知来了,弹出通知栏,然后开始播报第一条语音,第一条播报完了,开始播报第二天语音,可能当第二天语音播报到一半了,但是这个时候,通知栏周期的时间到了,这时通知栏就会收起,注意:,当通知栏收起时,扩展类里面的代码就会终止执行,导致后面的语音播报终端。

上面说到当通知栏收起时,扩展类的代码会终止执行,这里又引出了另一个注意点:就是我们创建的这个扩展类也是有生命周期的,并且这个生命周期和通知栏的生命周期他们是有依赖关系的。即:当通知栏收起时,扩展类就会被系统终止,扩展内里面的代码也会终止执行,只有当下一个通知栏弹出来,扩展类就恢复功能

上面说到通知栏的出现和收起能够影响到扩展类的功能,那我们是不是控制好通知栏的显示和隐藏,就能解决多条串行问题尼?

是的,我们只要控制好通知栏,就可以解决上面的棘手问题,那么问题又来了,我们怎么才能控制通知栏的显示和隐藏尼?感觉我们平时使用苹果的推送,从来没有关心过处理通知栏的显示与隐藏,感觉从来没有这样用过,是的,对应普通的需求,我们确实不需要关系通知栏显示隐藏,感觉这些苹果系统自己已经处理好了,通知来了就显示通知栏,等5秒左右,周期结束就隐藏通知栏。

其实啊,在扩展类里面中,苹果已经给我们指出了如何控制通知栏的显示和隐藏,核心就是这行代码:self.contentHandler(self.bestAttemptContent);,当我们调用到这行代码,就是用来弹出通知栏的,通知栏的隐藏不需要我们来控制了,因为5秒左右的生命周期结束后,它会自动隐藏。

是不是对这样代码既熟悉有陌生啊,熟悉是因为你的扩展类文件中确实有这行代码,陌生是因为你之前从来都没有用过这行代码,不知道行代码是用来干啥的。

好了,既然self.contentHandler(self.bestAttemptContent); 这行核心代码引用出来了,我们就回到最开始的问题,在没有做任何处理时,为什么当同时来多条通知是,语音播报就不能逐一播报尼,其实就是因为当每一条通知到达都会执行这个函数- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {},有没有发现,这个函数体里面 默认就是 执行了 self.contentHandler(self.bestAttemptContent); 这行代码。

假设 一次性同时来了 10条 通知,就会一次性调用了 10次 didReceiveNotificationRequest这个函数, 也就 执行了 10次 self.contentHandler(self.bestAttemptContent), 按照上面的说法,同时执行10次,不就是同时弹出10次的 通知栏吗,这里我调试时发现,当同时来10条通知时,通知栏并没有同时弹出来10次,可能只弹出来1-2次。也就只能在这1-2次的时间长度中进行语音播报了。

上面解释这么多,那么我们到底该如何做尼,细心的同学发现了,我们上面 贴出来的 .m 代码中,我们新增了一个 AVSpeechSynthesizer 类的代理函数,就是

首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇@property & @synthesize & @dyna.. 下一篇OC字典的使用

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目