推广

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

iseeyu2年前 (2024-02-21)推广144

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中高级开发必看的热门书籍(经典必看)

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/56634.html

相关文章

淘宝开店可以0元开店吗(淘宝0元开店怎么注销)

淘宝开店可以0元开店吗(淘宝0元开店怎么注销)

淘宝开店是很多人电商创业的选择,淘宝开店费用是很多人关心的问题。对于一些资金相当比较弱的卖家来说,往往需要节省淘宝开店成本。...

百度竞价推广实操干货

百度竞价推广实操干货

本文是为中国制定的付费搜索学习性文件。这份文件提供给想要了解搜索负责人使用参考。文章略长,颇干,请收藏并仔细琢磨,让你从网络“小白”变推广“大神”! 概念:什么是SEA?Search Engine Advertising (SEA) 付费搜索引擎广告也叫做搜索推广,是一种按...

淘宝开店资料要审核多久,淘宝怎么开店交多少钱(淘宝开店每个月要交钱吗)

淘宝开店资料要审核多久,淘宝怎么开店交多少钱(淘宝开店每个月要交钱吗)

淘宝店铺审核要多久基于支付宝认证成功,审核结束后会通过即时通过邮件和站内信方式提醒您审核结果,具体审核时间分以下两种情况:若您是在支付宝认证通过后提交的淘宝身份信息认证申请,那么会在您提交申请后的2个工作日内审核完毕;若是支付宝认证和淘宝身份信息认证一起提交申请,那么淘宝身份信息认证会在支付宝认证成...

淘宝店铺销售额目标规划怎么做,淘宝店销售额查询(淘宝店铺总资产怎么算)

淘宝店铺销售额目标规划怎么做,淘宝店销售额查询(淘宝店铺总资产怎么算)

做店铺不要盲目,如果你不了解自己的宝贝,不了解宝贝的市场,啥啥都不了解,那么你投身淘宝只会得到大量“血的教训”。做产品之前要先对整个市场有个综合的分析。...

必看 | 企业销售管理痛点及破局之道

必看 | 企业销售管理痛点及破局之道

在企业组织中,销售团队是创造经济效益的主要力量,也是企业与客户之间的桥梁。然而,很多行业中销售人员的流失率高达 20% 甚至更高。这种流失率长期存在会给企业带来巨大的隐患,因为销售人员的离职可能导致商业机密和客户资源的流失,这成为销售管理者的难题。如今,在移动办公大趋势下,...

小编教你全网平台整合营销推广如何做才更靠谱。

小编教你全网平台整合营销推广如何做才更靠谱。

现在任何企业想要发展,都不会忽略了网络上的营销效应,确实与传统的营销方式比起来,小编网络营销的力度会更大一些,而且传播的也会更快,如果找对了契入点,其发酵也是非常快的。而且现在许多企业都在进行全网平台推广,毕竟网络资源太多了,将其进行整合利用,那效果更不是一般的好。那才更靠谱呢? 一,聘请专业的机...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片