iOS面试总结(一)

来源:互联网 发布:profili软件 编辑:程序博客网 时间:2024/05/17 08:45

  1.weak和assign的区别?

  2.对于字符串属性生命用copy还是strong?

  3.关于NSTimer的?

  4.__block和weak的区别?

  5.@synthesize和@dynamic分别有什么作用?

  6.

- (void)viewDidLoad {    [super viewDidLoad];    NSLog(@"1");    dispatch_sync(dispatch_get_main_queue(), ^{        NSLog(@"2");    });    NSLog(@"3");}
上述代码会发生什么?
7.




8.weak和unsafe_unretained的区别?

9.ARC下block有几种?



  6.三个多线程的比较优缺点?



  答案:1.assign用来修饰基本数据类型,weak用来修饰NSObject对象,且是弱引用。

               assign其实也可以用来修饰对象,但为什么不用呢?因为assign修饰的对象当释放后,指针的地址还是存在的,但没有被置为nil,造成野指针(从内存中删除一个对象或者返回时删除栈帧后,并不会改变相关的指针的值。该指针仍然指向原来的内存地址,即使引用已经删除,现在也可能已经被其它进程使用了)。

             那为什么可以用assign修饰基本数据类型呢?因为基本数据类型一般分配在栈上,由系统管理,不会造成野指针。

            2.copy会在内存里拷贝一份对象,两个指针指向不同的内存地址。而strong是两个指针指向同一个内存地址。

            3.(1) NSTimer对象会保留其目标,直到计时器本身失效为止,调用invalidate方法可令计时器失效,另外,一次性计时器在触发完任务之后也会失效。

             (2)反复执行任务的计时器,很容易引入保留环,如果这种计时器的目标对象又保留了计时器本身,那肯定会导致保留环。

             (3)可以扩充NSTimer的功能,用block打破保留环。


+(NSTimer *)eoc_scheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void(^)())block repeats:(BOOL)repeats {    return     [self scheduledTimerWithTimeInterval:interval                                             target:self                                           selector:@selector(eoc_blockInvoke:)                                           userInfo:[block copy]                                            repeats:repeats];}- (void)eoc_blockInvoke:(NSTimer *)timer {    void (^block) () = timer.userInfo;    if (block) {        block();    }}

在相应的类里面:

- (void)startDoSth {    __weak ViewController *weakself = self;    _timer = [NSTimer eoc_scheduledTimerWithTimeInterval:5.0                                                   block:^ {                                                       /* 先定义了一个弱引用,令其指向self,使块捕获这个引用,而不是直接捕获普通的self变量。也就是说self不会为计时器所保留。当开始执行时,立刻生成一个强引用,以保证实例在执行期间持续存在 */                                                       ViewController *strongSelf = weakself;                                                       [strongSelf doSth];                                                   }                                                 repeats:YES];}


最后在dealloc中将计时器置为无效状态,这样计时器就会停止执行任务,即使忘记写了,再次执行任务时,weakself也是nil 了。

  4.__block也可以打破循环引用,优点:

     (1)通过__block变量可控制对象的持有时间

     (2)在不能使用__weak修饰符的环境中不使用__unsafe_unretained修饰符即可

  在执行block时可动态决定是否将nil或其他对象赋值在__block变量中。

    缺点:

      为了避免循环引用必须执行block


  5.@synthesize除了自动合成getter和setter方法外,还可以指定实例变量的名字。

     @dynamic是告诉编译器不要自动创建实现属性所用的实例变量,也不要为其创建存取方法。它相信这些方法会在运行期找到。比如说CoreData框架中的NSManagerObject类里继承了一个子类,那么就需要在运行期动态创建存取方法。继承NSManagerObject时之所以这样做,是因为子类的某些属性不是实例变量,其数据来自后端的数据库中。


  6.结果只是打印1

      原因:dispatch_sync(queue1, block)同步决定在当前线程中执行,假设当前线程为queue0,则会阻塞queue0直到queue1中的block执行完成。

              (1)当queue0与queue1不同时,queue0与queue1并行执行,queue0等待,queue1执行block,此时queue0和queue1互不影响,直到block执行结束,queue0阻塞也结束,即dispatch_sync语句返回。

              (2)当queue0与queue1相同时,即dispatch_sync和block在同一个队列中,此时queue0已经阻塞,不可能执行block,更无法等待block执行结束,因此造成死锁。

  关于死锁的概念可参考这篇文章:http://blog.csdn.net/abigale1011/article/details/6450845/

7.上述问题主要考察内存管理:实例变量,实例变量的setter方法和内存管理的关系。

  首先要明白苹果为什么要有@property这个关键字?它的出现主要是取代实例变量的setter和getter方法的声明(也可加上它们的调用)。

  @synthesize在前面已经说过了。

  通过上面就可总结出:(1)无论是setter还是getter方法操作的都是实例变量

                                      (2)实例变量需要有一对setter和getter方法

  如果使用了属性的话,那么编译器就会自动编写访问属性所需的方法。这个过程叫做自动合成。由于是在编译期完成,所以看不到这些“合成方法”。除了生成代码外,编译器还会自动像类中添加实例变量,实例变量的名字就是属性名前面加下划线,当然在.m文件也可以通过@synthesize自己规定实例变量的名字,但一般都用原名。

  说到自动合成,那什么情况下不会自动合成呢?

  (1)自己重写了setter和getter方法

  (2)重写了只读性的getter方法时

  (3)使用了@dynamic时

  (4)@protocol和@catergory里面的所有属性

  (5)重载的属性:当你在子类中重载了父类中的属性,你必须 使用 @synthesize 来手动合成ivar

直接使用实例变量要注意:
  (1)由于不经过oc的方法派发,所以直接访问实例变量比较快。这种情况是编译器所生成的代码会直接访问保存对象实例变量的那块内存

  (2)直接访问实例变量时,不会调用其“设置方法”,这就绕过了相关属性所定义的“内存管理语义”。比方说,在ARC下直接访问一个声明为copy的属性,那么并不会拷贝该属性,而只会保留新值释放旧值。

  (3)直接访问实例变量,不会触发KVO

  (4)通过属性访问有助于排查与之相关的错误。

  折中的方案是:在写入实例变量时,通过其“设置方法”,而在读取实例变量时,直接访问。这要做能够确保相关属性的“内存管理语义”。这种做法也要注意一下问题:
(1)在初始化发放中应该如何设置其属性值

(2)惰性初始化(为什么要惰性初始化)

 上面的[NSMutableArray arrayWithObjects:@"1", @"2", @"3", @"4", nil],array是不持有这个对象的,由它自己管理内存。

上面的self.testArr1 = array这句话里面的self.testArr1调用了setter方法,展开就是

- (void)setTestArr1:(NSArray *)array {    if (testArr1 != array) {        [array retain];        [testArr1 release];        testArr1 = array;    }}

看到后明白了吧,array  retain了一次。

参考:http://blog.csdn.net/kmyhy/article/details/8571739#comments

https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md

http://liuyafang.blog.51cto.com/8837978/1543715

http://leopard168.blog.163.com/blog/static/16847184420138153296930/

《52个有效方法》


8.1题中已经说过weak了,其实它适用于iOS5以上,所以为了适配老版本,在iOS4以下是用的unsafe_unretained。也是表达非“拥有关系”,正如其名,也不安全,当目标对象遭到摧毁时,属性值不会自动清空,这一点与weak有区别的。

9,ARC下只有全局和堆block

0 0
原创粉丝点击