iOS面试题-每日十道-第九天

一. @property的本质是什么?ivar,getter.setter是如何生成并添加到这个类中的.

property在编译时编译器会自动的为我们生成一个私有成员变量和setter与getter方法的声明和实现.反编译property大致生成五个东西

  • OBJC IVAR $类名$属性名称 该属性的偏移量
  • setter与getter方法对应的实现函数
  • ivar_list就是成员变量列表
  • method_list方法列表
  • prop_list 属性列表
    也就是说我们每次增加一个属性,系统都会在ivar_list中添加一个成员变量的描述,在method_list中增加setter与getter方法的描述,在属性列表中增加一个属性的描述,然后计算该属性在对象中的偏移量,然后产生setter与getter方法对应的实现,在setter方法方法中从偏移量的位置开始赋值,在getter方法中从偏移量开始取值,为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转。

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

@property有两个对应的词,一个是@synthesize,一个是@dynamic。如果@synthesize和@dynamic都没写,那么默认的就是@syntheszie var = var,var为property变量。可以手动修改属性var对应的实例变量。例如:@syntheszie var = var1

      @synthesize的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法, 在Xcode4.4之后的版本可以省略不写.

      @dynamic告诉编译器不要自动生成成员变量的getter和setter方法,而是开发者自己手工生成或者运行时生成.

三. 用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?

使用copy的目的是为了让本对象的属性不受外界影响,使用copy无论给我传入一股可变对象还是不可对象,我本身就是一股不可变副本.
如果使用strong.这个属性有可能指向一个可变对象,如果这个可变对象呗外部意外的修改了,由于可变对象呗改变之后起始地址不会发生变化.而strong修饰的属性依然会指向这块内存地址,下次读取的时候就会是被改变以后的对象了, 也就是说strong可能会被外部意外修改.

四. 属性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那种情况下用?

  • readwrite 是可读可写特性;需要生成getter方法和setter方法时
  • readonly 是只读特性 只会生成getter方法 不会生成setter方法 ;不希望属性在类外改变
  • assign 是赋值特性,setter方法将传入参数赋值给实例变量;仅设置变量时;
  • retain 表示持有特性,setter方法将传入参数先保留,再赋值,传入参数的retaincount会+1;
  • copy 表示赋值特性,setter方法将传入对象复制一份;需要完全一份新的变量时。
  • nonatomic 非原子操作,决定编译器生成的setter getter是否是原子操作,atomic表示多线程安全,

一般使用nonatomic

五. 原子(atomic)跟非原子(non-atomic)属性有什么区别?

  • atomic提供多线程安全。是防止在写未完成的时候被另外一个线程读取,造成数据错误
  • non-atomic:在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了 nonatomic ,
    那么访问器只是简单地返回这个值。

六. 在iOS应用中如何保存数据

  • 通过web服务, 保存在服务器上
  • 通过NSCoder固化机制,讲对象保存在文件中
  • 通过Sqlite或CoreData保存在文件数据库中

七. 关键字volatile有什么含义?并给出三个不同例子

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,
  优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

下面是volatile变量的几个例子:
  1) 并行设备的硬件寄存器(如:状态寄存器)
  2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
  3)多线程应用中被几个任务共享的变量

八. 一个指针可以是volatile么?解释为什么

可以是
尽管这种情况并不常见,但它还是可以,例如
当一个中断服务子程序企图去修改一个指向一个buffer指针的时候.

九. 谈谈obj - c的优缺点

优点

  • 分类特有语法.可以在不改变原有类的基础上,增加新的方法.
  • 动态识别
  • 弹性讯息传递
  • objective -C 和 C++可混合编程

缺点

  • 不支持命名空间机制:须在其类别名称加上前缀,时常引致冲突.
  • 不支持运算符重载(所谓重载,就是重新赋予新的含义。例如,大 家都 已习惯于用加法运算符”+”对整数、单精度数和双精度数进行加法运算,如5+8, 5.8 +3.67等,其实计算机对整数、单精度数和双精度数的加法操作过程是很不相同的, 但由于C++已经对运算符”+”进行了重载,所以就能适用于int, float, doUble类型的运算。)
  • 不支持多重继承
  • 弱语言,很多错误发生在运行时,不方便调试.

十. 堆和栈的区别

栈:向低地址扩展的数据结构,是一块连续的内存的区域。栈顶的地址和栈的最大容量是 系统预先规定好的,从栈获得的空间较小。
堆:向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

  • 碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出
  • 分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由 alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
  • 分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。

你可能感兴趣的:(iOS面试题-每日十道-第九天)