面试题

1、基础数据类型


image.png

image.png

2、关键字


image.png

3、strong、weak、assign、copy 区别
1、 strong 修饰符表示指向并持有该对象、引用计数会+1 (可变数组\字典)
2、weak 修饰符表示指向并不持有该对、引用计数不会+1,weak不可以修饰基本数据类型 (多用于避免循环引用的地方)(Delegate)
3、assign 主要用于修饰基本数据类型;(Int等)
4、copy多用于修饰有可变类型的不可变对象上 (不可变数组\字典)

1、对于不可变对象来说:retain、strong、copy三者的作用是一样的,即当引用的原对象值改变后,其他引用该对象的属性值不会受影响,还是保持原来的值;

2、对于可变对象来说:retain、strong和copy的作用就有区别了,使用retain、strong修饰的属性,当引用的原对象值改变后,其他引用该对象的属性值会一起跟着变化,而copy修饰的属性的值还是保持原样。copy的作用主要也是体现在这里: 让属性值不会随着原引用对象的值改变而改变;

3、retain和strong的区别:作用是一样的,只是写法上的区别。在非arc机制时,是用retain关键字修饰;在arc机制后,一般都用strong关键字来代替retain了

4、根本原因是:给字符串属性赋值不可变字符串,retain、strong、copy修饰的可变和不可变字符串属性都是指针拷贝;
5、给字符串属性赋值可变字符串,retain、strong修饰的可变和不可变字符串属性是指针拷贝,而copy修饰的可变和不可变字符串属性都是内容拷贝。
1 深复制:内容拷贝,源对象和副本对象指的是两个不同的对象,源对象引用计数器不变,副本对象引用计数器为1, 相当于copy(只有不可变对象创建不可变副本(copy)才是浅复制,其它的都是深复制)
2 浅复制:指针拷贝,源对象和副本对象指的都是同一个对象,对象引用计数器+1,相当于retain
结论:


image.png

1、 实例对象 类对象 元类对象

2、objc_msgSend消息执行流程
1)消息发送(cache缓存查找 ->class_rw_t查找 ->父类查找)
2)动态方法解析(resolveInstanceMethod方法)
3)消息转发(forwardingTargetForSelector方法-> methodSignatureForSelector(方法签名)-> forwardInvocation )

3、interface 和 implementation
@interface...@end :可以理解为相当于c++中类的变量和方法的声明

@implementation...@end :可以理解为相当于c++中类的方法的实现

4、instancetype说明
instancetype是clang 3.5开始提供的一个关键字,跟id类似,用于表示某个方法返回的未知类型的Objective-C对象。

5、associatedtype 协议关联类型(协议泛型)
6、typealias 用来给类型起别名
7、使用some关键字声明一个不透明类型(只能返回一种类型)

8、designated、convenience、required
1、designated(中文含义:指定的) :它指的是我们定义的公开的构造函数;公开的构造函数至少有一个,也可以有多个;
2、convenience(中文含义:便利的):我们可以用该关键字来扩展(即新增)构造函数,因此是修饰构造函数的,但需要注意几点:
必需在同一个类中使用;
必需调用一个 designated 构造函数,调用时使用的是 self.init,而不是 super.init;
子类无法继承重载被 convenience 修饰的构造方法;
3、required(中文含义:必要的) :含义很直白,即子类必需要实现父类指定的构造函数;

8、String 16个字节
少于16个字节 存放实际字符串值(内存)
大于16个字节 后8个字节存放真是字符串地址(常量区)常量区一般放字符串
改变(apped) 开辟堆空间(堆空间)

9、Array 8个字 存放地址值(堆空间)

6、分类(category),类扩展(interface)
'分类'(Category)是OC中的特有语法,它是表示一个指向分类的结构体的指针。原则上它只能增加方法,不能增加成员(实例)变量(没有属性列表)。
分类可以利用 关联对象(AssociatedObject)添加属性(写属性的set get 方法)
f
Category源码:

Category
Category 是表示一个指向分类的结构体的指针,其定义如下:
typedef struct objc_category *Category;
struct objc_category {
  char *category_name                          OBJC2_UNAVAILABLE; // 分类名
  char *class_name                             OBJC2_UNAVAILABLE; // 分类所属的类名
  struct objc_method_list *instance_methods    OBJC2_UNAVAILABLE; // 实例方法列表
  struct objc_method_list *class_methods       OBJC2_UNAVAILABLE; // 类方法列表
  struct objc_protocol_list *protocols         OBJC2_UNAVAILABLE; // 分类所实现的协议列表
}

@interface XXX ()
//私有属性
//私有方法(如果不实现,编译时会报警,Method definition for 'XXX' not found)
@end

区别
①类别中原则上只能增加方法(能添加属性的的原因只是通过runtime解决无setter/getter的问题而已);
②类扩展不仅可以增加方法,还可以增加实例变量(或者属性),只是该实例变量默认是@private类型的(
用范围只能在自身类,而不是子类或其他地方);
③类扩展中声明的方法没被实现,编译器会报警,但是类别中的方法没被实现编译器是不会有任何警告的。这是因为类扩展是在编译阶段被添加到类中,而类别是在运行时添加到类中。
④类扩展不能像类别那样拥有独立的实现部分(@implementation部分),也就是说,类扩展所声明的方法必须依托对应类的实现部分来实现。
⑤定义在 .m 文件中的类扩展方法为私有的,定义在 .h 文件(头文件)中的类扩展方法为公有的。类扩展是在 .m 文件中声明私有方法的非常好的方式。

6、isKindOfClass (是否是这种类型 或者这种类型的子类)
isMemberOfClass

10、死锁
同一个串行队列,执行 添加 同步任务
sync函数 往当前SERIAL串行队列添加任务


image.png

你可能感兴趣的:(面试题)