iOS开发跳槽入职小米,捋了一下iOS面试知识点

前言

大概捋了一下iOS面试知识点,以此作为大纲希望自己能有目标有计划地准备面试,后面我会逐个复习一下相应的内容,同时也会添加遗漏的知识点到文本,并记录下自己的笔记分享出来。喜欢的可以收藏,大家一起努力。

以下是小编收集总结的iOS技术点+面试题分类;看看你都会了吗?

重点总结-几大分类:

  • iOS底层原理
  • 性能优化以及架构
  • 多线程、网络
  • 数据结构算法

iOS底层原理(必问):iOS开发必备能力,也是大厂面试快速筛选人才方式之一。

面试官问:

一、性能优化点
二、项目难点,怎么解决的
三、项目流程迅游有品控审核和reviewcode
四、http怎么发送数据tcp3次握手
五、智能指针,智能指针有什么缺陷
六、释放不干净(举例a=b b=a这种情况)


51、数组和链表的区别
- 数组在内存上给出了连续的空间
- 链表,内存地址上可以是不连续的,每个链表的节点包括原来的内存和下一个节点的信息(单向的一个,双向链表的话,会有两个)

数组: 
- 优点: 使用方便,查询效率比链表高,内存为一连续的区域 
- 缺点: 大小固定,不适合动态存储,不方便动态添加

 链表: 
- 优点: 可动态添加删除,大小可变   
- 缺点: 只能通过顺次指针访问,查询效率低

53、谈谈你对编译、链接的理解
  • 谈谈你对编译、链接的理解

电子版 iOS面试题+答案:

文章由于答案太多,我做了一个PDF文档,由于不能上传文件,,由于文章有限,需要这些文档的,

点击腾讯文档自取吧

展示部分截图:↓↓↓↓↓

iOS面试文档
54、leak工具使用
55、应用程序启动过程,启动优化
- 应用启动时是用怎样加载所有依赖的Mach-O文件的?
- 请列举你所知道main()函数之前耗时的因素都有哪些

App启动分为两种:
- 冷启动(Cold Launch):从零开始启动app
- 热启动(Warm Launch):app已在内存中,在后台存活,再次点击图标启动app

启动时间的优化,主要是针对冷启动进行优化
1、通过添加环境变量可以打印app的启动时间分析(详情请见下图)
- DYLD_PRINT_STATISTICS
- DYLD_PRINT_STATISTICS_DETAILS(比上一个详细)
- 一般400毫秒以内正常

打印结果:
Total pre-main time: 238.05 milliseconds (100.0%)              // main函数调用之前(pre-main)总耗时
         dylib loading time: 249.65 milliseconds (104.8%)      // 动态库耗时 
        rebase/binding time: 126687488.8 seconds (18128259.6%) 
            ObjC setup time:  10.67 milliseconds (4.4%)        // OC结构体准备耗时 
           initializer time:  52.83 milliseconds (22.1%)       // 初始化耗时 
           slowest intializers :                               // 比较慢的加载 
             libSystem.B.dylib :   6.63 milliseconds (2.7%)
   libBacktraceRecording.dylib :   6.61 milliseconds (2.7%)
    libMainThreadChecker.dylib :  31.82 milliseconds (13.3%)

2、冷启动可以概括为3大阶段
- dyld
- runtime
- main

3、dyld(dynamic link editor),Apple的动态连接器,可以装载Mach-O(可执行文件、动态库等)
- 装载app的可执行文件,同时递归加载所有依赖的动态库
- 当dyld把可执行文件、动态库都装载完成后,会通知runtime进行下一步处理

4、runtime所做的事情
- 调用map_images函数中调用call_load_methods,调用所有Class和Category的+load方法
- 进行各种objc结构的初始化(注册objc类、初始化类对象等等)
- 调用C++静态初始化器和__attribure__((constructor))修饰的函数(JSONKit中存在具体应用)
- 到此为止,可执行文件和动态库中所有的符号(Class, Protocol, Selector, IMP...)都已按格式成功加载到内存中,被runtime所管理

