iOS面试题总结

1、属性readwrite,readonly,assign,retain,copy,nonatomic 各自什么作用,他们在那种情况下用?

  • readwrite:默认的属性,可读可写,生成setter和getter方法。

  • readonly:只读,只生成getter方法,也就是说不能修改变量。

  • assign:用于声明基本数据类型(int、float)仅设置变量,是赋值属性。

  • retain:持有属性,setter方法将传入的参数先保留,再赋值,传入的参数 引用计数retaincount 会加1

    在堆上开辟一块空间,用指针a指向,然后将指针a赋值(assign)给指针b,等于是a和b同时指向这块堆空间,当a不使用这块堆空间的时候,是否要释放这块堆空间?答案是肯定要的,但是这件堆空间被释放后,b就成了野指针。

    如何避免这样的问题? 这就引出了引用计数器,当a指针这块堆空间的时候,引用计数器+1,当b也指向的时候,引用计数器变成了2,当a不再指向这块堆空间时,release-1,引用计数器为1,当b也不指向这块堆空间时,release-1,引用计数器为0,调用dealloc函数,空间被释放

    总结:当数据类型为int,float原生类型时,可以使用assign。如果是上面那种情况(对象)就是用retain。

  • copy:是赋值特性,setter方法将传入对象赋值一份;需要完全一份新的变量时,直接从堆区拿。

    当属性是 NSString、NSArray、NSDictionary时,既可以用strong 修饰,也可以用copy修饰。当用strong修饰的NSString 指向一个NSMutableString时,如果在不知情的情况下这个NSMutableString的别的引用修改了值,就会出现:一个不可变的字符串却被改变了的情况, 使用copy就不会出现这种情况。

  • nonatomic:非原子性,可以多线程访问,效率高。

  • atomic:原子性,属性安全级别的表示,同一时刻只有一个线程访问,具有资源的独占性,但是效率很低。

  • strong:强引用,引用计数+ 1,ARC下,一个对象如果没有强引用,系统就会释放这个对象。

  • weak:弱引用,不会使引用计数+1.当一个指向对象的强引用都被释放时,这块空间依旧会被释放掉。

    使用场景:在ARC下,如果使用XIB 或者SB 来创建控件,就使用 weak。纯代码创建控件时,用strong修饰,如果想用weak 修饰,就需要先创建控件,然后赋值给用weak修饰的对象。

    查找了一些资料,发现主要原因是,controller需要拥有它自己的view(这个view是所以子控件的父view),因此viewcontroller对view就必须是强引用(strong reference),得用strong修饰view。对于lable,它的父view是view,view需要拥有label,但是controller是不需要拥有label的。如果用strong修饰,在view销毁的情况下,label还仍然占有内存,因为controller还对它强引用;如果用wak修饰,在view销毁的时label的内存也同时被销毁,避免了僵尸指针出现。

    用引用计数回答就是:因为Controller并不直接“拥有”控件,控件由它的父view“拥有”。使用weak关键字可以不增加控件引用计数,确保控件与父view有相同的生命周期。控件在被addSubview后,相当于控件引用计数+1;父view销毁后,所有的子view引用计数-1,则可以确保父view销毁时子view立即销毁。weak的控件在removeFromSuperview后也会立即销毁,而strong的控件不会,因为Controller还保有控件强引用。

    总结归纳为:当控件的父view销毁时,如果你还想继续拥有这个控件,就用srtong;如果想保证控件和父view拥有相同的生命周期,就用weak。当然在大多数情况下用两个都是可以的。

    使用weak的时候需要特别注意的是:先将控件添加到superview上之后再赋值给self,避免控件被过早释放。

2、Objective-C如何对内存管理的,说说你的看法以及你遇到的问题以及解决方法?

​ Objective-C使用引用计数来管理内存,对象有个计数器,用以表示当前有多少个事物想令此对象继续存活下去。

  • MRC 手动内存计数 (Reference Counted)

    retain 递增保留计数

    release 递减保留计数

    对象被创建出来,对象的保留计数至少为1,若想令某对象继续存活,则调用retain方法。要是不想令其继续存活,就调用release或autorelease。当保留计数归零时,对象就回收了(deallocated),系统会将其占用的内存标记为“可重用”。(拖对象保留计数为1 的时候 调用release或autorelease,不会让计数为0,会直接释放,因为这样可以省一步操作)

    ​注意:对象创建出来之后,并不是说对象此时的保留计数必定是1.在alloc或initWith方法的实现代码中,也许还有其他对象也保留了此对象,所以,其保留计数可能会大于1.绝不应该说保留计数一定是某个值,只能说你执行的操作是递增了引用计数或递减了引用计数。

    autoreleasepool(自动释放池)

    调用autorelease时,对象的引用计数不会马上递减,而是先对象放进自动释放池,通常是在下一次“事件循环”时递减。

    因为自动释放池中的释放操作要等到下一次事件循环时才会执行,所以NSLog语句在使用str对象前不需要手工保留。但是,假如要持有此对象的话(比如将其设置给实例变量),那就需要保留。

  • ARC 自动内存计数(Garbage Collection)

    使用ARC时,引用计数实际还是要执行的,只不过保留与释放操作现在是由ARC自动添加。

    这种方式和java类似,在你的程序的执行过程中。始终有一个高人在背后准确地帮你收拾垃圾,你不用考虑它什么时候开始工作,怎样工作。你只需要明白,我申请了一段内存空间,当我不再使用从而这段内存成为垃圾的时候,我就彻底的把它忘记掉,反正那个高人会帮我收拾垃圾。遗憾的是,那个高人需要消耗一定的资源。

    ARC在调用这些方法时(retain、release、autorelease、dealloc),并不通过普通的Objective-C消息派发机制,而是直接调用其底层C语言版本。这样做性能更好,因为保留及释放操作需要频繁执行,所以直接调用底层函数能节省很多CPU周期。比方说,ARC会调用与retain等价的底层函数objc_retain。这也是不能覆写retain、release、autorelease的原因。

3、内存管理的几条原则时什么?按照默认法则.哪些关键字生成的对象需要手动释放?在和property结合的时候如何有效的避免内存泄露?

  • 谁申请,谁释放  遵循Cocoa Touch的使用原则;  内存管理主要要避免“过早释放”和“内存泄漏”,对于“过早释放”需要注意@property设置特性时,一定要用对特性关键字,对于“内存泄漏”,一定要申请了要负责释放,要细心。 关键字alloc 或new 生成的对象需要手动释放;  设置正确的property属性,对于retain需要在合适的地方释放,

  • 使用new、alloc或copy方法创建一个对象时,该对象引用计数器为1。如果不需要使用该对象,可以向其发送release或autorelease消息,在其使用完毕时被销毁。

    ​ 如果通过其他方法获取一个对象,则可以假设这个对象引用计数为1,并且被设置为autorelease,不需要对该对象进行清理,如果确实需要retain这个对象,则需要使用完毕后release。

    ​ 如果retain了某个对象,需要release或autorelease该对象,保持retain方法和release方法使用次数相等。

    ​ 使用new、alloc、copy关键字生成的对象和retain了的对象需要手动释放。设置为autorelease的对象不需要手动释放,会直接进入自动释放池。

4、MVC设计模式是什么? 你还熟悉什么设计模式?他们和MVC有什么不同的地方?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值