Unruly的博客

心存善念,必有善行;善念善行,天必佑之。


  • 首页

  • 归档

  • 标签

  • 分类

  • 关于

SwiftUI初识

发表于 2019-07-20

设计的动机和目标

  1. 降低开发门槛
  2. 在UI开发领域,描述性语音是最佳方式
  3. 数据驱动
  4. 实时预览 preview

DSL

竞品

  • HTML
  • Flutter
  • JSP、JQote、PHP
  • JSX、Vue、Pug

    使用现有Swift包装语法糖

SwiftUI组件系统

  1. 内置组件
  2. 简化布局系统(flex)

Combine

IGListKit

发表于 2019-06-20

IGListKit

Instagram: 文档

  • 优点
    1. diff算法时间复杂度O(n) 并且局部刷新
    2. sectionController 高内聚低耦合 M或VM独立 多处复用
    3. 数据驱动
  • 缺点
    1. autolayout支持不好 需计算高度
    2. 不支持单条局部刷新

iOS 知识小集(7)

发表于 2019-05-22 | 分类于 知识小集
  • plist: View controller-based status bar appearance -> true
  • preferredStatusBarStyle
1
2
3
4
5
6
7
8
9
10
class NavigationController: UINavigationController {
override var childViewControllerForStatusBarStyle: UIViewController? {
return visibleViewController
}
}
class TabBarController: UITabBarController {
override var childViewControllerForStatusBarStyle: UIViewController? {
return selectedViewController
}
}

AVAudioRecorder

发表于 2019-05-14

iOS录音- AVAudioRecorder

音频采集 - PCM编码

1
模拟信号数字化必须经过三个过程,即抽样、量化和编码,以实现话音数字化的脉冲编码调制(PCM,Pulse Coding Modulation)技术
  • 抽样
  • 量化
  • - 编码
    • 抽样频率(Sampling Rate): 人对频率的识别范围是 20HZ - 20000HZ, 如果每秒钟能对声音做 20000 个采样, 回放时就足可以满足人耳的需求. 所以 22050 的采样频率是常用的, 44100已是CD音质, 超过48000的采样对人耳已经没有意义。这和电影的每秒 24 帧图片的道理差不多
    • 位宽(bit depth): 每一个采样点都需要用一个数值来表示大小,这个数值的数据类型大小可以是:4bit、8bit、16bit、32bit 等等,位数越多,表示得就越精细,声音质量自然就越好,而数据量也会成倍增大。我们在音频采样过程中常用的位宽是 8bit 或者 16bit
    • 声道数(channels): 声道数为 1 和 2 分别称为单声道和双声道 (iPhone只有一个麦克风,一个单声道的通道足够了,它把你的数据需求削减了一半)
    • 比特率(bit rate): 表示经过编码(压缩)后的音频数据每秒钟需要用多少个比特来表示,单位常为kbps

音频压缩

常见的音频编码格式: MP3、AAC、WAV

音频基础概念及常见编码格式

AVAudioSession

  • Category