5、总结
- app的启动由dylb主导,将可执行文件加载到内存,顺便加载所有依赖的动态库
- 并由runtime负责加载成objc定义的结构
- 所有初始化工作结束后,dyld就会调用main函数
- 接下来就是ApplicationMain函数,AppDelegate的application:didFinishLaunchingWithOptions:方法

6、按照不同的阶段优化
dyld
- 减少动态库、合并一些动态库(定期清理不必要的动态库)
- 减少objc类、分类的数量、减少selector数量(定期清理不必要的类、分类)
- 减少C++虚构函数
- Swift尽量使用struct

runtime
- 使用+initialize方法和dispatch_once取代所有的__attribute__((constructor))、C++静态构造器、Objc的+load方法

main
- 在不影响用户体验的前提下,尽可能将一些操作延迟,不要全部都放在finishLaunching方法中
- 按需加载

DYLD_PRINT_STATISTICS设置为1
56、包体积优化
  • 深入理解iOS App的启动过程
安装包瘦身(ipa):资源文件、可执行文件

资源文件(图片、音频、视频等)
- 采取无损压缩(使用工具)
- 去除没有用到的资源(https://github.com/tinymind/LSUnusedResources)

可执行文件瘦身:
- 编译器优化(Xcode相关配置)
- 利用AppCode(https://www.jetbrains.com/objc/)检测未使用的代码:菜单栏 -> Code -> Inspect Code
- 生成LinkMap,可以查看可执行文件的具体组成
- 可借助第三方工具解析LinkMap文件:http://github.com/huanxsd/LinkMap

57、项目的优化、性能优化
  • 你一般是如何优化你的APP的?
启动速度:
- 启动过程中做的事情越少越好(尽可能将多个接口合并)
- 不在UI线程上作耗时的操作(数据的处理在子线程进行,处理完通知主线程刷新节目)
- 在合适的时机开始后台任务(例如在用户指引节目就可以开始准备加载的数据)
- 尽量减小包的大小
- 辅助工具(友盟,听云,Flurry)

页面浏览速度
- json的处理(iOS 自带的NSJSONSerialization,Jsonkit,SBJson)
- 数据的分页(后端数据多的话,就要分页返回,例如网易新闻,或者 微博记录)
- 数据压缩(大数据也可以压缩返回,减少流量,加快反应速度)
- 内容缓存(例如网易新闻的最新新闻列表都是要缓存到本地,从本地加载,可以缓存到内存,或者数据库,根据情况而定)
- 延时加载tab(比如app有5个tab,可以先加载第一个要显示的tab,其他的在显示时候加载,按需加载
- 算法的优化(核心算法的优化,例如有些app 有个 联系人姓名用汉语拼音的首字母排序)

操作流畅度优化
- Tableview 优化(tableview cell的加载优化)
- ViewController加载优化(不同view之间的跳转,可以提前准备好数据)

58、说说你自己吧
- 你在项目中技术亮点、难点
- 你的发展方向(职业规划)
- 你的优点、你的缺点

59、说说组件化,你是如何组件化解耦的
TODO(待填充);⌛️⌛️⌛️⌛️⌛️

60、静态库、动态库相关
  • iOS 库.a 和 framework的区别和创建
1、什么是库?
- 共享代码,实现代码的复用,一般分为静态库和动态库。

2、静态库和动态库的区别
静态库(.a和.framework 样式):
- 链接时完整的拷贝到可执行文件,多次使用多次拷贝,造成冗余,使包变的更大
- 但是代码装载速度快,执行速度略比动态库快

动态库:(.dylib和.framework)
- 链接时不复制,程序运行时由系统加在到内存中,供系统调用,系统加在一次,多次使用,共用节省内存。

3、为什么framework既是静态又是动态?
- 系统的framework是动态的,自己创建的是静态的。

4、.a 和 .framework 的区别是什么?
- .a 是单纯的二进制文件,需要 .h文件配合,不能直接使用
- .framework是二进制文件+资源文件,可以直接使用。 .framework = .a + .h + sorrceFile(资源文件)


十三、OC对象相关

61、对 OC 中 Class 的源码理解?其中 cache 的理解?说说NSCache缓存策略
  • iOS开发-底层篇-Class详解
struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

62、protocol中能否添加属性
  • iOS开发 - protocol中定义属性?
- OC语言的协议里面是支持声明属性的
- 但在协议中声明属性其实和在其中定义方法一样,只是声明了getter和setter方法,并没有具体实现

63、OC内联函数 inline
  • iOS OC内联函数 inline
作用:
- 替代宏

inline函数与宏有区别
- 解决函数调用效率的问题
- 函数之间调用,是内存地址之间的调用,当函数调用完毕之后还会返回原来函数执行的地址。
- 函数调用有时间开销,内联函数就是为了解决这一问题

inline相比于宏的优点
- 避免了宏的缺点:需要预编译.因为inline内联函数也是函数,不需要预编译.
- 编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。消除了它的隐患和局限性。
- 可以使用所在类的保护成员及私有成员

inline相比于函数的优点
- inline函数避免了普通函数的,在汇编时必须调用call的缺点:取消了函数的参数压栈,减少了调用的开销,提高效率.所以执行速度确比一般函数的执行速度要快.
- 集成了宏的优点,使用时直接用代码替换(像宏一样)

64、id和NSObject ,instancetype的区别?
  • iOS中的NSObject*、id和instancetype
- id和instancetype都可以做方法的返回值。

- id类型的返回值在编译期不能判断对象的真实类型,即非关联返回类型
- instancetype类型的返回值在编译期可以判断对象的真实类型,即关联返回类型。

- id可以用来定义变量, 可以作为返回值, 可以作为形参
- instancetype只能用于作为返回值。

非关联返回类型、关联返回类型
TODO(待填充);⌛️⌛️⌛️⌛️⌛️

65、方法签名有什么作用?
TODO(待填充);⌛️⌛️⌛️⌛️⌛️

66、nil、Nil、NULL、NSNull的区别?
- nil:指向一个对象的空指针    
- Nil:指向一个类的空指针,   
- NULL:指向其他类型(如:基本类型、C类型)的空指针, 用于对非对象指针赋空值.
- NSNull:在集合对象中,表示空值的对象.

NSNull在Objective-C中是一个类 .NSNull有 + (NSNull *)null; 单例方法.多用于集合(NSArray,NSDictionary)中值为空的对象.

NSArray *array = [NSArray arrayWithObjects: [[NSObject alloc] init], [NSNull null], @"aaa", nil, [[NSObject alloc] init], [[NSObject alloc] init], nil];
NSLog(@"%ld", array.count);// 输出 3,NSArray以nil结尾

67、NSDictionary底层实现原理
  • NSDictionary底层实现原理
- 在OC中NSDictionary是使用hash表来实现key和value的映射和存储的。

hash表存储过程简单介绍:
- 根据key值计算出它的hash值h;
- 假设箱子的个数是n,那么键值对应该放在第(h%n)个箱子中。
- 如果该箱子中已经有了键值对,就是用开放寻址法或者拉链法解决冲突。使用拉链法解决哈希冲突时,每个箱子其实是一个链表,属于同一个箱子的所有键值对都会排列在链表中。

68、父类的property是如何查找的?
  • 父类的property是如何查找的?
- 子类中的propert_list、method_list、ivar_list并不包含父类
- 子类对象的_IMPL包含父类的

从以上几点回答
TODO(待填充);⌛️⌛️⌛️⌛️⌛️

69、+load与 +initialize
  • OC中load方法和initialize方法的异同
共同点:
- 方法只会执行一次
- 在类使用之前,就自动调用了这两个方法

区别:
- 执行时机不同()

- load方法:如果类自身没有定义,并不会调用其父类的load方法;
- initialize方法:如果类自身没有定义,就会调用其父类的initialize方法;

执行的前提条件:
- load 只要类所在文件被引用,就会执行; 
- 如果类没有引用进项目,就不会有load的执行; 
- initialize 需要类或者其子类的第一个方法被调用,才会执行,而且是在第一个方法执行之前,先执行; 
- 即使类文件被引用进项目,但是没有使用,那么initialize就不会调用执行;

70、iOS如何实现多继承,代码书写一下
  • iOS开发:OC中实现多继承
  • 协议和 NSProxy 实现多继承
- 使用协议组合
- NSProxy

TODO(待填充);⌛️⌛️⌛️⌛️⌛️

71、类与结构体的区别
- 结构体只能封装数据,而类还可以封装行为
- 赋值:结构体是拷贝,对象之间是地址
- 结构体变量分配在栈空间(如果是一个局部变量的情况下),而对象分配在堆空间

72、crash崩溃怎么解,崩溃到底层代码
NSSetUncaughtExceptionHandler可以统计闪退
TODO(待填充);⌛️⌛️⌛️⌛️⌛️

73、属性、成员变量、set、get方法相关
- 属性可以与set方法和get方法 三者同时存在吗,如果不行,请说明原因?
换句话说就是:iOS中同时重写属性的set与get方法时,为什么访问不了下划线属性?

原因:
- 属性的setter方法和getter方法是不能同时进行重写,
- 因为,一旦你同时重写了这两个方法,那么系统就不会帮你生成这个成员变量了

解决方式:
@synthesize authType = _authType;
- 意思是,将属性的setter,getter方法,作用于这个变量。

74、isa和superclass相关
1、对象的isa指针指向哪里?superclass指针呢?(⚠️图-总结图)
- instance的isa指向class
- class的isa指向meta-class
- meta-class的isa指向基类的meta-class

- class的superclass指向父类的class(如果没有父类,superclass指针为nil)
- meta-class的superclass指向父类的meta-class
- ⚠️基类的meta-class的superclass指向基类的class

2、方法调用查找(⚠️⚠️⚠️图-instance调用对象的轨迹;图-类方法调用轨迹)
- 对象方法的调用:通过instance的isa找到class,最后找到对象方法的实现进行调用
- 类方法的调用:当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用

3、class对象的superclass指针
Student : Person : NSObject

当Student的instance对象要调用Personal的对象方法时:
- 先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用

4、meta-class对象的superclass指针
当Student的class要调用Person的类方法时
- 先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用

image
image
image
image
image
image
75、OC的类信息存放在哪里?
- 对象方法、属性、成员变量、协议信息,存放在class对象中
- 类方法,存放在meta-class对象中
- 成员变量的具体值,存放在instance对象中

76、class、meta-class的结构

struct objc_class : objc_object {
    Class ISA;
    Class superclass;
    cache_t cache;             // 方法缓存
    class_data_bits_t bits;    // 用于获取具体的类信息
}

& FAST_DATA_MASK

struct class_rw_t {
    uint32_t flags;
    uint32_t version;
    const class_ro_t *ro;        // 
    method_array_t methods;      // 方法列表
    property_array_t properties; // 属性列表
    protocol_array_t protocols;  // 协议列表
    Class firstSubclass;
    Class nextSiblingClass;
    char *demangledName;
}

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    const uint8_t * ivarLayout;
    
    const char * name; // 类名
    method_list_t * baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars; // 成员变量列表

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;
}

推荐阅读:iOS热门面试技术文集

  • ①BAT等各个大厂iOs面试真题+答案大全

  • ② iOS开发高级面试”简历制作"指导

  • ②iOS中高级开发必看的热门书籍(经典必看)

你可能感兴趣的:(iOS开发跳槽入职小米,捋了一下iOS面试知识点)