怎么样去回答iOS面试问题
- 日常工作中能用,原理了解清楚了,但是在面试中很难清晰流畅的去表达,所有在此,用文字去记录问题的回答答案以及方式,可能会偏口语一点,意在加深印象同时学会回答。
- 主要从iOS相关面试题开始,基础,方案,框架性的东西逐一整理。
iOS基础面试题
OC相关
- assign和weak修饰符的区别
- assign一般用来修饰值类型,存储在栈空间的属性,由系统管理其内存生命周期
- weak属性一般用来打断引用环,被weak引用的对象它的引用计数不会增加,而且在这个对象被释放的时候被Weak修饰的变量会自动置空,不会造成野指针问题。
- weak属性实现:
- 通过全局的SideTables查找到对应属性(指针地址为Key)的SideTable。(哈希查找)
- SideTable存在一个自旋锁,RefcountMap, weak_table。其中自旋锁用于保证同一时间只能由一个线程进行修改,RefcountMap代表属性的应用关系,weak_table_t保存着弱引用实体。结构体如下:
SideTable结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
struct SideTable { spinlock_t slock; RefcountMap refcnts; weak_table_t weak_table; SideTable() { memset(&weak_table, 0, sizeof(weak_table)); } ~SideTable() { _objc_fatal("Do not delete SideTable."); } void lock() { slock.lock(); } void unlock() { slock.unlock(); } void forceReset() { slock.forceReset(); } // Address-ordered lock discipline for a pair of side tables. template<HaveOld, HaveNew> static void lockTwo(SideTable *lock1, SideTable *lock2); template<HaveOld, HaveNew> static void unlockTwo(SideTable *lock1, SideTable *lock2); };
weak_table_t结构体
1 2 3 4 5 6
struct weak_table_t { weak_entry_t *weak_entries; size_t num_entries; uintptr_t mask; uintptr_t max_hash_displacement; };
- 概念问题:
- SideTabls:为了管理所有对象的引用计数和weak指针,苹果创建了一个全局的SideTables,虽然名字后面有个”s”不过他其实是一个全局的Hash表,里面的内容装的都是SideTable结构体而已。它使用对象的内存地址当它的key。管理引用计数和weak指针就靠它了。
- NSObject *obj = [[NSObject alloc] init]占有多少空间?
obj指向的内存空间大小取决于NSObject内部实现的需要占有多少内存空间,如下代码块Object存在一个对象 Class isa,该实例占有8个字节的空间。所有obj里面的实例对象占有8bytes空间,但是obj占有的空间不是8bytes而是16bytes,具体原因如下:
NSObject 对象结构 ``` @interface NSObject
{ Class isa OBJC_ISA_AVAILABILITY; } /// 翻译成C和C++如下: struct NSObject_IMPL { Class isa; }
1 2
+ alloc时处理: CF requires all objects be at least 16 bytes,对象最少16个字节起
inline size_t instanceSize(size_t extraBytes) const { if (fastpath(cache.hasFastInstanceSize(extraBytes))) { return cache.fastInstanceSize(extraBytes); }
1 2 3 4
size_t size = alignedInstanceSize() + extraBytes; // CF requires all objects be at least 16 bytes. if (size < 16) size = 16; return size; }
```
NSArray *a1 = [NSArray alloc]
和NSArray *a2 = [NSArray alloc]
中a1和a2是否相同?- 是相同的,NSArray包含一系列类簇,空元素数组类对象为
__NSPlaceholderArray
,单个元素数组类对象为__NSSingleObjectArrayI
,多个元素数组对象为__NSArrayI
。在alloc时,只申请占位类对象为__NSPlaceholderArray
。同时对__NSPlaceholderArray
进行init初始化,同样生成的地址是一样的,空数组无需占用额外空间,只需要指向内存中某一块标记为无元素数组内存即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
+ (id) allocWithZone: (NSZone*)z { if (self == NSArrayClass) { /* * For a constant array, we return a placeholder object that can * be converted to a real object when its initialisation method * is called. */ if (z == NSDefaultMallocZone() || z == 0) { /* * As a special case, we can return a placeholder for an array * in the default malloc zone extremely efficiently. */ /// defaultPlaceholderArray为标记为static。因此第一次开辟后,后续所有空数组地址都一样。NSArray和NSMutableArray各自有个defaultPlaceholderArray return defaultPlaceholderArray; } else { id obj; /* * For anything other than the default zone, we need to * locate the correct placeholder in the (lock protected) * table of placeholders. */ (void)pthread_mutex_lock(&placeholderLock); obj = (id)NSMapGet(placeholderMap, (void*)z); if (obj == nil) { /* * There is no placeholder object for this zone, so we * create a new one and use that. */ obj = (id)NSAllocateObject(GSPlaceholderArrayClass, 0, z); NSMapInsert(placeholderMap, (void*)z, (void*)obj); } (void)pthread_mutex_unlock(&placeholderLock); return obj; } } else { return NSAllocateObject(self, 0, z); } }
- 是相同的,NSArray包含一系列类簇,空元素数组类对象为
isa
指针的作用- Class结构体下有对应的isa指针
Swift相关
iOS Widget开发
- Widget如何和主App进行数据交互
- 在Widget和主APP间使用App Groups进行数据交互。在Capability中勾选App Groups选项。
- 使用NSUserDefault进行数据传输交互
- 使用NSFileManage进行数据交互
- Widgets和主App以服务端数据为桥接进行数据交互
- Widget如何支持动画
- 不支持播放动画Gif、视频
- 不支持滚动
- 不支持主动刷新视图
- 貌似有私有API可以旋转动画(后期可以去调查)
- Widget生命周期
- 核心是时间线,在对应的时间点上显示对应的UI内容
- 时间线由一个或者多个时间线入口以及重载策略组成。
- 时间线刷新:
- System Reloads: 由系统主动、按时发起,会relad下一时间的数据。
- App Reloads: 应用在前台时调用Widget Center相关API进行触发;处于后台时通过后台推送刷新时间。
第三方库
底层原理
- iOS启动流程,编译过程
- 插桩
- 二进制重排
设计方案
架构思路
网络传输
- 为什么TCP协议需要三次握手?
- 面试回答的时候回答到了只有三次握手才能让
client
,server
都知道对方是可通信的。这样回答会比较片面,三次握手主要解决的问题是握手丢失重传的时候怎么去区分。
- 面试回答的时候回答到了只有三次握手才能让