Skip to content

Commit 06d5bb2

Browse files
author
Wang,Suyan
committed
1月第二周整理
1 parent 0f5f830 commit 06d5bb2

10 files changed

Lines changed: 138 additions & 0 deletions

File tree

2018/01.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
为什么音频播放器突然没声音了呢?
44
--------
55

6+
**作者**: [Lefe_x](https://weibo.com/u/5953150140)
7+
8+
69
做音频的同学可能都会遇到播放的音频突然没声音的情况,遇到这种情况后,一般控制台会抛出下面的错误:
710

811
```objc
@@ -32,6 +35,9 @@ if (isSuccess) {
3235
iOS 中音量控制解惑
3336
--------
3437

38+
**作者**: [Lefe_x](https://weibo.com/u/5953150140)
39+
40+
3541
iOS 中音量中其实也有好多小窍门,这个小集帮你解惑。iOS 中主要有2个地方可以控制音量,一个是系统音量,用户主动按音量键,调整音量,这种方式会显示系统音量提示框;另一个是播放器的音量,比如通过 `AVAudioPlayer` 调整音量,这种不会显示系统提示音量框。
3642

3743
### 如何调节音量时不显示系统音量提示框
@@ -107,3 +113,135 @@ AVSystemController_SystemVolumeDidChangeNotification; object = <AVSystemControll
107113

108114
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/2-2.jpg?raw=true)
109115

116+
动态修改应用程序的icon
117+
--------
118+
119+
**作者**: [南峰子_老驴](https://weibo.com/touristdiary)
120+
121+
122+
偶然看到 `Price Tag` 有个替换应用图标的功能,如图,研究了一下。
123+
124+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/3-1.jpg?raw=true)
125+
126+
这个功能是在 `iOS 10.3` 后新增的,主要的 `API` 如下所示:
127+
128+
```objc
129+
@interface UIApplication (UIAlternateApplicationIcons)
130+
// If false, alternate icons are not supported for the current process.
131+
@property (readonly, nonatomic) BOOL supportsAlternateIcons NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
132+
133+
// Pass `nil` to use the primary application icon. The completion handler will be invoked asynchronously on an arbitrary background queue; be sure to dispatch back to the main queue before doing any further UI work.
134+
- (void)setAlternateIconName:(nullable NSString *)alternateIconName completionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
135+
136+
// If `nil`, the primary application icon is being used.
137+
@property (nullable, readonly, nonatomic) NSString *alternateIconName NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
138+
@end
139+
```
140+
141+
只读属性 `supportsAlternateIcons` 用于判断系统是否允许修改 `App` 图标,只有在允许的情况下才能修改。`-setAlternateIconName:completionHandler:` 用于执行修改操作,如果 `iconName` 设置为 `nil`,则恢复为主图标,使用方式如下代码所示:
142+
143+
```objc
144+
- (IBAction)changeIcon:(UIButton *)sender {
145+
if ([[UIApplication sharedApplication] supportsAlternateIcons]) {
146+
147+
NSString *iconName = nil;
148+
if (sender.tag == 1) {
149+
iconName = @"rocket";
150+
} else if (sender.tag == 2) {
151+
iconName = @"pin";
152+
}
153+
154+
[[UIApplication sharedApplication] setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
155+
156+
}];
157+
}
158+
}
159+
```
160+
161+
除了调用 `API` 外,最主要的还需要在 `info.plist` 中配置 `CFBundleIcons` 项,这是一个字典,可包含 `CFBundlePrimaryIcon``CFBundleAlternateIcons``UINewsstandIcon` 三个键。
162+
163+
`CFBundlePrimaryIcon` 为主图标,即 `Assets.xcassets``AppIcon` 的信息,一般置空。`CFBundleAlternateIcons` 即用于设置替换图标,具体的配置项描述可以参考[官方文档](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html) ,通常的配置如图所示。
164+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/3-2.jpg?raw=true)
165+
166+
这里需要注意的是,替换图标应该放在工程的某个目录下,而不放在 `Assets.xcassets` 中,如图所示。
167+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/3-3.jpg?raw=true)
168+
169+
170+
iOS 关于音频播放调研
171+
--------
172+
173+
**作者**: [Lefe_x](https://weibo.com/u/5953150140)
174+
175+
176+
由于最近做音频方面的工作,就调研了一下关于音频播放的一些知识,中间也走过不少弯路,希望这篇小集能对关注我们的同学一点启示,少走一些弯路。最后提供一份我看过的资料。这里关于音频播放简单做一个总结。iOS 中音频播放有以下 5 种方式(如果你有更多的方式告诉我,非常感激),它们的使用场景各不同。
177+
178+
[1] 播放小于 30s 的音频:
179+
AudioServicesPlaySystemSound 可以播放小于等于30s的音频,主要用于播放一些提示音,你可以利用 AudioServicesPlaySystemSoundWithCompletion 的值播放完成的 callback。它有以下特点:
180+
181+
- 使用系统音量,不能修改播放音量;
182+
- 立刻开始播放,不能暂停;
183+
- 不支持快进播放,也不可以循环播放;
184+
- 同一时刻只能播放一个音频;
185+
- 只能通过手机播放音频,不能通过其它设备输出,比如不能通过车载播放。
186+
187+
[查看更多的系统声音ID](http://iphonedevwiki.net/index.php/AudioServices)
188+
189+
[2] AVAudioPlayer 播放本地的音频,或者已加载到内存中的音频流,主要用于播放本地的一些音频文件。注意它不能播放网络音频。它有以下特点:
190+
191+
- 可以从任意位置播放,可快进,快退;
192+
- 可以循环播放;
193+
- 可以同时播放多个音频;
194+
- 可以控制播放速率;
195+
196+
[3] AVPlayer 可以播放本地和网络音频,也可以播放视频,它支持流媒体播放,也就是说我们可以用它来做边下别播的使用场景。
197+
198+
[4] AVQueuePlayer 是 AVPlayer 的子类,它含有一个队列,主要用来播放一个音视频队列。
199+
200+
[5] Audio Queue 主要用来播放音频,录音,它比较底层,会有更多的控制权,如果 APP 主要功能是基于音频播放,推荐使用这个。
201+
202+
总的来说,如果普通的本地音频播放,可以选择 AVAudioPlayer ,这个不需要了解更多的音频知识,就可以达到一个基本的播放;如果想做流媒体播放,建议使用 AVPlayer + Local Server 的方式,类似于唱吧目前开源的方式。当然也可以选择 Audio Queue,不过这个难度比较高,需要对音频播放有一个整体的了解,推荐使用三方库 FreeStream,不过需要一些 C++ 的知识,因为使用过程中有一些坑需要填,这样不得不阅读源码。最后推荐一些不错的文章。
203+
204+
[官方 Audio Queue](https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/AQPlayback/PlayingAudio.html#//apple_ref/doc/uid/TP40005343-CH3-SW1)
205+
206+
[官方 AudioSession](https://developer.apple.com/library/content/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007875)
207+
208+
[@pp锅的码农生活 博客](https://brownfeng.github.io/2016/07/25/iOS%E9%9F%B3%E9%A2%91%E7%B3%BB%E5%88%97(%E4%B8%80)/)
209+
210+
[@cy_zju 博客](http://msching.github.io/blog/2014/07/08/audio-in-ios-2/)
211+
212+
213+
iOS中NSArray/NSSet的一些巧妙用法
214+
--------
215+
**作者**: [Vong_HUST](https://weibo.com/VongLo)
216+
217+
最近用到很多操作集合类型的方法,这里总结分享一下,也欢迎大家一起补充。
218+
219+
1、假设我们已经有一个 `NSArray<Model *>` 类型的数组,但是我们想把这个数组中的 `Model` 的某个属性取出组成一个新的数组,一般情况下可能是直接去遍历,但是 `NSArray/NSSet` 有一个更便捷的方法 `valueForKey:`,可以快速取出对应属性组成的数组。但是有个问题就是这个方法的效率比for循环低,数据量不大的时候使用还是没有问题的。如下面两张图
220+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/4-1.jpg?raw=true)
221+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/4-2.jpg?raw=true)
222+
223+
2、要取两个数组的交集的时候,可以先将 `NSArray` 转换成 `NSMutableSet`,再通过取二者交集即可。但是需要注意一点的是数组中的元素最好复写一下 `isEqual:``hash` 方法,保证取交集后的结果是正确的。
224+
3、要将数组内元素排序或者过滤等操作,可以结合 `NSSortDescriptor``NSPredicate` 使用,可以避免掉大量冗余的 `for` 循环之类的代码。关于 `NSPredicate` 的用法可以参考 [NSHipster](http://nshipster.com/nspredicate/) 和 Realm 的 [Cheetsheet](https://academy.realm.io/posts/nspredicate-cheatsheet/)
225+
4、关于图中 `valueForKey:` 的参数为什么不直接用 `@"name"` 而是用 `NSStringFromSelector(@selector(name))`,是因为
226+
后者会有代码提示可以避免硬编码带来的错误,同时后续该 `key` 换名字了之后,会有对应的警告。这个也是从 AFNetworking 中学到的。如图
227+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/4-3.jpg?raw=true)
228+
229+
对清除图片缓存的思考
230+
--------
231+
232+
**作者**: [高老师很忙](https://weibo.com/517082456)
233+
234+
235+
众所周知,使用`+[UIImage imageNamed:]`方法加载图片是会进图片缓存的,清除缓存是系统触发,并没有为我们提供API;使用`+[UIImage imageWithContentsOfFile:]`方法加载图片是不会进入图片缓存的。如果想要有图片缓存机制,并且能手动清除图片缓存,我们可以这样做:
236+
237+
`+[UIImage imageWithContentsOfFile:]`方向下手:
238+
我们可以自己维护一套图片缓存,`Swizzle +[UIImage imageWithContentsOfFile:]`方法加入缓存机制。加载图片后,加入到NSCache缓存,再次取该图片时,优先取NSCache内的缓存,如果缓存内没有再去真正加载。NSCache在Memory Warning的时候会自动清除缓存,我们也可以使用`-[NSCache removeAllObjects]`手动清除缓存。当然,你也可以不使用Swizzle,写一个Manager也是可以的,我只是提供一种思路。
239+
240+
`+[UIImage imageNamed:]`方向下手:
241+
在Memory Warning或进入后台时,系统会自动帮我们清除使用`+[UIImage imageNamed:]`的图片缓存。我们也可以通过模拟发送`UIApplicationDidReceiveMemoryWarningNotification``UIApplicationDidEnterBackgroundNotification`来清除图片缓存,风险可以根据实际情况来评估。
242+
还可以从私有API来下手,`+[UIImage imageNamed:]`系统底层是通过`UIAssetManager`来管理图片缓存的,如图1,如图2,我们可以模拟调用`_clearCachedResources`方法来实现清除缓存。
243+
244+
如果有其他思路的,欢迎提出!
245+
246+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/5-1.jpg?raw=true)
247+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/5-2.jpg?raw=true)

images/2018/01/3-1.png

128 KB
Loading

images/2018/01/3-2.png

122 KB
Loading

images/2018/01/3-3.png

104 KB
Loading

images/2018/01/3-4.mp4

1.98 MB
Binary file not shown.

images/2018/01/4-1.jpg

1020 KB
Loading

images/2018/01/4-2.jpg

1010 KB
Loading

images/2018/01/4-3.jpg

591 KB
Loading

images/2018/01/5-1.jpg

253 KB
Loading

images/2018/01/5-2.jpg

178 KB
Loading

0 commit comments

Comments
 (0)