第十七章、拓展一之基本问题

一、Swift与OC的区别?

SwiftObjective-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 与 __weak的区别理解

六、为什么在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)的地址被赋给了ObjectAssociationMapkey,策略OBJC_ASSOCIATION_COPY_NONATOMIC被赋值给了ObjectAssociationpolicy,传递进来的值sex被赋值给了ObjectAssociationvalue

这种设计的巧妙之处就在于:

当一个person对象不光有一个属性值要关联时,比如我们要关联heightsex这两个属性时,我们以person对象作为key,然后值是AssociationMap这个字典类型,在这个字典类型中,分别使用@selector(sex)@selector(height)作为key,然后分别利用sex属性的policy和传递进来的valueheight属性的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

https://www.cnblogs.com/wangbinios/p/7882082.html

你可能感兴趣的:(第十七章、拓展一之基本问题)