Category 是否允许音频播放/录音 是否打断其他不支持混音APP 是否会被静音键或锁屏键静音
ambient 只支持播放 ❎ ✅
soloAmbient (默认) 只支持播放 ✅ ✅
playback 只支持播放 ✅,可以重写为❎ ❎
record 只支持录制 ✅ ❎(锁屏下仍可录制
playAndRecord 支持播放,支持录制 ✅,可以重写为❎ ❎
audioProcessing 不支持播放,不支持录制 ✅ ❎
multiRoute 支持播放,支持录制 ✅ ❎
  • Mode

session mode

  • Options

session options

  • 激活 AVAudioSession.sharedInstance().setActive(true)

UITableView优化

发表于 2019-03-12 | 分类于 优化

TableViewCell 复用

在cellForRowAtIndexPath:回调的时候只创建实例,快速返回cell,不绑定数据。在willDisplayCell: forRowAtIndexPath:的时候绑定数据(赋值)

高度缓存 - 预排版

在tableView滑动时,会不断调用heightForRowAtIndexPath:,当 cell 高度需要自适应时,每次回调都要计算高度,会导致 UI 卡顿。为了避免重复无意义的计算,需要缓存高度
(Dictionary, NSCache)
FDTemplateLayoutCell

Texture/AsyncDisplayKit/ASDK

ASDK 的作者是 Scott Goodson (Linkedin),
他曾经在苹果工作,负责 iOS 的一些内置应用的开发,比如股票、计算器、地图、钟表、设置、Safari 等,当然他也参与了 UIKit framework 的开发。后来他加入 Facebook 后,负责 Paper 的开发,创建并开源了 AsyncDisplayKit。目前他在 Pinterest 和 Instagram 负责 iOS 开发和用户体验的提升等工作

阻塞主线程的任务

Layout

  1. 文本高度计算
  2. 视图布局计算

Rendering

  1. 文本渲染
  2. 图片解码
  3. 图形绘制

UIKit Objects

  1. 对象创建
  2. 对象调整
  3. 对象销毁

总结大体原因

  • UI 渲染需要时间较长,无法按时提交结果;
  • 一些需要密集计算的处理放在了主线程中执行,导致主线程被阻塞,无法渲染 UI 界面;
  • 网络请求由于网络状态的问题响应较慢,UI 层由于没有模型返回无法渲染

优化方向

文本和布局的计算、渲染、解码、绘制都可以通过各种方式异步执行,但 UIKit 和 Core Animation 相关操作必需在主线程进行。ASDK 的目标,就是尽量把这些任务从主线程挪走,而挪不走的,就尽量优化性能
视图的惰性加载:ASDisplayNode对UIView封装,它可以在后台线程创建和修改,直到第一次在主线程访问 view 或 layer 属性时,它才会在内部生成对应的对象
图片解码的时机

图片优化

发表于 2019-03-11 | 分类于 优化

UIImageView加载过程

iOS从磁盘加载一张图片,使用UIImageVIew显示在屏幕上,需要经过以下步骤:

  1. 从磁盘拷贝数据到内核缓冲区
  2. 从内核缓冲区复制数据到用户空间
  3. 生成UIImageView,把图像数据赋值给UIImageView
  4. 如果图像数据为未解码的PNG/JPG,解码为位图数据
  5. CATransaction捕获到UIImageView layer树的变化
  6. 主线程Runloop提交CATransaction,开始进行图像渲染
    1. 如果数据没有字节对齐,Core Animation会再拷贝一份数据,进行字节对齐。
    2. GPU处理位图数据,进行渲染

性能优化

缩率图

异步加载

使用Image Asset Catalogs

强制解码

在子线程对图片原始数据强制解码,然后把解码后的图片通过主线程加载 (Core Graphics 框架的 CGBitmapContextCreate)

补充

  1. 不要同时在内存中加载所有图像 内存警告时释放图片加载内存
  2. 提前写入缓存
  3. cell消失时 取消加载

好文章

发表于 2018-12-02

优秀文章

##工具
Git 如何遗弃已经 Push 的提交

iOS调试WebView,简单到无门槛

##底层
孙源的Runloop视频

深入理解RunLoop

Runtime Method Swizzling开发实例汇总(持续更新中

UI

iOS系统中导航栏的转场解决方案与最佳实践

iOS 渲染框架

实现自定义的Slider滑块组件(轨道上带有刻度标记)

揭秘iOS布局

存储

iOS 文件操作简介

性能

老生常谈的圆角图片优化,结合SDWebImage的解决方案

iOS 瘦包常见方式梳理

架构

支付宝客户端架构解析:iOS 容器化框架初探

手把手实践《iOS组件化》

功能

录屏

  • iOS端屏幕录制(replaykit)调研
  • iOS端屏幕录制Replaykit项目实践
  • iOS端使用replaykit录制屏幕的技术细节

图片合成视频

  • CMTime

前端

学习前端的路径图

iOS 知识小集(6)

发表于 2018-11-06 | 分类于 知识小集

Ruby China

FFmpeg

发表于 2018-10-30

采用FFmpeg从视频中提取音频(声音)保存为mp3文件

下载mp3的编码库

因为FFmpeg默认只支持mp3的解码,不支持mp3编码.需要借助第三方的mp3编码库。这里采用lame编码库 下载地址

1
2
3
4
cd lame-3.100
./configure
make
make install

下载FFmpeg

下载

1
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg

brew

1
brew install ffmpeg

编译

1
2
3
./configure --enable-libmp3lame 
make
make install
阅读全文 »

iOS 知识小集(5)

发表于 2018-10-18 | 分类于 知识小集

异步方法封装成同步

  • 使用派发组dispatch_group
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

- (NSInteger)methodSync {
NSLog(@"methodSync 开始");

__block NSInteger result = 0;

dispatch_group_t group = dispatch_group_create();

dispatch_group_enter(group);

[self methodAsync:^(NSInteger value) {

result = value;

dispatch_group_leave(group);

}];

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

NSLog(@"methodSync 结束 result:%ld", (long)result);

return result;
}
  • (推荐):使用信号量dispatch_semaphore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- (NSInteger)methodSync {
NSLog(@"methodSync 开始");

__block NSInteger result = 0;

dispatch_semaphore_t sema = dispatch_semaphore_create(0);

[self methodAsync:^(NSInteger value) {

result = value;

dispatch_semaphore_signal(sema);

}];
// 这里本来同步方法会立即返回,但信号量=0使得线程阻塞
// 当异步方法回调之后,发送信号,信号量变为1,这里的阻塞将被解除,从而返回正确的结果

dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

NSLog(@"methodSync 结束 result:%ld", (long)result);

return result;
}
12…4
Unruly

Unruly

40 日志
4 分类
71 标签
GitHub 微博
Links
  • kalman
© 2016 — 2019 Unruly
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4