Skip to content

Commit 85fb15b

Browse files
southpeakTechTinySet
authored andcommitted
内容微调
1 parent 61afea0 commit 85fb15b

File tree

9 files changed

+37
-27
lines changed

9 files changed

+37
-27
lines changed

2017/12.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ git push origin HEAD:refs/for/Dev0.0.1
108108

109109
调试的时候,往往底层库会埋一些 `NSLog` 来调试,使用下面这种方式打印出来的函数名称 `__PRETTY_FUNCTION__` 是底层库的函数名。
110110

111-
```
111+
```c
112112
# define LEFLog(fmt, ...) NSLog((@"%s (%d) => " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
113113
```
114114
@@ -121,7 +121,7 @@ git push origin HEAD:refs/for/Dev0.0.1
121121
不太理解?举个例子吧:
122122
每个 APP 都会有一个网络层,业务层会直接与网络层进行交互。调试的时候,我想知道 A 请求是在哪个页面中的哪个函数被调用了,咋么办?前提是 `NSLog` 在底层库。我们可以这样实现:
123123
124-
```
124+
```objc
125125
@implementation LEFLog
126126
+ (NSString *)lastCallMethod
127127
{
@@ -150,13 +150,13 @@ git push origin HEAD:refs/for/Dev0.0.1
150150

151151
然后定义一个宏:
152152

153-
```
153+
```c
154154
# define LEFLog(fmt, ...) NSLog((@"%@, %s (%d) => " fmt), [LEFLog lastCallMethod], __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__
155155
```
156156
157157
打印结果是这样的:在 `LefexViewController` 中的 `viewDidLoad` 调用了 `Network ` 的 `post` 方法,并打印 `I am a log`.
158158
159-
```
159+
```objc
160160
-[LefexViewController viewDidLoad], +[Network post] (22) => I am a log
161161
```
162162

@@ -339,14 +339,14 @@ CoreAnimation 与 pop 的对比
339339

340340
3.当使用 KTVHCLogEnable(HTTPServer, YES) ,将会定义一个名为 `KTVHCLog_ HTTPServer_ConsoleLogEnable` 静态常量,初始值为 YES。
341341

342-
```
342+
```c
343343
#define KTVHCLogEnable(target, console_log_enable) \
344344
static BOOL const KTVHCLog_##target##_ConsoleLogEnable = console_log_enable; \
345345
```
346346

347347
比如我们使用不同的 View 名字创建不同的 View:
348348

349-
```
349+
```objc
350350
#define Name(target) weibo_##target##_name
351351
#define View(target) view##target##Label
352352

@@ -384,4 +384,5 @@ iOS快速解析崩溃日志
384384
385385
- 4、遇到线上用户崩溃,无法拿到完整崩溃日志,可以让用户到【设置->分析->分析数据】里面找到对应时间点的崩溃日志,然后截图,根据一个开源工具 [dSYMTools](https://github.com/answer-huang/dSYMTools),把崩溃栈的关键地址输入到文本框中即可解析出崩溃的那个方法,具体使用方法参考 [ReadMe](https://github.com/answer-huang/dSYMTools)。
386386
387-
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2017/12/10-2.jpg?raw=true)
387+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2017/12/10-2.jpg?raw=true)
388+

2018/01.md

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ AVSystemController_SystemVolumeDidChangeNotification; object = <AVSystemControll
121121

122122
偶然看到 `Price Tag` 有个替换应用图标的功能,如图,研究了一下。
123123

124-
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/3-1.jpg?raw=true)
124+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/3-1.png?raw=true)
125125

126126
这个功能是在 `iOS 10.3` 后新增的,主要的 `API` 如下所示:
127127

@@ -161,10 +161,12 @@ AVSystemController_SystemVolumeDidChangeNotification; object = <AVSystemControll
161161
除了调用 `API` 外,最主要的还需要在 `info.plist` 中配置 `CFBundleIcons` 项,这是一个字典,可包含 `CFBundlePrimaryIcon``CFBundleAlternateIcons``UINewsstandIcon` 三个键。
162162

