1. iOS NSString是否可以使用 assign 、strong 修饰,为什么不用 assign,除了内存?
1.NSString 可以用 strong 修饰。
如果使用 assign 修饰,NSString 对象不会使引用计数加 1,如果该对象没有其他对象引用,对象会被释放掉,你持有的指针就变成野指针了(其他楼的大佬有结束)
2.使用 strong 修饰,引用的对象是同一个,如果该对象在其他地方被修改,这里的也会同步修改。
使用 copy 修饰,可以对原有对象拷贝一份,之前对象如果被修改了,不会影响你现在持有的
2.iOS 属性修饰词 weak,assign,strong,copy
assign 一般用来修饰基础类型,如 float ,double,int ,NSInteger等。
它也可以用来修饰对象,但是assign 修饰对象有个问题,就是当对象的引用计数器为0时,不会主动将对象置空,如果我们没有手动处理的话,就会造成野指针,导致程序崩溃
对于weak,我们都知道它是用来修饰 OC对象的,是弱引用,在对象的引用计数器等于0的时候,会将对象的指针 置为空。
strong表示指向并拥有该对象。其修饰的对象引用计数会增加1。该对象只要引用计数不为0则不会被销毁。当然强行将其设为nil可以销毁它。
copy与strong类似。不同之处是strong的复制是多个指针指向同一个地址,而copy的复制每次会在内存中拷贝一份对象,指针指向不同地址。copy一般用在修饰有可变对应类型的不可变对象上,如NSString, NSArray, NSDictionary。
nonatomic和atomic的区别
atomic:默认是有该属性的,这个属性是为了保证程序在多线程情况下,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题。非常消耗性能。
nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率。如果没有使用多线程间的通讯编程,建议使用nonatomic。
3.深拷贝,浅拷贝
深拷贝就是把内容拷贝一份产生一份新的对象,新对象计数器为1,源对象计数器不变,深拷贝会重新申请一块内存,对象指针指向新的内存地址。与原指针存储的数据内容相同,内存地址不一样。
浅拷贝是指针拷贝,把地址给你,你和我指向同一个对象,源对象计数器加一,源对象和副本的计数器相同。浅拷贝只是对object对象指针进行拷贝,不会开辟新的内存。与数据源指向的是同一内存。
深拷贝:指针复制,创建新的指针地址,内容复制
浅拷贝:内容复制,指针地址不变
4.block局部变量全局变量
Block 是将函数及其执行上下文封装起来的对象。block调用其实就是函数的调用。既然 block 内部封装了函数,那么它同样也有参数和返回值。局部变量截获是值截获
由于局部变量的内存可能会被销毁,所以block会捕获局部变量的值;
静态局部变量的内存在程序运行期间不会被销毁,所以block会捕获静态局部变量的地址;
由于全局变量可以直接访问,所以block不会捕获全局变量;
5.iOS KVC 键值编码
直接通过存取方法或变量名来访问对象的属性。我们也可以使用 KVC 间接访问对象的属性,KVC 还可以访问私有变量
-
(nullable id)valueForKey:(NSString *)key; // 通过 key 来取值
-
(nullable id)valueForKeyPath:(NSString *)keyPath; // 通过 keyPath 来取值
-
(void)setValue:(nullable id)value forKey:(NSString *)key; // 通过 key 来赋值
-
(void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath; // 通过 keyPath 来赋值
6.iOS生命周期
alloc init-> loadView-> viewDidLoad-> viewWillAppear-> viewDidAppear-> viewWillDisappear-> viewDidDisappear-> dealloc
image.png
7.iOS http网络请求协议,get和post请求方式的区别
HTTP超文本传输协议,是短连接,是客户端主动发送请求,服务器做出响应,服务器响应之后,链接断开!HTTP 是基于 TCP 的应用层协议 (OSI 网络七层协议从上到下分别是 应用层、表示层、会话层 、传输层、网络层 、数据链路层、物理层)
GET请求:参数在地址后拼接,没有请求数据,不安全(因为所有参数都拼接在地址后面),不适合传输大量数据
POST请求:参数在请求数据区放着,相对GET请求更安全,并且数据大小没有限制。把提交的数据放置在HTTP包的包体
POST的安全性要比GET的安全性高;
8.Swift中?!都是解包,!是强解,?弱解析
9.AnyObject和Any不同:Any是任意基本数据类型,AnyObject是任意类
10.就是执行操作的意思,也就是在线程中执行的那段代码。在 GCD 中是放在 block 中的。执行任务有两种,三种多线程 NSThread、NSoperationQueue、GCD
方式:同步执行(sync)和异步执行(async)
同步(Sync):同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的
任务完成之后再继续执行,即会阻塞线程。只能在当前线程中执行任务(是当前线程,不一定是主线程),
不具备开启新线程的能力。
异步(Async):线程会立即返回,无需等待就会继续执行下面的任务,不阻塞当前线程。可以在新的线程中
执行任务,具备开启新线程的能力(并不一定开启新线程)。如果不是添加到主队列上,异步会在子线程中
执行任务
队列
队列(Dispatch Queue):这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊
的线性表,采用 FIFO(先进先出)的原则,即新任务总是被插入到队列的末尾,而读取任务的时候总是从
队列的头部开始读取。每读取一个任务,则从队列中释放一个任务
在 GCD 中有两种队列:串行队列和并发队列。两者都符合 FIFO(先进先出)的原则。两者的主要区别是:
执行顺序不同,以及开启线程数不同。
11.Swift中的访问权限 访问级别 由高到低
1.open:公开权限,最高的权限,可以被其他模块访问,继承以及复写。只能用于类和类的成员
2.public:公开访问权限,类或者类的公有属性或者公有方法可以从文件或者模块的任何地方进行访问。那么什么样才能成为一个模块呢?一个app就是一个模块,一个第三方API,第三方框架等都是一个完整的模块。这些模块如果要对外留有访问的属性或者方法,就应该使用public的访问权限。public的权限在swift3.0后无法在其他模块被复写方法/属性或被继承。
3.internal:有着internal访问权限的属性和方法说明在模块内部可以访问,超出模块内部就不可以被访问了。在swift中默认就是internal访问权限。
4.fileprivate:文件私有访问权限,被fileprivate修饰的类或者类的属性或方法可以在同一个物理文件中访问。如果超出该物理文件,那么有着fileprivate访问权限的类,属性和方法就不能被访问。
5.private:私有访问权限,被private修饰的类或者类的属性或方法可以在同一物理文件中的同一个类型(包含extension)访问。如果超出该物理文件或不属于同一个类型,那么有着private的访问权限和方法就不能被访问。
12.iOS中#import 、@import、#include的区别
import指令是Object-C针对#include的改进版本。
@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import;
import会链入该头文件的全部信息,包括实体变量和方法等;而@class只是告诉编译器,其后面声明的名称是类的名称。
import" " 是自己创建的文件;#import< > 是系统的文件。
import 确定一个文件只能被导入一次、这使你在递归包含中不会出现问题、<标记>、所以、#import比起#include的好处就是不会引起交叉编译
如果不是c/c 、尽量用#import
能在实现文件中#import、就不在头文件中#import
能在头文件中@class 实现文件中#import、就不在头文件中#import
13.iOS分类和扩展的区别
1、类别原则上只能添加方法而不能添加属性(能添加属性的原因只是通过runtime解决无setter/getter方法的问题而已,如果调用_成员变量,程序还是会报错)。
2、类扩展不仅可以增加方法,还可以增加实例变量(或者属性),只是该变量默认是 @private 类型的。(所以作用范围只能在自身类,而不是子类或者其它地方)
3、类扩展中声明的方法没被实现,编译器会报警告。但是类别中的方法没被实现,编译器是不会有任何警告的。这是因为类扩展是在编译阶段被添加到类中,而分类是在运行时添加到类中。
4、类扩展不能像类别那样拥有独立的实现部分(@implementation部分),和本类共享一个实现。也就是说,类扩展所声明的方法必须依托对应宿主类的实现部分来实现。
14.iOS静态库跟动态库的区别:
静态库:链接时完整的拷贝至可执行文件库中,被多次使用就有多份冗余拷贝
动态库:链接时不复制,程序运行时由系统动态加载到内存中,供程序调用,系统只加载一次,多个程序共用,节省内存!
15.iOS网络层性能优化策略
优化DNS解析和缓存。对传输的数据进行压缩,减少传输的数据。使用缓存手段减少请求的发起次数。使用策略来减少请求的发起次数,比如在上一个请求为着地之前,不进行新的请求。避免网络抖动,提供重发机制。
16.iOS的self跟super的区别:
self是类的一个隐藏参数,每个方法的实现的第一个参数即为self。
super并不是隐藏参数,实际上只是一个编译器标识符,负责告诉编译器,当调用方法时,去调用父类的方法。而不是本类中的方法。
17.iOS基本属性修饰符:
assign:修饰基本数据类型,不更改引用计数。如果修饰对象nsstring,对象在堆中需要手动释放内存,基本数据类型在栈中自动释放内存。会导致对象释放后指针不为nil会出现野指针。
retain:和strong一样,释放旧对象,传入新对象引用计数+1,在mrc中和release成对出现。
strong:表示指向并持有该对象,其修饰对象的引用计数会+1。该对象只要引用计数不为0就不会被销毁,也可以通过变量强制赋值nil来进行销毁。在arc中使用,告诉系统把这个对象保留在堆中,直到没有指针指向,并且arc机制下不需要担心引用计数,系统会自动释放。
weak:修饰符指向但是并不持有该对象,引用计数也不会加1。weak用来修饰对象,多用于避免循环引用,不可以修饰基本数据类型。 在被强引用之前,尽可能得保留,不改变引用计数。weak引用是弱引用,本质上是分配一个不被持有的属性,weak引用的指针会自动被置为nil,可以避免循环引用。
copy:修饰不可变类型属性,如nsstring,用copy修饰可以防止本对象属性受外界影响!block也经常使用copy修饰符。
nonatomic:非原子性访问,用nonatomic可以多线程访问变量,会导致读写线程不安全,但是会提高执行性能。
atomic:原子性访问,编译器会自动生成互斥锁。atomic修饰的数组添加对象或者移除对象是没办法保证线程安全的。
18.iOS的设计模式:
单例模式:在整个应用程序中,共享一份资源,保证在程序运行过程中,一个类只有一个实例,而且该实例只提供一个全局访问点供外界访问。
工厂类方法模式:通过类继承创建抽象产品,创建一种产品,子类化创建者并重载工厂方法以创建新产品!
抽象工厂模式:通过对象组合创建抽象产品,可以创建多系列产品,必须修改父类的接口才能支持新的产品!
代理模式:代理用来处理事件的监听和参数传递。@required修饰必须实现这个协议方法。@optional修饰是可选实现。
观察者模式:用来消除具有不同行为的对象直接的耦合,不同对象可以协同工作,如kvo
19.iOS的类的继承多继承:
oc的类不支持多继承只支持单继承。协议可以实现多继承遵循多个协议即可。消息的转发也可以实现多继承。
20.多线程和锁:
多线程:一个进程中并发执行多个线程叫做多线程。
NSthread,GCD, nsoperation
21.网络TCP协议:
TCP是传输控制协议,具有面向连接,可靠传输,点到点通信,全双工服务等特点,TCP侧重可靠传输
UDP:用户数据报协议,具有非链接的,不可靠的点到多点的通信特点,UDP侧重快速传输
22.runloop和runtime
runloop通过系统内部维护的循环进行事件,消息管理的一个对象。runloop实际上就是一个do。。。while循环,有任务时开始,无任务时休眠!本质是通过mach_msg()函数接收,发送消息。
runtime是一套c,c++汇编编写的api,为oc提供运行时的功能。能够将数据类型的确定由编译期推迟到运行时。本质上就是发送消息
网友评论