OC基础知识总结二

1、什么是GPU?什么是离屏渲染?

GPU(Graphic Processing Unit)“图形处理器”,GPU屏幕渲染有两种方式:
1、On-Screen Rendering (当前屏幕渲染)
指的是GPU的渲染操作是在当前屏幕缓冲区中进行。

2、Off-Screen Rendering (离屏渲染)
渲染发生在当前屏幕之外。将渲染结果临时保存(创建缓冲区),等到要用时再取出(需要切换上下文),创建缓冲区和切换上下文都会影响性能。(也可以这么说:GPU在当前屏幕缓冲区以外开辟一个缓冲区进行渲染操作。)
3、优缺点
当前屏幕渲染不需要额外创建新的缓存,也不需要开启新的上下文,相对于离屏渲染性能更好。但是受当前屏幕渲染的局限因素限制(只有自身上下文、屏幕缓存有限等),当前屏幕渲染有些情况下的渲染解决不了的,就使用到离屏渲染。

4、特殊的“离屏渲染”:CPU渲染
如果我们重写了drawRect方法,并且使用任何Core Graphics的技术进行了绘制操作,就涉及到了CPU渲染。整个渲染过程由CPU在App内同步地完成,渲染得到的bitmap(位图)最后再交由GPU用于显示。

5、优化方案:
iOS 9.0 之后UIButton设置圆角会触发离屏渲染,而UIImageView里png图片设置圆角不会触发离屏渲染了,如果设置其他阴影效果之类的还是会触发离屏渲染的。

6、view的drawRect集成于CoreGraphics走的是CPU ,消耗性能较大、

7、动画避免丽萍渲染的方法:
7.1、CALayer属于CoreAnimation与被萨尔曲线可以实现不在view的drawRect方法中换出一些想要的图形。
7.2、CAShapeLayer动画渲染直接提交到手机的GPU中,相较于view的drawRect方法使用CPU渲染而言,效率极高,能大大优化内存使用情况。
知识点链接:https://www.jianshu.com/p/492a151ba25b

2、new和alloc/init的区别?

概括来说,new和alloc/init在功能上几乎是一致的,分配内存并完成初始化。
差别在于,采用new的方式只能采用默认的init方法完成初始化,
采用alloc的方式可以用其他定制的初始化方法。

3、@class和 #import的区别?

@class class1只是告诉编译器,class1是一个类,你不要以为class1是个未声明的野类,除此之外,没了。
但是 #import “class1.h”会告诉编译器,class1这个类中有什么东西,即class1.h中包含的函数和变量。
所以.h中使用@class绰绰有余,若你有需要创建或访问class1中的函数和变量,则必须使用#import。

4、简述一下MVC、MVP、MVVM?

MVC:当用户出发事件的时候,view层会发送指令到controller层,接着controller去通知model层更新数据,model层更新完数据以后直接显示在view层上,这就是MVC的工作原理。
如何理解MVVM设计模式
ViewModel层,就是View和Model层的粘合剂,他是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他各种各样的代码的极好的地方。说白了,就是把原来ViewController层的业务逻辑和页面逻辑等剥离出来放到ViewModel层。
View层,就是ViewController层,他的任务就是从ViewModel层获取数据,然后显示。
链接:https://www.jianshu.com/p/ed2d3c1faaaa

5、属性实质是什么?默认关键字是什么?

属性是描述类的特征,也就是具备什么特性。包括三个部分,带下划线的成员变量,get、setter方法。
默认的属性关键字分两种情况:
一种是基本数据类型,一种是OC普通对象。不管哪种情况默认都有atomic原子属性和readwrite可读写属性,区别是基本数据类型默认是有个assign属性关键字,而OC对象对应的默认有个strong属性关键字。

基本数据类型的默认关键字有:atomic,readwrite,assign
普通OC对象的默认关键字有:atomic,readwrite,strong

6、#include和#import的区别是什么?

#include是c/c++导入头文件的关键字,#import 是oc导入头文件的关键字,#import会自动导入一次,不会重复导入,不会引起交叉编译。

7、weak&assign的不同点:

1、weak策略在属性所指的对象遭到摧毁时,系统会将weak修饰的属性对象的指针指向nil,OC给nil发消息不会有问题。
2、如果使用assign策略在属性所指的对象遭到摧毁时,属性对象指针还指向原来的对象,由于对象的已经被销毁,这时候就产生了野指针,如果这时候再给此对象发送消息,很容易造成程序崩溃,assign可以用于修饰非OC对象,而weak必须用于OC对象。
野指针:指向一个已释放的对象或没有访问权限的内存的指针。
https://www.jianshu.com/p/8b3cf2187255

8、什么是堆?什么是栈?

堆栈是两种数据结构。
堆先进先出,栈先进后出。
空间分配:
栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
缓存方式:
栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。
堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

9、哈希表怎么实现
哈希表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值。

10、NSNotification、Block、Delegate和KVO的区别?
代理是一种回调机制,且是一对一的关系,通知是一对多的关系,一个对向所有的观察者提供变更通知;
效率:Delegate比NSNOtification高;
Delegate和Block一般是一对一的通信;
Delegate需要定义协议方法,代理对象实现协议方法,并且需要建立代理关系才可以实现通信;
Block : Block更加简洁,不需要定义繁琐的协议方法,但通信事件比较多的话,建议使用Delegate;

11、runtime的使用场景?
1、方法交换。(无埋点hook方法、监控控件的点击)。
2、增加类别属性。(objc_getAssicoate,set,并设置属性关键字)
3、获取类的所有属性和成员变量。字典转模型。典型为MJExtention

13、问题:苹果是如何实现Autorelease Pool的?
解答:Autorelease Pool作用:缓存池,可以避免我们经常写relase的一种方式。其实就是延迟release,将创建的对象,添加到最近的autoreleasePool中,等到autoreleasePool作用域结束的时候,会将里面所有的对象的引用计数器 - autorelease.
链接:https://www.jianshu.com/p/c3a5ffcd856b

14、给类动态的添加weak修饰的属性?
首先,给 Category 属性是需要使用runtime中的关联来实现set 和 get 方法。但runtime只提供如下几种修饰实现,并没有weak。
思路是这样的,虽然runtime没有开放weak解决方案,但OBJC对象是可以实现weak的,所以让需要被修饰的对象去持有一个strong的对象,然后当被修饰的对象被释放的时候,持有的对象也会被释放,那么我们就可以捕捉到释放的事件,进而使用OBJC_ASSOCIATION_ASSIGN 来实现弱引用,在释放事件里面再将其释放掉,进而实现weak功能。
// 这里关联的key必须唯一,如果使用_cmd,对一个对象多次关联的时候,前面的对象关联会失效。
https://blog.csdn.net/yan_1564335/article/details/53996538

猜你喜欢

转载自blog.csdn.net/xiaoxiaocode/article/details/80341273