野火🔥

生命如野火,骄傲而顽强

【从历年weak看iOS面试】

  • 2013年
    面试官:代理用weak还是strong?
    我 :weak 。
    面试官:明天来上班吧

  • 2014年
    面试官:代理为什么用weak不用strong?
    我 : 用strong会造成循环引用。
    面试官:明天来上班吧

  • 2015年
    面试官:weak是怎么实现的?
    我 :weak其实是 系统通过一个hash表来实现对象的弱引用
    面试官:明天来上班吧

  • 2016年
    面试官:weak是怎么实现的?
    我 :runtime维护了一个weak表,用于存储指向某个对象的所有weak指针。weak表其实是一个hash(哈希)表,key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象指针的地址)数组。
    面试官:明天来上班吧

  • 2017年
    面试官:weak是怎么实现的?
    我 : 1 初始化时:runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址。
    2 添加引用时:objc_initWeak函数会调用 storeWeak() 函数, storeWeak() 的作用是更新指针指向,创建对应的弱引用表。
    3 释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。
    面试官:明天来上班吧

  • 2018年
    面试官:weak是怎么实现的?
    我 :跟2017年说的一样,还详细补充了objc_initWeak, storeWeak, clearDeallocating的实现细节。
    面试官:小伙子基础不错。13k ,996干不干?干就明天来上班。。 下一个

  • 2019年
    面试官:weak是怎么实现的?
    我 : 别说了,拿纸来,我动手实现一个。
    面试官:等写完后,面试官慢悠悠的说,小伙子不错,我考虑考虑,你先回去吧

面试常见:iOS Category


面试非常多候选人,涉及到runtime相关知识Category是一个常见考察点,毕竟这是应用最多的runtime场景。
本文会针对这部分知识问题做一下分解。

-[UIImage imageNamed:]方法导致的卡顿优化

引子

这两天追查app卡顿问题,打开time profiler查看方法耗时,惊奇发现-[UIImage imageNamed:]占用CPU时间很长:

下图是重复打开一个feed页面的CPU占用,发现20%的CPU时间在-[UIImage imageNamed:]中,显然不合理,因为我们知道-[UIImage imageNamed:]相对于-[UIImage imageWithContentsOfFile:]存在图片缓存,重复打开本地图片应该性能影响非常小。

关掉time profiler的Hide System Libraries勾选项,查看系统方法堆栈和对应的耗时:

发现-[NSFileManager fileExistsAtPath:]为主要耗时方法,该方法没有本地数据读取,只是判断是否存在,感觉一脸懵逼?难道内存缓存了还会每次线判一次本地存在?苹果的实现不会这么蠢吧?..

-[UIImage imageNamed:] 的实现原理

imageNamed:实际上调用的是一个叫做UIAssetManager的类,每个Bundle有一个UIAssetManager。它有一个strong-strong的NSMapTable的属性,用来做缓存。。。

如果查询不到缓存,首先命中的是Assets.car,这个是CoreUIFrramework处理的(私有framework),会解压(有缓存)那个Assets.car然后解码取回图。

如果还找不到,会通过Bundle的path按照那个文档描述的,搜索@3x @2x @1x .png忽略等规则,直到找到一个那种非Assets.car的bundle图,然后加载。

如果你的图片不在Assets.car里面,会直接触发到最远的第三部,可能遍历搜索fileExist比较耗时吧

最终卡顿原因

原因找到了:
themedImageNamed: 方法会每次都给 imageName 加上后缀先去取图,这个应该是iOS7之前没有Images Assets之前的适配逻辑。现在其实包里面没有-667h、-736h这样的图了,会导致所有图片第一次都取不到。就会发现频繁调用fileExistsAtPath:,而没调取图逻辑。
系统缓存了所有找到图片的UIImage,没缓存找不到的黑名单。

一些结论和启示

-[UIImage imageNamed:] 需要hook加保护
FPS优化一定要找到瓶颈,别贸然优化 --> 合理使用工具
IO操作很恐怖,哪怕只是很轻量级的处理
有必要监控一下NSFileManager的IO操作情况

复杂多人项目Owner思考

1、背景

UGC方向业务场景比较复杂,易同时出现多职能线和多业务线的大需求,而PM经常要求赶在某个版本前上线,使得频繁出现“时间倒排”
当业务复杂遇上需求较大,那么每个业务方人员平均参与人数将大于1人,项目复杂度也会成倍提升。
需求完成情况最终体现在“代码合入”时间节点上,分解开来,便是提测时间点代码质量。如果开发团队没有应对复杂业务逻辑、多业务线、多人项目工程化能力,最终导致项目delay或者采用加班方式解决问题,会遭各方吐槽,长此以往,则失去信任力。

2、Delay一般原因分析

一般出现这类原因有两点:开发者时间评估不准确;缺乏纠偏。

2.1 时间评估问题

  • 需求点把握不足:没能准确的将需求各个模块分解和细化。
  • 核心流程图缺失、整体架构设计缺失:整体认知不足,不能高屋建瓴。
  • 过UI/UE时间评估不足,联调时间评估不足。

2.2 Owner在项目运行中缺少纠偏

  • 没有里程碑或者里程碑过于简略 。
  • 里程碑进展出现问题,不能尽快完成纠偏,导致问题持续、放大,最终导致delay。

3、规避问题方式

3.1 重视技术方案设计

  • RD在提供排期时,需同时提供详细的分解工期,否则该排期不应予以接受。
  • Owner应review各RD的需求分解的合理性。
  • RD内部需要做技术方案,并内部进行技术方案review,技术方案需要包含核心业务流程图(后端API调用流程、主干UI交互流程)。

3.2 重视站会和里程碑

  • 过UI/UE时间点联调时间点是项目进度管理中的重要里程碑。
  • 表格、看板、甘特图都是可选的项目管理工具,复杂项目运行过程中至少使用一种。
  • 要有规律的站会,站会重点review进展和里程碑完成情况。
  • 每次站会需根据实际情况调整分解排期里程碑,出现delay风险需提前周知项目利益方。

3.3 大需求的分解code review

项目内部需有code review里程碑,根据里程碑分解code review。
--- 分阶段code review思考待续 ---

4、总结

  • RD职责:做项目拆解及各分解时间安排,做技术方案。
  • Owner职责:根据各方拆解建立排期和里程碑,并组织站会,站会中回归项目风险点。

更新一下今年的学习计划

1、工作上

找到新的突破

2、学习

一本英文书
Introduction to Computation and Programming Using Python(2nd)

3、身体

一三五去健身,平均每周2小时健身房运动。