本文参考资料有:
《招聘一个靠谱的iOS》面试题参考答案(上)
一、NSUInteger 、NSINteger、int、NSNumber的区别和联系
- int和NSInteger是差不多的,但是用int声明的时候要考虑设备,32位机里面是int类型,64位里面就有可能是long型,而用NSUInteger 、NSINteger不用考虑这个问题,会自动判别。
- NSUInteger是无符号的,没有负数,NSINteger是有符号的。例如
NSUInteger row = [indexPath row];
也就是说,NSUInteger常用于索引值。
- NSNumber是NSValue的一个子类,是一个对象来存储数字值包括bool型,它提供了一系列方法来存储char asigned or unsigned char, short int, long int, long long int, float, or double or as a BOOL, 它提供了一个compare:方法来决定NSNumber对象的排序。
- NSNumber类有点类似id类型,对于任何类型的数字对象都能用它来声明,通过声明,很难判断声明变量是什么数字类型,确定数字对象类型是在初始化的时候才能确定。
数字对象的创建或初始化:
NSNumber *数字对象 = [NSNumber numberWith数字类型:数值];
NSNumber *intNumber = [NSNumber numberWithInt:5];
NSNumber *longNumber = [NSNumber numberWithLong:0xabcdef];
NSNumber *floatNumber = [NSNumber numberWithFloat:11.11];
- NSUInteger 、NSINteger、int都是基本类型,声明的时候都不带*号。NSNumber是一个类,如果需要存储一个数值,直接使用NSINteger时不行的,比如在一个数组里面使用下面的语句就会报错:
NSMutableArray *array = [NSMutableArray arrayWithCapacity:0];
[array addObject:4];
因为array里面应该是一个类,但4不是,所以需要NSNumber:
NSMutableArray *array = [NSMutableArray arrayWithCapacity:0];
[array addObject:[NSNumber numberWithInteger:5]];
当然也可以用NSNumber的@语法糖来写:
NSArray *array = @[@1, @2,@3];
二、什么情况使用weak关键字,相比assign有什么不同?
- 在ARC中,在有可能出现循环引用的时候,要通过让其中一端使用weak来解决,比如:delegate代理属性;
- 自身已经对它进行一次强引用,必有必要再强引用一次,此时也会用weak,自定义OBOutlet控件属性一般也使用weak;当然也可以使用strong;
- weak 此特质表明该属性定义了一种"非拥有关系"(nonowning relationship),为这种属性设置新值时,设置方法既不保留新值,也不释放旧值.此特质与assign类似,但在属性所指的对象遭到摧毁时,属性值也会清空(nil out),而assign的"设置方法"只会执行针对"纯量类型(scalar type, 如 CGFloat 或 NSInteger等)"的简单赋值操作
- assign可以用于非OC对象,而weak必须用于OC对象.
三.怎么使用copy关键字?
- NSString NSArray NSDictionary等等经常使用copy关键字,因为它们有对应的可变类型:NSMutableString NSMutableArray NSMutableDictionay;
- block也经常使用copy关键字,block使用copy时MRC遗留下来的"传统",在MRC中,方法内部的block在栈区,使用copy可以把它放到堆区,在ARC中写不写都行:对于block使用copy还是strong效果是一样的,但写成copy也无妨,还提醒我们:编译器自动对block进行了copy操作.
- copy此特质所表达的所属关系与strong类似,但设置方法并不保留新值,而是将其"拷贝(copy)".当属性类型位NSString时,经常用此特质来保护其封装性,因为传递给设置方法的新值可能指向一个NSMutableString类的实例,这个类是NSString的子类,表示一种可修改值的字符串,此时若是不拷贝字符串,那设置完属性之后,字符串的值就可能会在对象不知情的情况下遭到更改,所以要拷贝一份"不可变"(immutable)字符车,确保对象中的字符串值不会无意间变动.只要实现属性所用的对象是"可变的"(mutable),就应该在设置新属性值时copy一份
- 如果要想让自己所写的对象具有copy功能,需要实现NSCopying协议.如果自定义的对象分为可变版本与不可变版本,那么就要同时实现NSCopying与NSMutableCopying协议
四.@property中有哪些属性关键字?/ @property 后面可以有哪些修饰符?
属性可以拥有的特质分为四类:
- 原子性---nonatomic特质
在默认情况下,由编译器合成的方法会通过锁定机制确保其原子性(atomicity)。如果属性具备nonatomic特质,则不使用同步锁。请注意,尽管没有名为“atomic”的特质(如果某属性不具备nonatomic特质,那它就是“原子的” ( atomic) ),但是仍然可以在属性特质中写明这一点,编译器不会报错。若是自己定义存取方法,那么就应该遵从与属性特质相符的原子性。 - 读/写权限---readwrite(读写)、readooly (只读)
- 内存管理语义---assign、strong、 weak、unsafe_unretained、copy
方法名---getter=、setter=
getter=的样式:
@property (nonatomic, getter=isOn) BOOL on;
( setter=这种不常用,也不推荐使用。故不在这里给出写法。)
- 不常用的:nonnull,null_resettable,nullable
五@synthesize和@dynamic分别有什么作用?
- @property有两个对应的词,一个是@synthesize,一个是@dynamic。如果@synthesize和@dynamic都没写,那么默认的就是@syntheszie var = _var;
- @synthesize的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法。
- @dynamic告诉编译器:属性的setter与getter方法由用户自己实现,不自动生成。(当然对于readonly的属性只需提供getter即可)。假如一个属性被声明为@dynamic var,然后你没有提供@setter方法和@getter方法,编译的时候没问题,但是当程序运行到instance.var = someVar,由于缺setter方法会导致程序崩溃;或者当运行到 someVar = var时,由于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
六.ARC下,不显式指定任何属性关键字时,默认的关键字都有哪些?
对应基本数据类型默认关键字是
- atomic,readwrite,assign
对于普通的OC对象
- atomic,readwrite,strong
用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?
- 因为父类指针可以指向子类对象,使用copy的目的是为了让本对象的属性不受外界影响,使用copy无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.
- 如果我们使用是strong,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性.
copy此特质所表达的所属关系与strong类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。 当属性类型为NSString时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个NSMutableString类的实例。这个类是NSString的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。
为了理解这种做法,首先要知道,对非集合类对象的copy操作:
在非集合类对象中:对immutable对象进行copy操作,是指针复制,mutableCopy操作时内容复制;对mutable对象进行copy和mutableCopy都是内容复制。用代码简单表示如下:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //深复制
[mutableObject copy] //深复制
[mutableObject mutableCopy] //深复制
比如以下代码:
NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy
NSString *stringCopy = [string copy];
查看内存,会发现 string、stringCopy 内存地址都不一样,说明此时都是做内容拷贝、深拷贝。即使你进行如下操作:
[string appendString:@"origion!"]
stringCopy的值也不会因此改变,但是如果不使用copy,stringCopy的值就会被改变。 集合类对象以此类推。 所以,用@property声明 NSString、NSArray、NSDictionary 经常使用copy关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份。
网友评论