iOS不想看的一些Question

搜集一些总是不愿意面对的东西,答案自由发挥……

1. objc在向一个对象发送消息时,发生了什么?objc中向一个nil对象发送消息将会发生什么?如果向一个nil对象发消息不会crash的话,那么unrecognized selector sent to instance的错误是怎么回事?
  1. 根据对象的 isa 指针找到类对象 id,在查询类对象里面的 methodLists 方法函数列表,如果没有在好到,在沿着 superClass ,寻找父类,再从父类 methodLists 方法列表里面查询,最终找到 SEL ,根据 id 和 SEL 确认 IMP(指针函数),再发送消息。
  2. 如果向一个nil对象发送消息,首先在寻找对象的isa指针时就是0地址返回了,所以不会出现任何错误,也不会崩溃。
  3. 因为这个对象已经被释放了(引用计数为0了),那么这个时候再去调用方法肯定是会Crash的,这个时候对象就是一个野指针(指向僵尸对象(对象的引用计数为0,指针指向的内存已经不可用)的指针)了,安全的做法是释放后将对象重新置为nil,使它成为一个空指针。
2. 一个objc对象的isa的指针指向什么,有什么作用?

1、对象的isa指向类,类的isa指向元类(meta class),元类isa指向元类的根类。isa帮助一个对象找到它的方法
2、是一个Class 类型的指针. 每个实例对象有个isa的指针,他指向对象的类,而Class里也有个isa的指针, 指向meteClass(元类)。元类保存了类方法的列表。当类方法被调用时,先会从本身查找类方法的实现,如果没有,元类会向他父类查找该方法。同时注意的是:元类(meteClass)也是类,它也是对象。元类也有isa指针,它的isa指针最终指向的是一个根元类(root meteClass).根元类的isa指针指向本身,这样形成了一个封闭的内循环

3. iOS分类中能否添加属性,why?

分类是只可以添加方法的,不能直接添加属性的,因为分类的结构体中没有struct objc_ivar_list * _Nullable ivars这个数组。
如果要给分类添加属性,可以利用runtime,重写getter、setter方法

4. ARC通过什么方式帮助开发者管理内存?

ARC 在代码编译时,自动的向代码中插入retain和release,完成了对象的引用计算加减。
在运行时,通过对weak对象的管理,避免了引用环。runtime维护的weak对象列表。

5. 如何用GCD同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图

答案链接

6. block中使用self是否一定会造成循环引用?

block容易引起循环引用是因为在VC中声明block,相当于VC拥有block,然后在block中访问self,block又拥有self,所以会造成循环引用。但是如果self没有拥有block,在block中使用self就不会循环引用

7. BAD_ACCESS在什么情况下出现?如何调试BAD_ACCESS错误?

1⃣️访问了野指针,比如对一个已经释放的对象执行了release、访问已经释放对象的成员变量或者发消息,死循环。
2⃣️如下方法都可行:
1、重写object的respondsToSelector方法,找到出现EXEC_BAD_ACCESS前访问的最后一个object
2、设置全局断点快速定位问题代码所在行

3、如下图设置方法
image.png
8. dispatch_barrier_sync 和dispatch_barrier_async的区别

dispatch_barrier_sync 需要等待栅栏执行完才会执行栅栏后面的任务,而dispatch_barrier_async 无需等待栅栏执行完,会继续往下走(保留在队列里)
原因:在同步栅栏时栅栏函数在主线程中执行,而异步栅栏中开辟了子线程栅栏函数在子线程中执行

9. 字符串为什么使用copy?能不能使用Strong?

这是一个安全性问题,比如声明的一个NSString *str变量,然后把一个NSMutableString * mStr变量的赋值给它了,如果要求str跟着mStr变化,那么就用strong;如果str不能跟着mStr一起变化,那就用copy。而对于要把NSString类型的字符串赋值给str,那两都没啥区别。不会影响安全性,内存管理也一样

10. UITableView继承于谁?如何做性能优化?

1、UITableView继承于UIScrollview,因此它默认支持垂直滚动(只支持垂直滚动)
2、性能优化:cell复用、cell高度的计算、渲染、减少视图的数目、减少多余的绘制操作、不要给cell动态添加subView、异步化UI不要阻塞主线程等

