iOS开发笔记(九)— 数据库、Crash、内存问题分析

前言

分享iOS开发中遇到的问题,和相关的一些思考,本次内容包括:UIKit的iOS11问题、数据库问题定位、线上Crash处理、内存问题分析

正文

1、iOS 11的UITabbar的高度异常

问题描述:iOS 11+iPhone,在横竖屏切换的场景下,UITabbarViewController的底部栏UITabbar会出现高度异常。

问题定位:经过调试发现,从竖屏到横屏的时候,系统会改变UITabbar的高度;而我们的底部栏高度是自定义的值,故而会导致系统修改后的高度与自定义值不相同的情况。

解决方案,KVO:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {

        if (self.tabBar.height != KSTabBarHeight) {
            self.tabBar.height = KSTabBarHeight;
            self.tabBar.bottom = SCREEN_HEIGHT;
        }

Stackoverflow的类似情况

2、CoreData数据库升级时间长

问题描述:App在升级的时候会对CoreData数据库进行一次迁移,而某些用户反馈升级时间长达数分钟。

问题定位:CoreData数据库迁移使用的是系统提供的自动迁移,经过本地测试,确实存在数据库较大的情况下,升级时间较长的问题。
那么如何确定数据库是哪些表是瓶颈?
用户的数据库比较大,不可能进行整个数据库上传操作;而CoreData并不支持获取某个表的大小。

可以采取一种方案:用户上报数据库每张表的行数,本地通过工具求出每张表的平均值,用以估算每张表的大小。
找到可以导出沙盒本地沙盒的App活跃使用者(比如说运营、产品),用sqlite3_analyzer对数据库进行分析,得到每张表大小,再除以行数,得到每张表每行的平均值。
(不能通过行数直接判断数据库大小,因为表的列数不确定;也不能通过列大小*行数得到表体积,因为某些字段为空)

修复方案:

  • 对瓶颈的表进行行数和体积双重控制;
  • 对某些行数较多但表体积小的表建索引;

引用:
sqlite数据库分析
sqlite3_analyzer安装
Appropriate Uses For SQLite
sqlite索引
Customizing the Migration Process

3、objc_msgSend的Crash分析

问题描述:objc_msgSend是常见的一种Crash,这次的堆栈如下

objc_msgSend

这类由UIKit引起的Crash通常是在回调业务层时,对应的target已经被释放,于是在objc_msgSend的时候就会发生Crash。

寄存器和模块加载地址

问题定位:在本例中,查看上图知道,lr寄存器的地址是在第一个模块的加载区间内,以此作为线索。
用以下指定,进行手工符号化:
atos -o XXX arm64 0x000000010134d36c -l 0x1000fc000(XXX是二进制名字)

最终定位到问题,具体的代码类似:

[self.delegete remove];
self.data = ...

在这种情况下,self.delegate在remove掉之后self之后,self已经被释放,下面的self.data再进行赋值操作,就会出现异常情况。

解决方案:把 [self.delegete remove]; 放到最后一行。

后记:
该问题只出现在iOS 8。在iOS 11的机型上,通过调试我们可以获取到self.data=...这一行在执行时,关于self的内存引用情况:


autoreleasepool和thread都会持有self,保证self在本次执行过程中不释放。故此猜测该问题苹果已经发现,并且在iOS 8后续的版本已经修复。

4、内存相关问题

实际场景涉及到业务,所以抽象成代码来进行分析。

场景1

下面这段代码是否能够正常运行?
如果可以,结果是什么?
如果不可以,是为什么?

- (void)viewDidLoad {
    [super viewDidLoad];
    SInt16* buffer = NULL;
    SInt16* p = &buffer[15];
    NSLog(@"tmp %d", p);
}
场景2

下面这段代码是否能够正常运行?
如果可以,结果是什么?
如果不可以,是为什么?

- (void)viewDidLoad {
    [super viewDidLoad];
    
    char *pBuf = malloc(5);
    memcpy(pBuf, "aaabbbcccddddeeefff", 10);
   
    puts(pBuf);
}

分析:
场景1:
此处有两个trick:
1、p是否能够正常赋值,以及赋何值;
2、指针类型是SInt16*, 计算地址要注意;

[] 是下标运算符,根据操作数和偏移量,获取指定地址的值;
在此题之中,buffer[15]等于*(buffer + 15)
&buffer[15] 等于&(*(buffer + 15))

& 是取址运算符,返回操作数的内存地址;
&buffer[15] = &(*(buffer + 15)) = buffer + 15
所以p = &buffer[15] = buffer+15 = 0+15*sizeof(SInt16) = 30

故而答案是能正常运行,结果是"tmp 30"。

场景2:
申请了一块较大的内存,在memcpy的时候,偶然情况下会出现越界的情况。但是因为堆内存空间到栈内存空间的距离不固定,不一定会出现crash的情况。
上面的题目本质是堆内存访问越界。
故而上述代码大多数情况下输出aaabbbcccd,少数情况下不可预知。

总结

2018年的忙碌情况超过我想象,长时间不更新iOS开发笔记让我都忘了还有这个专题所在。
我有个习惯,开发中遇到问题,超过十分钟还没解决的时候,就会记录下来,这样是开发笔记专题的雏形。
而在加入新公司的第二个年头,我慢慢已经在iOS上的收获越来越少。
从笔记的新增情况来看,就可以发现:每天大多数是重复性劳动!
尝试看过一些iOS相关的书籍,但总感觉收获不大。
今年我选择把更多的业余学习时间分配给Metal,详见Metal入门教程总结

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270