面试题之属性

  1. @property(nonatomic,copy)NSMutableArray *array;这个写法会出什么问题?

当一个NSMutableArray 对象使用initWithArray:初始化方法创建时,并将该对象赋值给了array属性。那么之后array执行可变数组的方法,比如:removeObjectAtIndex:时会出现unrecognized selector sent to instance 的崩溃。原因在于array属性在被赋值的时候默认执行了copy方法后变为了不可变NSArray对象。

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

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

也就是说我们每次在增加一个属性:

①系统都会在ivar_list中添加一个成员变量的描述;

②在method_list中增加setter与getter方法的描述;

③在属性列表中增加一个属性的描述;

④然后计算该属性在对象中的偏移量,然后产生setter与getter方法对应的实现,在setter方法中从偏移量的位置开始赋值,在getter方法中从偏移量开始取值,为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转。

  1. @synthesize 合成实例变量的规则是什么?假如property名为foo,存在一个名为_foo的实例变量,那么还会自动合成新变量么?

如果没有指定实例变量的名称,就会默认自动生成一个与属性同名的并在前面加一条下划线的实例变量。

如果指定了实例变量名称,刚好与属性自动合成的实例变量名称相同,那该属性就不自动合成实例变量了。

默认的是@synthesize foo = _foo,属性就不会自动生成实例变量了。

如果使用@synthesize foo = foo1;属性不会自动生成实例变量,而且成员变量被修改为foo1,使用点语法set属性成员变量的值会赋值给foo1,而不是foo。

  1. 能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?

1.不能向编译后得到的类增加实例变量

因为: 编译后的类已经注册在runtime中,类结构体中的objc_ivar_list实例变量的链表和instance_size实例变量的内存大小已经确定,runtime会调用class_setvarlayout或class_setWeaklvarLayout来处理strong weak引用.所以不能向存在的类中添加实例变量

2.能向运行时创建的类中添加实例变量

运行时创建的类是可以添加实例变量,调用class_addIvar函数.但是的在调用objc_allocateClassPair之后,objc_registerClassPair之前,原因同上.

  1. @synthesize和 @dynamic 的区别?

@synthesize:系统自动生成gettersetter属性声明。

@dynamic:告诉编译器,属性的获取与赋值方法由用户自己实现,不自动生成。

  1. 实例变量和成员变量的区别?

实例变量+基本数据类型变量=成员变量

实例变量是成员变量的一种!

  1. self.name 中的.在OC、C++有什么区别?

OC:是调用了namesetter/getter方法

C++:可以直接访问成员变量

  1. 在一个对象的方法里self.name = objectname = object有什么不同?

前者调用的是设置器方法,后者是普通赋值。

  1. 请说明并比较以下关键字:atomic,nonatomic

atomic

1.是默认的

2.会保证别的线程来访问这个属性之前,先执行完当前的线程

3.速度慢,因为要保证操作整体的完成

4.线程是相对安全的,只能说读写是安全,线程是不安全的,如果同时又线程调用[name release],就会出现 crash,因为 release 是不受 getter/setter 方法限制。

nonatomic

1.不是默认的

2.速度快

3.线程不安全

4.如果两个线程访问同一个属性,会出现无法预料的结果

  1. 如何让自己的类用copy修饰符?如何重写带copy关键字的setter?

①该类必须要实现NSCopying协议。实现-(id)copyWithZone:(NSZone *)zone;方法

②重写copy关键字的setter时,_name = [name copy];

  1. 怎么用copy关键字?

①一般使用retain或者strong修饰属性时,是使引用对象的指针指向同一个对象,即为同一块内存地址,只要其中有一个指针变量被修改时所有其他引用该对象的变量都会被改变。

②而使用copy关键字修饰在赋值时是释放旧对象,拷贝新对象内容。重新分配了内存地址,以后该指针变量被修改时就不会影响旧对象的内容了。

③copy只有实现NSCopying协议的对象类型才有效。

④常用于NSString和block。

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

使用copy的目的:

是为了让本对象的属性不受外界影响,使用copy无论给我传入是一个可变对象还是不可变对象,我本身持有的就是一个不可变的副本。

使用strong这个属性有可能指向一个可变对象,如果这个可变对象被外部意外的修改了,由于可变对象被改变之后起始地址不会发生变化。而附有strong修饰的属性依然指向这块内存地址,下次读取的时候就会是被改变以后的对象了,也就是说如果使用strong可能会被外部意外的修改。

  1. 什么情况使用weak关键字,相比assign有什么优势

①在ARC下使用block引起循环引用时,需要使用weak。

②属性使用IBOutlet时,使用weak关键字修饰。

③assign用于简单的赋值,不改变属性的引用计数,用于OC中的NSInteger,CGFloat。以及C语言中的int,float,double等数据类型。

④weak用于对象类型,同样不改变对象的引用计数且不持对象。当该对象废弃时,该弱引用失效并自动的将指针变量赋值为nil,可以避免循环引用。

  1. weak属性需要在dealloc中置nil么?

不需要,在ARC环境无论是强指针还是弱指针都无需在dealloc设置为nilARC会自动帮我们处理。

  1. 请说明并比较以下关键词:strongweakassign、copy

strong表示指向并拥有该对象。其修饰的对象引用计数会增加1.该对象只要引用计数不为0则不会被销毁。当然强行将其设为nil可以销毁它。

weak表示指向但不拥有该对象。其修饰的对象引用计数不会增加。无需手动设置,该对象会自行在内存中销毁。

assign主要用于修饰基本数据类型,如NSIntegerCGFloat,这些数值主要存在于栈上。

weak一般用来修饰对象,assign一般用来修饰基本数据类型。原因是assign修饰的对象被释放后,指针的地址依然存在,造成野指针,在堆上容易造成崩溃。而栈上的内存系统会自动处理,不会造成野指针。

copystrong类似。不同之处是strong的复制是多个指针指向同一个地址,而copy的复制每次会在内存中拷贝一份对象,指针指向不同地址。copy一般用在修饰有可变对应类型的不可变对象上,如NSStringNSArrayNSDictionary

  1. ARC下,不显示指定任何属性关键字时,默认的关键字都有哪些?

基本数据类型:atomicreadwriteassign

普通OC对象:atomicreadwritestrong

  1. @property后面可以有哪些修饰符?

线程安全:nonatomicatomic

内存管理:strongweakcopyretain

访问权限:readonlyreadwrite

指定方法名:getter=setter=

  1. OC中的类方法和实例方法有什么本质区别?

存储位置:类方法在元类对象中,实例方法在类对象中

调用者:类方法的调用者是类对象,实例方法是实例对象

成员变量:类方法不能访问,实例方法可以访问

对象方法:类方法不能访问,实例方法可以访问

self:类方法的 self 是类对象,实例方法的 self 是实例对象

你可能感兴趣的:(面试题之属性)