11. 在做画板时使用一直在DrawRect方法画会造成内存爆涨?如果是你你会怎么样解决该问题?

1、drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
在此方法调用之前,CALayer需要创建一个空寄宿图(有尺寸)和一个CoreGraphics 的CGContextRef(上下文),当绘制结束后,Core Animation打包所有图层和动画属性,然后通过IPC(内部处理通信)发送到渲染服务器进行显示,同时上下文会被不断渲染到屏幕上,直到下次调用setNeedsDisplay。
所以每次重绘都需要抹掉内存重新分配,空寄宿图的产生就消耗了大量内存,这也就是drawRect 内存暴增原因。
2、1⃣️用CGPath来定义想要绘制的图形,CAShapeLayer会自动渲染。它可以完美替代我们的直接使用Core Graphics绘制layer;
2⃣️CAShapeLayer继承自CALayer,可以使用CALayer的所有属性值,CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类;3⃣️渲染快速,CAShapeLayer 使用了硬件加速,绘制同一图形会比用 Core Graphics 快很多;4⃣️高效使用内存,一个 CAShapeLayer 不需要像普通 CALayer 一样创建一个contents寄宿图形,所以无论有多大,都不会占用太多的内存;5⃣️不会被图层边界剪裁掉;6⃣️不会出现像素化;
总结:
CAShapeLayer属于CoreAnimation框架,其动画渲染直接提交到手机的GPU当中,相较于view的drawRect方法使用CPU渲染而言(实现drawRect消耗性能跟CoreGraphics 这个框架是基于CPU没有关系),GPU图像处理工作更多在硬件层面,效率极高;
一个 CAShapeLayer 不需要像普通 CALayer 一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。
所以,关于绘图,我们可以尝试使用CAShapeLayer + UIBezierPath

12. 什么时候使用代理,什么时候使用Block,什么时候使用通知?

通知,代理,block都用于系统回调
代理
优点:
1.代理语法清晰,可读性高,易于维护
2.它减少代码耦合性,使事件监听与事件处理分离
3.一个控制器可以实现多个代理,满足自定义开发需求,灵活性较高
缺点:
1.实现代理的过程较繁琐
2.跨层传值时加大代码的耦合性,并且程序的层次结构也变得混乱
3.当多个对象同时传值时不易区分,导致代理易用性大大降低
Block
优点:
1.语法简洁,代码可读性和维护性较高 ;2. 配合GCD优秀的解决多线程问题
缺点:
1.Block中得代码将自动进行一次retain操作,容易造成内存泄漏
2.Block内默认引用为强引用,容易造成循环应用
通知
优点:
1.使用简单,代码精简
2.支持一对多,解决同时向多个对象监听的问题
3.传值方便快捷,context自带携带相应的内容
缺点:1.通知使用完毕后需要注销,否则会造成意外崩溃
2.key不够安全,编译器不会检测到是否被通知中心处理
3.调试时难以跟踪
4.当使用者向通知中心发送通知的时候,并不能获得任何反馈信息
5.需要一个第三方的对象来做监听与被监听者的中介
注:delegate运行成本低,block成本高
block出栈需要将使用的数据从栈内存拷贝到堆内存,当然对象的话就是加计数,使用完或者block置 nil 后才消除;delegate只是保存了一个对象指针,直接回调,没有额外消耗,相对C的函数指针,只做了一个查表的动作

13. 多个cell展示图片圆形头像时,如何处理优化性能?

问题:
1、我们需要一个圆角的图片,但是使用 cornerRadius 切了个假圆角,实际上是把四周透明了,操作了layer层。
2、有透明就有混合图层。
3、有混合图层,GPU 计算量就会变大。
4、图层固定还好,如果图层一直在移动(cell 滚动),那么就会出现离屏渲染。
所以使用核心绘图 + 贝塞尔圆形切割 产生一张新真正切割过四个角的图图片就好了。渲染最慢的操作之一是混合(blending),混合操作由GPU来执行。提高性能的方法是减少混合操作的次数。优化混合操作的关键点是在平衡CPU和GPU的负载。
拖慢帧率的原因其实都是Off-Screen Rendering(离屏渲染)的原因。离屏渲染是个好东西,但是频繁发生离屏渲染是非常耗时的。

