设为首页收藏本站

安徽论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 22342|回复: 0

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

[复制链接]

1

主题

0

回帖

3

积分

新手上路

Rank: 1

积分
3
发表于 2022-2-26 12:09:28 | 显示全部楼层 |阅读模式
网站内容均来自网络,本站只提供信息平台,如有侵权请联系删除,谢谢!
前言

大概捋了一下iOS面试知识点,以此作为大纲希望自己能有目标有计划地准备面试,后面我会逐个复习一下相应的内容,同时也会添加遗漏的知识点到文本,并记录下自己的笔记分享出来。喜欢的可以收藏,大家一起努力。
以下是小编收集总结的iOS技术点+面试题分类;看看你都会了吗?
重点总结-几大分类:

  • iOS底层原理
  • 性能优化以及架构
  • 多线程、网络
  • 数据结构算法
iOS底层原理(必问):iOS开发必备能力,也是大厂面试快速筛选人才方式之一。
面试官问:

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

- 数组在内存上给出了连续的空间- 链表,内存地址上可以是不连续的,每个链表的节点包括原来的内存和下一个节点的信息(单向的一个,双向链表的话,会有两个)数组: - 优点: 使用方便,查询效率比链表高,内存为一连续的区域 - 缺点: 大小固定,不适合动态存储,不方便动态添加 链表: - 优点: 可动态添加删除,大小可变   - 缺点: 只能通过顺次指针访问,查询效率低53、谈谈你对编译、链接的理解

<hr>电子版  iOS面试题+答案:
文章由于答案太多,我做了一个PDF文档,由于简书不能上传文件,,由于文章有限,需要这些文档的,
点击腾讯文档自取吧
展示部分截图:↓↓↓↓↓
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- main3、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尽量使用structruntime- 使用+initialize方法和dispatch_once取代所有的__attribute__((constructor))、C++静态构造器、Objc的+load方法main- 在不影响用户体验的前提下,尽可能将一些操作延迟,不要全部都放在finishLaunching方法中- 按需加载56、包体积优化

安装包瘦身(ipa):资源文件、可执行文件资源文件(图片、音频、视频等)- 采取无损压缩(使用工具)- 去除没有用到的资源(https://github.com/tinymind/LSUnusedResources)可执行文件瘦身:- 编译器优化(Xcode相关配置)- 利用AppCode(https://www.jetbrains.com/objc/)检测未使用的代码:菜单栏 -> Code -> Inspect Code- 生成LinkMap,可以查看可执行文件的具体组成- 可借助第三方工具解析LinkMap文件:http://github.com/huanxsd/LinkMap57、项目的优化、性能优化

启动速度:- 启动过程中做的事情越少越好(尽可能将多个接口合并)- 不在UI线程上作耗时的操作(数据的处理在子线程进行,处理完通知主线程刷新节目)- 在合适的时机开始后台任务(例如在用户指引节目就可以开始准备加载的数据)- 尽量减小包的大小- 辅助工具(友盟,听云,Flurry)页面浏览速度- json的处理(iOS 自带的NSJSONSerialization,Jsonkit,SBJson)- 数据的分页(后端数据多的话,就要分页返回,例如网易新闻,或者 微博记录)- 数据压缩(大数据也可以压缩返回,减少流量,加快反应速度)- 内容缓存(例如网易新闻的最新新闻列表都是要缓存到本地,从本地加载,可以缓存到内存,或者数据库,根据情况而定)- 延时加载tab(比如app有5个tab,可以先加载第一个要显示的tab,其他的在显示时候加载,按需加载- 算法的优化(核心算法的优化,例如有些app 有个 联系人姓名用汉语拼音的首字母排序)操作流畅度优化- Tableview 优化(tableview cell的加载优化)- ViewController加载优化(不同view之间的跳转,可以提前准备好数据)58、说说你自己吧

- 你在项目中技术亮点、难点- 你的发展方向(职业规划)- 你的优点、你的缺点59、说说组件化,你是如何组件化解耦的

TODO(待填充);⌛️⌛️⌛️⌛️⌛️60、静态库、动态库相关

1、什么是库?- 共享代码,实现代码的复用,一般分为静态库和动态库。2、静态库和动态库的区别静态库(.a和.framework 样式):- 链接时完整的拷贝到可执行文件,多次使用多次拷贝,造成冗余,使包变的更大- 但是代码装载速度快,执行速度略比动态库快动态库:(.dylib和.framework)- 链接时不复制,程序运行时由系统加在到内存中,供系统调用,系统加在一次,多次使用,共用节省内存。3、为什么framework既是静态又是动态?- 系统的framework是动态的,自己创建的是静态的。4、.a 和 .framework 的区别是什么?- .a 是单纯的二进制文件,需要 .h文件配合,不能直接使用- .framework是二进制文件+资源文件,可以直接使用。 .framework = .a + .h + sorrceFile(资源文件)<hr>十三、OC对象相关

61、对 OC 中 Class 的源码理解?其中 cache 的理解?说说NSCache缓存策略

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中能否添加属性

- OC语言的协议里面是支持声明属性的- 但在协议中声明属性其实和在其中定义方法一样,只是声明了getter和setter方法,并没有具体实现63、OC内联函数 inline

作用:- 替代宏inline函数与宏有区别- 解决函数调用效率的问题- 函数之间调用,是内存地址之间的调用,当函数调用完毕之后还会返回原来函数执行的地址。- 函数调用有时间开销,内联函数就是为了解决这一问题inline相比于宏的优点- 避免了宏的缺点:需要预编译.因为inline内联函数也是函数,不需要预编译.- 编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。消除了它的隐患和局限性。- 可以使用所在类的保护成员及私有成员inline相比于函数的优点- inline函数避免了普通函数的,在汇编时必须调用call的缺点:取消了函数的参数压栈,减少了调用的开销,提高效率.所以执行速度确比一般函数的执行速度要快.- 集成了宏的优点,使用时直接用代码替换(像宏一样)64、id和NSObject ,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底层实现原理

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

- 子类中的propert_list、method_list、ivar_list并不包含父类- 子类对象的_IMPL包含父类的从以上几点回答TODO(待填充);⌛️⌛️⌛️⌛️⌛️69、+load与 +initialize

共同点:- 方法只会执行一次- 在类使用之前,就自动调用了这两个方法区别:- 执行时机不同()- load方法:如果类自身没有定义,并不会调用其父类的load方法;- initialize方法:如果类自身没有定义,就会调用其父类的initialize方法;执行的前提条件:- load 只要类所在文件被引用,就会执行; - 如果类没有引用进项目,就不会有load的执行; - initialize 需要类或者其子类的第一个方法被调用,才会执行,而且是在第一个方法执行之前,先执行; - 即使类文件被引用进项目,但是没有使用,那么initialize就不会调用执行;70、iOS如何实现多继承,代码书写一下

- 使用协议组合- NSProxyTODO(待填充);⌛️⌛️⌛️⌛️⌛️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指向基类的class2、方法调用查找(⚠️⚠️⚠️图-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,最后找到类方法的实现进行调用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_MASKstruct 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热门面试技术文集

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
免责声明
1. 本论坛所提供的信息均来自网络,本网站只提供平台服务,所有账号发表的言论与本网站无关。
2. 其他单位或个人在使用、转载或引用本文时,必须事先获得该帖子作者和本人的同意。
3. 本帖部分内容转载自其他媒体,但并不代表本人赞同其观点和对其真实性负责。
4. 如有侵权,请立即联系,本网站将及时删除相关内容。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表