一、Swift与OC的区别?
Swift
和Objective-C
共用一套运行时环境。两者可以互相引用混合编程。其次就是,OC之前积累的很多类库,在Swift
中大部分依然可以直接使用。OC出现过的绝大多数概念,比如引用计数、ARC、属性、协议、接口、初始化、扩展类、命名参数、匿名函数等,在Swift
中继续有效。Swift
大多数概念与OC一样。当然Swift
也多出了一些新兴概念,这些在OC中是没有的,比如范型、元组等。
其实到现在为止Swift
离完全替代Objective-C
还是很遥远,因为Apple内部一直在用 Objective-C
来做一些Framework
的开发,底层也不可能用Swift
实现,所以现在更多的替代是体现在外部开发。
优点:
1、Swift容易阅读,语法和文件结构简易化。
2、Swift更易于维护,文件分离后结构更清晰。
3、Swift更加安全,它是类型安全的语言。
4、Swift代码更少,简洁的语法,可以省去大量冗余代码。
5、Swift速度更快,运算性能更高。
缺点:
1、版本不稳定,之前升级Swift3大动刀
2、使用人数比例偏低,目前还是OC的天下
3、社区的开源项目偏少,毕竟OC独大好多年,很多优秀的类库都不支持Swift,不过这种状况正在改变,现在有好多优秀的Swift的开源类库了
4、公司使用的比例不高,很多公司以稳为主,还是在使用OC开发,很少一些在进行混合开发,更少一些是纯Swift开发
5、偶尔开发中遇到的一些问题,很难查找到相关资料,这是一个弊端
6、纯Swift的运行时和OC有本质区别,一些OC中运行时的强大功能,在纯Swift中变无效了
7、对于不支持Swift
的一些第三方类库,如果非得使用,只能混合编程,利用桥接文件实现
二、OC是动态语言?Swift为静态语言?
1、动态语言
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。
主要动态语言:Objective-C、C#、JavaScript、PHP、Python、Erlang
2、静态语言
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++
三、如何理解OC是一门动态语言
https://blog.csdn.net/wangsongyang617/article/details/79550045
四、runtime的消息传递机制
首先,runtime
系统会把方法调用转化为消息发送,即objc_msgSend
,并且把方法的调用者、方法选择器,当做参数传递过去.
此时,方法的调用者会通过isa
指针来找到其所属的类,然后在cache
或者methodLists
中查找该方法,找得到就跳到对应的方法去执行。
如果在类中没有找到该方法,则通过super_class
往上一级超类查找(如果一直找到NSObject
都没有找到该方法的话,这种情况,我们放到后面消息转发的时候再说)。
在runtime
中维护了一个SEL的表,这个表存储SEL不按照类来存储,只要相同的SEL就会被看做一个,并存储到表中。在项目加载时,会将所有方法都加载到这个表中,而动态生成的方法也会被加载到表中。
简单讲,对象根据方法编号SEL去映射表查找对应的方法实现。
五、__block和__weak?
- __block
对被截获变量进行赋值操作需要添加__block
修饰符。__block
修饰的变量最终变成了对象。__block
本身并不能避免循环引用,避免循环引用需要在block内部把__block
修饰的obj置为nil。另外一点就是__block
修饰的变量在block
内外都是唯一的,要注意这个特性可能带来的隐患。
1、__block对象在block中是可以被修改、重新赋值的。
2、__block对象在block中不会被block强引用一次,从而不会出现循环引用问题。
- (void)test0506_1
{
__block NSMutableArray *array;
void(^Block)(void) = ^{
array = [NSMutableArray array];
};
Block();
}
- __weak
本身是可以避免循环引用的问题的。但是其会导致外部对象释放了之后,block
内部也访问不到这个对象的问题,我们可以通过在block内部声明一个__strong
的变量来指向 weakObj,使外部对象既能在block内部保持住,又能避免循环引用的问题。
使用了__weak
修饰符的对象,作用等同于定义为weak的property。自然不会导致循环引用问题,当原对象没有任何强引用的时候,弱引用指针也会被设置为nil。
六、为什么在Block里面不加__block不允许更改变量?
我们可以发现,系统自动给我们加上的注释,bound by copy
,自动变量val虽然被捕获进来了,但是是用 __cself->val来访问的。Block仅仅捕获了val的值,并没有捕获val的内存地址。所以在__main_block_func_0
这个函数中即使我们重写这个自动变量val的值,依旧没法去改变Block外面自动变量val的值。
OC可能是基于这一点,在编译的层面就防止开发者可能犯的错误,因为自动变量没法在Block中改变外部变量的值,所以编译过程中就报编译错误。
七、为什么自动变量的值没有增加,而其他几个变量的值是增加的?自动变量是什么状态下被block捕获进去的?
自动变量是以值传递方式传递到Block的构造函数里面去的。Block只捕获Block中会用到的变量。由于只捕获了自动变量的值,并非内存地址,所以Block内部不能改变自动变量的值。Block捕获的外部变量可以改变值的是静态变量,静态全局变量,全局变量。
1、静态全局变量,全局变量由于作用域的原因,于是可以直接在Block里面被改变。他们也都存储在全局区。
2、静态变量传递给Block是内存地址值,所以能在Block里面直接改变值。
八、为什么block能捕获变量
__block将变量包装成对象,然后在把捕获到的变量封装在block的结构体里面,block内部存储的变量为结构体指针,也就可以通过指针找到内存地址进而修改变量的值。
九、load和initialize的区别
load是只要类所在文件被引用就会被调用,而initialize是在类或者其子类的第一个方法被调用前调用。所以如果类没有被引用进项目,就不会有load调用;但即使类文件被引用进来,但是没有使用,那么initialize也不会被调用。
相同点在于:方法只会被调用一次。
十、关联对象为分类实现的添加对象,对象添加到哪里了?
关联对象由AssociationsManager
管理,并在AssociationsHashMap
存储。所有对象的关联内容都在同一个全局容器中。
十一、了解关联对象的本质
AssociationsManager
AssociationsHashMap --> object
ObjectAssociationMap --> key
ObjectAssociation --> value、policy
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)
例子说明:
- (void)setSex:(NSString *)sex
{
objc_setAssociatedObject(self, @selector(sex), sex, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
self
也就是person
对象被赋给了AssociationHashMap的key
,而@selector(sex)
的地址被赋给了ObjectAssociationMap
的key
,策略OBJC_ASSOCIATION_COPY_NONATOMIC
被赋值给了ObjectAssociation
的policy
,传递进来的值sex
被赋值给了ObjectAssociation
的value
。
这种设计的巧妙之处就在于:
当一个person
对象不光有一个属性值要关联时,比如我们要关联height
和sex
这两个属性时,我们以person
对象作为key
,然后值是AssociationMap
这个字典类型,在这个字典类型中,分别使用@selector(sex)
和@selector(height)
作为key
,然后分别利用sex
属性的policy
和传递进来的value
和height
属性的policy
和传递进来的value
生成ObjectAssociation
作为value
。而如果有多个person
对象需要关联时,我们只需要在AssociationHashMap
中创造更多的键值对就可以解决这个问题。
通过这个过程我们也能明白:
关联对象的值它不是存储在自己的实例对象的结构中,而是维护了一个全局的结构AssociationManager
更多请参考Category的本质<三>关联对象
十二、TCP为什么三次握手、四次释放?
十三、项目中有没有用到runtime?怎么使用的?
十四、iOS中成员变量、实例变量、属性区分
@interface MyViewController :UIViewController
{
UIButton *yourButton;
int count;
id data;
}
@property(nonatomic, strong) UIButton *myButton;
@end
- 成员变量
在{ }
中所声明的变量都为成员变量。yourButton、count、data
都是成员变量。
成员变量用于类内部,无需与外界接触的变量。因为成员变量不会生成set、get方法,所以外界无法与成员变量接触。
- 实例变量
实例变量本质上就是成员变量。只是实例是针对类而言,实例是指类的声明。
- 属性变量
根据成员变量的私有性,为了方便访问,所以就有了属性变量。属性变量的好处就是允许让其他对象访问到该变量。
你可以设置只读或者可写等,设置方法也可自定义。所以,属性变量是用于与其他对象交互的变量。myButton
是属性变量。
综上所述可知:
成员变量是定义在{}
号中的变量,如果变量的数据类型是一个类则称这个变量为实例变量。因为实例变量是成员变量的一种特殊情况,所以实例变量也是类内部使用的,无需与外部接触的变量,这个也就是所谓的类私有变量。而属性变量是用于与其他对象交互的变量。
十五、TCP连接与轮询拉取数据有什么区别?
十六、自我介绍
十七、简单介绍一下自己的项目
十八、iOS开发中的几种设计模式
目前常用的几种设计模式:代理模式、观察者模式、MVC模式、单例模式、策略模式、工厂模式、MVVM