14. 离屏渲染

通常,GPU 的渲染性能要比 CPU 高效很多,同时对系统的负载和消耗也更低一些。
CPU离屏渲染:core graphics是cpu渲染
GPU离屏渲染:需要开辟新的缓冲区渲染,绘制的时候需要上下文切换。

15. coreData和FMDB的区别及用法?
CF9CED8C-4B12-4DAA-909E-5B5D319BD91D.png

1⃣️FMDB:用OC封装C语言SQLite3,非苹果官方,第三方;还是需要程序员编写SQL语句
2⃣️CoreData:用OC封装C语言SQLite3,相对FMDB来说较重量级,苹果官方;不需要程序员编写SQL语句
3⃣️CoreData会把一个对象整个存到数据库,而使用FMDB可以做到存储一个对象的某个属性

16. const常量与宏定义区别?

1.一般项目中尽量避免使用大量的宏定义,宏定义不会分配内存,是代码段的替换,而static const 修饰的常量 ,则只会开启一份内存空间,其使用效果和宏定义相同,建议以后项目开发中定义常量时,多用 static const 来代替宏定义
2.const修饰字符串:一般const修改可变与不可变,就看const右边修饰的是什么,如:NSString * const name = @"JACK",则代表指针name不可变,*name可变,若NSString const * name = @"JACK",则 *name不可变,指针name可变
3.const常量有数据类型,而宏常量没有数据类型;编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应);宏定义是一个’编译时’概念,const是’运行时’概念
4.宏定义可以通过#undef来使之前的宏定义失效,const常量定义后将在定义域内永久有效
5.宏定义不能作为参数传递给函数,const常量可以在函数的参数列表中出现

17. runloop的运行模式

主线程已经自动创建了Runloop,子线程中需要手动创建之后开启runloop才能保证线程不死,定时器才能正常工作。RunLoop的5个类: CFRunLoopRef、CFRunLoopModeRef、CFRunLoopSourceRef、CFRunLoopTimerRef、CFRunLoopObserverRef。
在RunLoop中有多个运行模式,但RunLoop只能选择一种模式运行
Mode里面至少要有一个Timer或Source
CFRunLoopModeRef代表RunLoop的运行模式
一个RunLoop包含若干个Mode,每个Mode又包含若干个Source/Timer/Observer
每次RunLoop启动时,只能指定其中一个Mode,这个Mode被称作CurrentMode
如果需要切换Mode,只能退出Loop ,在重新指定一个Mode进入
这样做主要是为了分割开不同组的Source/Timer/Observer,让其互不影响

18. NSMutableArray和NSArray用什么修饰好?

[答案链接]//www.greatytc.com/p/503ed56bbf1f

19. 什么情况下用assign,什么情况下用retain,什么情况下用copy?

这些关键字一般影响的是set方法:
assign:直接赋值,无retain操作;
retain:release旧值,retain新值;
copy:set方法会先release旧值,再copy一个新的对象,reference count 为1。
assign 适用于基本数据类型如int,float,struct等值类型,不适用于引用类型。因为值类型会被放入栈中,遵循先进后出原则,由系统负责管理栈内存。而引用类型会被放入堆中,需要我们自己手动管理内存或通过ARC管理

20. 浅拷贝和深拷贝区别

浅拷贝:浅拷贝并不拷贝对象本身,只是对指向对象的指针进行拷贝
深拷贝:直接拷贝对象到内存中一块区域,然后把新对象的指针指向这块内存
调用copy和mutableCopy方法的区别:
1、非容器类对象:
非容器类不可变对象调用Copy方法其实只是把当前对象的指针指向了原对象的地址,而调用mutableCopy方法则是新分配了一块内存区域并把新对象的指针指向了这块区域。对于可变对象来说调用Copy和MutableCopy方法都会重新分配一块内存。但是copy和mutableCopy的区别在于copy在复制对象的时候其实是返回了一个不可变对象,当调用方法改变对象的时候会崩溃。
2、容器类对象:
可变对象不管调用Copy还是MutableCopy都是新分配一块内存。但是虽然重新分配了一块内存,对象里面的数据依然是指针复制,容器类对象,其元素对象始终是指针复制

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容