OC面试题 -- 属性的问题

文章目录

  • 1. @property的本质是什么
  • 2. ivar、getter、setter是如何生成并添加到这个类中的
  • 3. @protocol 和 category 中如何使用 @property
  • 4. @synthesize 和 @dynamic 分别有什么作用?
  • 5. 属性关键字assign、retain、weak、copy
  • 6. strong和weak关键字有什么区别
  • 7. 什么情况下使用weak关键字?相比于assign有什么不同?
  • 8. atomic(原子性)和nonatomic(非原子性)区别

1. @property的本质是什么

@property的本质 = ivar (实例变量) + getter (取方法) + setter (存方法)

2. ivar、getter、setter是如何生成并添加到这个类中的

  • “自动合成”( autosynthesis)

这是编译器自动合成的,通过@synthesize 关键字指定,若不指定,默认为@synthesize propertyName = _propertyName;若手动实现了getter/setter 方法,则不会自动合成。

现在编译器已经默认为我们添加了@synthesize propertyName = _propertyName;因此不再手动添加了,除非你真的要改变成员变量名字。

生成getter方法时,会判断当前属性名是否有“_”,比如声明属性为@property(nonatomic,copy)NSString *_name;那么所生成的成员变量名就会变成“name”,如果我们要手动生成getter 方法,就要判断是否以“”开头了。

  • @synthesize:为属性创建带“_”的成员变量,同时生成getter和setter方法

在类的实现代码里通过 @synthesize语法来指定实例变量的名字.

@implementation Person 
@synthesize firstName = _myFirstName; 
@end

3. @protocol 和 category 中如何使用 @property

  1. 在protocol中使用property只会生成setter和getter方法声明,我们使用属性的目的,是希望遵守我协议的对象能实现该属性。
    在实现 protocol 的类中如果要使用 property 对应的实例变量,需要做一下 @synthesize var = _var;
  2. category使用@property也是只会生成setter和getter方法的声明,如果我们真的需要给category增加属性的实现,需要借助于运行时的两个函数:
    obj_setAssociatedObject
    obj_getAssociatedObject
    示例
    // MyView+MyCategory.h
    #import "MyView.h"

    @interface MyView (MyCategory)

    // 在 Category 中定义属性:
    @property (assign, nonatomic) int32_t viewIndex;

    @end

    // MyView+MyCategory.m
    #import "MyView+MyCategory.h"
    #import 

    // 标记属性的 Key:
    static const void *ViewIndexKey = &ViewIndexKey;

    @implementation MyView (MyCategory)

    @dynamic viewIndex;

    - (void)setViewIndex:(int32_t)viewIndex {
        objc_setAssociatedObject(self, ViewIndexKey, @(viewIndex), OBJC_ASSOCIATION_ASSIGN);
    }

    - (int32_t)viewIndex {
        return [objc_getAssociatedObject(self, ViewIndexKey) intValue];
    }

    @end

4. @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 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。

5. 属性关键字assign、retain、weak、copy

assign:用于基本数据类型和结构体。如果修饰对象的话,当销毁时,属性值不会自动置nil,可能造成野指针。
weak:用来修饰OC对象。对象引用计数为0时,属性值也会自动置nil
retain:强引用类型,ARC下相当于strong,但block不能用retain修饰,因为等同于assign不安全。
strong:强引用类型,修饰block时相当于copy。

copy

  1. block 是在栈区分配内存,由系统管理,使用copy拷贝到堆区 避免被释放
  2. NSString NSArray NSDictionary 存在对应的可变类型
    可变字符串 copy -> 不可变字符串

6. strong和weak关键字有什么区别

  1. 针对于对象的
  2. strong是强指针,持有对象的所有权
  3. weak是弱指针,不持有对象所有权

7. 什么情况下使用weak关键字?相比于assign有什么不同?

  1. 委托 为了规避循环引用,使用weak限定delegate 指针
  2. StoryBoard Xib 拖拽控件,可以使用weak关键字限定属性

与assign的区别

  1. weak只能修饰对象指针,assign可以修饰任意类型的指针
  2. weak指针指向的对象如果被释放,weak指针自动置为nil,assgin不会自动置为nil

基本数据类型用weak来修饰
Xcode会直接提示错误,信息如下

Property with 'weak' attribute must be of object type

对象使用assign来修饰
编译没有问题,运行也没有问题。
weak修饰的对象,当对象释放后,即引用计数为0时,对象会置为nil
复制代码而向nil发送消息是没有问题的,不会崩溃。
assign修饰的对象,当对象释放之后,即引用计数为0时,对象会变为野指针,不知道指向哪,再向对象发消息,非常容易崩溃。
 

8. atomic(原子性)和nonatomic(非原子性)区别

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

你可能感兴趣的:(面试题,ios,objective-c)