163163
`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)
164+
165+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/3-2.png?raw=true)
165166

166167
这里需要注意的是,替换图标应该放在工程的某个目录下,而不放在 `Assets.xcassets` 中,如图所示。
167-
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/3-3.jpg?raw=true)
168+
169+
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/3-3.png?raw=true)
168170

169171

170172
iOS 关于音频播放调研
@@ -176,7 +178,7 @@ iOS 关于音频播放调研
176178
由于最近做音频方面的工作,就调研了一下关于音频播放的一些知识,中间也走过不少弯路,希望这篇小集能对关注我们的同学一点启示,少走一些弯路。最后提供一份我看过的资料。这里关于音频播放简单做一个总结。iOS 中音频播放有以下 5 种方式(如果你有更多的方式告诉我,非常感激),它们的使用场景各不同。
177179

178180
[1] 播放小于 30s 的音频:
179-
AudioServicesPlaySystemSound 可以播放小于等于30s的音频,主要用于播放一些提示音,你可以利用 AudioServicesPlaySystemSoundWithCompletion 的值播放完成的 callback。它有以下特点:
181+
`AudioServicesPlaySystemSound` 可以播放小于等于 `30s` 的音频,主要用于播放一些提示音,你可以利用 `AudioServicesPlaySystemSoundWithCompletion` 的值播放完成的 `callback`。它有以下特点:
180182

181183
- 使用系统音量,不能修改播放音量;
182184
- 立刻开始播放,不能暂停;
@@ -186,20 +188,20 @@ AudioServicesPlaySystemSound 可以播放小于等于30s的音频,主要用于
186188

187189
[查看更多的系统声音ID](http://iphonedevwiki.net/index.php/AudioServices)
188190

189-
[2] AVAudioPlayer 播放本地的音频,或者已加载到内存中的音频流,主要用于播放本地的一些音频文件。注意它不能播放网络音频。它有以下特点:
191+
[2] `AVAudioPlayer` 播放本地的音频,或者已加载到内存中的音频流,主要用于播放本地的一些音频文件。注意它不能播放网络音频。它有以下特点:
190192

191193
- 可以从任意位置播放,可快进,快退;
192194
- 可以循环播放;
193195
- 可以同时播放多个音频;
194196
- 可以控制播放速率;
195197

196-
[3] AVPlayer 可以播放本地和网络音频,也可以播放视频,它支持流媒体播放,也就是说我们可以用它来做边下别播的使用场景。
198+
[3] `AVPlayer` 可以播放本地和网络音频,也可以播放视频,它支持流媒体播放,也就是说我们可以用它来做边下别播的使用场景。
197199

198-
[4] AVQueuePlayer 是 AVPlayer 的子类,它含有一个队列,主要用来播放一个音视频队列。
200+
[4] `AVQueuePlayer``AVPlayer` 的子类,它含有一个队列,主要用来播放一个音视频队列。
199201

200-
[5] Audio Queue 主要用来播放音频,录音,它比较底层,会有更多的控制权,如果 APP 主要功能是基于音频播放,推荐使用这个。
202+
[5] `Audio Queue` 主要用来播放音频,录音,它比较底层,会有更多的控制权,如果 `APP` 主要功能是基于音频播放,推荐使用这个。
201203

202-
总的来说,如果普通的本地音频播放,可以选择 AVAudioPlayer ,这个不需要了解更多的音频知识,就可以达到一个基本的播放;如果想做流媒体播放,建议使用 AVPlayer + Local Server 的方式,类似于唱吧目前开源的方式。当然也可以选择 Audio Queue,不过这个难度比较高,需要对音频播放有一个整体的了解,推荐使用三方库 FreeStream,不过需要一些 C++ 的知识,因为使用过程中有一些坑需要填,这样不得不阅读源码。最后推荐一些不错的文章。
204+
总的来说,如果普通的本地音频播放,可以选择 `AVAudioPlayer` ,这个不需要了解更多的音频知识,就可以达到一个基本的播放;如果想做流媒体播放,建议使用 `AVPlayer + Local Server` 的方式,类似于唱吧目前开源的方式。当然也可以选择 `Audio Queue`,不过这个难度比较高,需要对音频播放有一个整体的了解,推荐使用三方库 `FreeStream`,不过需要一些 `C++` 的知识,因为使用过程中有一些坑需要填,这样不得不阅读源码。最后推荐一些不错的文章。
203205

204206
[官方 Audio Queue](https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioQueueProgrammingGuide/AQPlayback/PlayingAudio.html#//apple_ref/doc/uid/TP40005343-CH3-SW1)
205207

@@ -212,36 +214,43 @@ AudioServicesPlaySystemSound 可以播放小于等于30s的音频,主要用于
212214

213215
iOS中NSArray/NSSet的一些巧妙用法
214216
--------
217+
215218
**作者**: [Vong_HUST](https://weibo.com/VongLo)
216219

217220
最近用到很多操作集合类型的方法,这里总结分享一下,也欢迎大家一起补充。
218221

219-
1、假设我们已经有一个 `NSArray<Model *>` 类型的数组,但是我们想把这个数组中的 `Model` 的某个属性取出组成一个新的数组,一般情况下可能是直接去遍历,但是 `NSArray/NSSet` 有一个更便捷的方法 `valueForKey:`,可以快速取出对应属性组成的数组。但是有个问题就是这个方法的效率比for循环低,数据量不大的时候使用还是没有问题的。如下面两张图
222+
* 假设我们已经有一个 `NSArray<Model *>` 类型的数组,但是我们想把这个数组中的 `Model` 的某个属性取出组成一个新的数组,一般情况下可能是直接去遍历,但是 `NSArray/NSSet` 有一个更便捷的方法 `valueForKey:`,可以快速取出对应属性组成的数组。但是有个问题就是这个方法的效率比 `for` 循环低,数据量不大的时候使用还是没有问题的。如下面两张图:
223+
220224
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/4-1.jpg?raw=true)
225+
221226
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/4-2.jpg?raw=true)
222227

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 中学到的。如图
228+
* 要取两个数组的交集的时候,可以先将 `NSArray` 转换成 `NSMutableSet`,再通过取二者交集即可。但是需要注意一点的是数组中的元素最好复写一下 `isEqual:``hash` 方法,保证取交集后的结果是正确的。
229+
230+
* 要将数组内元素排序或者过滤等操作,可以结合 `NSSortDescriptor``NSPredicate` 使用,可以避免掉大量冗余的 `for` 循环之类的代码。关于 `NSPredicate` 的用法可以参考 [NSHipster](http://nshipster.com/nspredicate/)`Realm`[Cheetsheet](https://academy.realm.io/posts/nspredicate-cheatsheet/)
231+
232+
* 关于图中 `valueForKey:` 的参数为什么不直接用 `@"name"` 而是用 `NSStringFromSelector(@selector(name))`,是因为后者会有代码提示可以避免硬编码带来的错误,同时后续该 `key` 换名字了之后,会有对应的警告。这个也是从 `AFNetworking` 中学到的。如图所示:
233+
227234
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/4-3.jpg?raw=true)
228235

229236
对清除图片缓存的思考
230237
--------
231238

232239
**作者**: [高老师很忙](https://weibo.com/517082456)
233240

241+
众所周知,使用 `+[UIImage imageNamed:]` 方法加载图片是会进图片缓存的,清除缓存是系统触发,并没有为我们提供API;使用 `+[UIImage imageWithContentsOfFile:]` 方法加载图片是不会进入图片缓存的。如果想要有图片缓存机制,并且能手动清除图片缓存,我们可以这样做:
234242

235-
众所周知,使用`+[UIImage imageNamed:]`方法加载图片是会进图片缓存的,清除缓存是系统触发,并没有为我们提供API;使用`+[UIImage imageWithContentsOfFile:]`方法加载图片是不会进入图片缓存的。如果想要有图片缓存机制,并且能手动清除图片缓存,我们可以这样做:
243+
`+[UIImage imageWithContentsOfFile:]` 方向下手:
244+
我们可以自己维护一套图片缓存,`Swizzle +[UIImage imageWithContentsOfFile:]` 方法加入缓存机制。加载图片后,加入到 `NSCache` 缓存,再次取该图片时,优先取 `NSCache` 内的缓存,如果缓存内没有再去真正加载。`NSCache``Memory Warning` 的时候会自动清除缓存,我们也可以使用 `-[NSCache removeAllObjects]` 手动清除缓存。当然,你也可以不使用 `Swizzle` ,写一个 `Manager` 也是可以的,我只是提供一种思路。
236245

237-
`+[UIImage imageWithContentsOfFile:]`方向下手:
238-
我们可以自己维护一套图片缓存,`Swizzle +[UIImage imageWithContentsOfFile:]`方法加入缓存机制。加载图片后,加入到NSCache缓存,再次取该图片时,优先取NSCache内的缓存,如果缓存内没有再去真正加载。NSCache在Memory Warning的时候会自动清除缓存,我们也可以使用`-[NSCache removeAllObjects]`手动清除缓存。当然,你也可以不使用Swizzle,写一个Manager也是可以的,我只是提供一种思路
246+
`+[UIImage imageNamed:]` 方向下手:
247+
`Memory Warning` 或进入后台时,系统会自动帮我们清除使用 `+[UIImage imageNamed:]` 的图片缓存。我们也可以通过模拟发送 `UIApplicationDidReceiveMemoryWarningNotification``UIApplicationDidEnterBackgroundNotification` 来清除图片缓存,风险可以根据实际情况来评估
239248

240-
`+[UIImage imageNamed:]`方向下手:
241-
在Memory Warning或进入后台时,系统会自动帮我们清除使用`+[UIImage imageNamed:]`的图片缓存。我们也可以通过模拟发送`UIApplicationDidReceiveMemoryWarningNotification``UIApplicationDidEnterBackgroundNotification`来清除图片缓存,风险可以根据实际情况来评估。
242-
还可以从私有API来下手,`+[UIImage imageNamed:]`系统底层是通过`UIAssetManager`来管理图片缓存的,如图1,如图2,我们可以模拟调用`_clearCachedResources`方法来实现清除缓存。
249+
还可以从私有API来下手,`+[UIImage imageNamed:]` 系统底层是通过 `UIAssetManager` 来管理图片缓存的,如下两图所示,我们可以模拟调用 `_clearCachedResources` 方法来实现清除缓存。
243250

244251
如果有其他思路的,欢迎提出!
245252

246253
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/5-1.jpg?raw=true)
247254
![](https://github.com/southpeak/iOS-tech-set/blob/master/images/2018/01/5-2.jpg?raw=true)
255+
256+

images/2018/01/3-1.png

-64.8 KB
Loading

images/2018/01/3-2.png

-2.32 KB
Loading

images/2018/01/4-1.jpg

-723 KB
Loading

images/2018/01/4-2.jpg

-690 KB
Loading

images/2018/01/4-3.jpg

-469 KB
Loading

images/2018/01/5-1.jpg

-206 KB
Loading

images/2018/01/5-2.jpg

-126 KB
Loading

0 commit comments

Comments
 (0)