iOS面试笔试题

iOS总结

2018-03-15  本文已影响6人  Rumbles

4.https://juejin.im/entry/574f97d2df0eea004f5025cd

1.谈谈你对Block和delegate的理解

1.从源头上理解和区别block和delegate
delegate运行成本低,block的运行成本高。
block出栈需要将使用的数据从栈内存拷贝到堆内存,当然对象的话就是加计数,使用完或者block置nil后才消除。delegate只是保存了一个对象指针,直接回调,没有额外消耗。就像C的函数指针,只多做了一个查表动作。
delegate更安全些,比如: 避免循环引用。使用 block 时稍微不注意就形成循环引用,导致对象释放不了。这种循环引用,一旦出现就比较难检查出来。而 delegate 的方法是分离开的,并不会引用上下文,因此会更安全些
当多于 3 个方法时就应该优先采用 delegate。当1,2个回调时,则使用block。

2.谈谈instancetype和id的异同

一、什么是instancetype
instancetype是clang 3.5开始,clang提供的一个关键字,表示某个方法返回的未知类型的Objective-C对象。我们都知道未知类型的的对象可以用id关键字表示,那为什么还会再有一个instancetype呢?
instancetype只能作为返回值,不能像id那样作为参数,比如下面的写法:

3.isKindOfClass和isMemberOfClass的区别

@interface textType1 : ZombieType1
textType1 * text1 = [[textType1 alloc]init]
BOOL b3 = [text1 isMemberOfClass:[textType1 class]];//YES  
BOOL b4 = [text1 isMemberOfClass:[ZombieType1 class]]; 
isMemberOfClass  判断师傅是某一个类的实例对象
isKindOfClass 来确定一个对象是否是一个类的成员,或者是派生自该类的成员

4.如何检查内存泄漏

好问题:
1). 静态分析 Analyze:command+shift+B  
参考 :https://www.jianshu.com/p/2e4f7553659c
2). instruments工具里面有个leak可以动态分析   --> Profile
这个如果显示16进制代码:那么在Xcode里面:build setting 中搜索 debug information format,然后选择第二个选项
参考:https://www.jianshu.com/p/92cd90e65d4c
第二个工具:Time Profiler
参考:https://www.jianshu.com/p/9ac281228de2

5.iOS中常用的设计模式

代理模式  单例模式 观察者模式 MVC模式 MVVM模式
工场模式:简单工厂模式就是由一个工厂类根据传入的参数决定创建哪一种的产品类。简单工厂模式会包含过多的判断条件,维护起来不是特别方便。

6.@property的本质是什么?

@property = ivar + getter +setter 方法
我们写了@property 实际上在编译器里面会自动生成getter 和setter 方法 并且会生成合适类型的实例变量 也就是属性名字 加上下划线 
ARC 下默认的关键字都有哪些 
基本数据类型:
atomic  readwrite  assign
OC 对象
atomic readwrite strong

7.什么时候使用weak 什么时候使用assign

weak 是用来修饰对象类型的
assign 用来修饰基本数据类型
weak 弱引用 用来避免循环引用 例如delegate
  1. copy 关键字
对可变内容copy的是内容 对不可变copy的是指针  copy出来的对象是不可变的
例如:
@property (nonatomic, copy) NSMutableArray *arr;
当我们对arr进行添加删除的时候 会导致系统的崩溃
原因:是因为 copy 就是复制一个不可变 NSArray 的对象,不能对 NSArray 对象进行添加/修改。
  1. @systhesize 和@dynamic
systhesize:合成  如果systhesize修饰一个实例变量 意思就是系统自动生成setter和getter方法
dynamic:动态  意思就是我们自己生成getter和setter 方法

10.NSInteger和int

NSInteger 是基本数据类型 NSInteger是基本数据类型Int或者Long的别名(NSInteger的定义typedef long NSInteger),它的区别在于,NSInteger会根据系统是32位还是64位来决定是本身是int还是long。

11.KVC的底层实现?

KVC 的意思就是我们可以通过属性名字来给属性赋值和取值
当一个对象调用KVC方法的时候系统会进行一下判断
1.首先查看是否有方法 set(key)有就调用这个方法
2.在查看是否有_key的属性 有就赋值
3.查看是否有key这个属性有就赋值
4.都没有就报错 valueForUndefinedKey:
参考:
https://www.jianshu.com/p/fbd1e7c93fd0

12.过OC中的反射机制

理解就是可以通过名字来找到类啊方法啊
Class class = NSClassFromString(@"student"); 
SEL selector = NSSelectorFromString(@"setName");  

13.谓词

查询条件 筛选我们需要的东西  

14.isa指针问题

objec_object(对象)结构体中只有isa一个成员属性,指向objec_class(该对象的类)。
struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;   //isa指针,指向metaclass(该类的元类)
#if !__OBJC2__
    Class super_class   //指向objc_class(该类)的super_class(父类)
    const char *name    //objc_class(该类)的类名
    long version        //objc_class(该类)的版本信息,初始化为0,可以通过runtime函数class_setVersion和class_getVersion进行修改和读取
    long info           //一些标识信息,如CLS_CLASS表示objc_class(该类)为普通类。ClS_CLASS表示objc_class(该类)为metaclass(元类)
    long instance_size  //objc_class(该类)的实例变量的大小
    struct objc_ivar_list *ivars    //用于存储每个成员变量的地址
    struct objc_method_list **methodLists   //方法列表,与info标识关联
    struct objc_cache *cache        //指向最近使用的方法的指针,用于提升效率
    struct objc_protocol_list *protocols    //存储objc_class(该类)的一些协议
#endif
} OBJC2_UNAVAILABLE;
作用:

当我们调用某个对象的对象方法时,它会首先在自身isa指针指向的objc_class(类)的methodLists中查找该方法,如果找不到则会通过objc_class(类)的super_class指针找到其父类,然后从其methodLists中查找该方法,如果仍然找不到,则继续通过 super_class向上一级父类结构体中查找,直至根class;
当我们调用某个类方法时,它会首先通过自己的isa指针找到metaclass(元类),并从其methodLists中查找该类方法,如果找不到则会通过metaclass(元类)的super_class指针找到父类的metaclass(元类)结构体,然后从methodLists中查找该方法,如果仍然找不到,则继续通过super_class向上一级父类结构体中查 找,直至根metaclass(元类);
这里有个细节就是要说运行的时候编译器会将代码转化为objc_msgSend(obj, @selector (makeText)),在objc_msgSend函数中首先通过obj(对象)的isa指针找到obj(对象)对应的class(类)。在class(类)中先去cache中通过SEL(方法的编号)查找对应method(方法),若cache中未找到,再去methodLists中查找,若methodists中未找到,则去superClass中查找,若能找到,则将method(方法)加入到cache中,以方便下次查找,并通过method(方法)中的函数指针跳转到对应的函数中去执行。
参考:http://www.cocoachina.com/ios/20170615/19530.html

15.block的注意点

1). 在block内部使用外部指针且会造成循环引用情况下,需要用__week修饰外部指针:
    __weak typeof(self) weakSelf = self; 
2). 在block内部如果调用了延时函数还使用弱指针会取不到该指针,因为已经被销毁了,需要在block内部再将弱指针重新强引用一下。
    __strong typeof(self) strongSelf = weakSelf;
3). 如果需要在block内部改变外部栈区变量的话,需要在用__block修饰外部变量。

16.类目==类别==分类

类目就是类别  另起一个类   是给类来添加一个眼睛
只可以添加方法 可以使用runtime来实现添加方法
上一篇下一篇

猜你喜欢

热点阅读