美文网首页
Objctive-C - 基础知识点整理(持续更新)

Objctive-C - 基础知识点整理(持续更新)

作者: 75b9020bd6db | 来源:发表于2019-10-23 12:03 被阅读0次
    1.请说明并比较以下关键词:strong, weak, assign, copy, unsafe_unretained
    • strong: 表示指向并强引用该对象,其修饰的对象引用计数会增加1。该对象只要引用计数不为0则不会被销毁。当然强行将其设为nil可以销毁它
    • weak: 表示弱引用对象,指向但不拥有该对象。其修饰的对象引用计数不会增加。当对象消失后指针自动指向nil,所以这里也就防止了野指针的存在。
    // 测试 weak 和 strong
    @property (nonatomic, strong) Person *strongPerson;
    @property (nonatomic, weak) Person *weakPerson;
    
    // 测试代码
    self.strongPerson = [Person new];
    self.weakPerson = self.strongPerson;
    self.strongPerson = nil; 
    NSLog(@"strongStr = %@, weakStr = %@", self.strongPerson, self.weakPerson);
    
    // 打印结果:说明weak修饰的属性并不会使引用计数增加
    strongStr = (null), weakStr = (null)
    

    稍微改一下代码:

    self.strongPerson = [Person new];
    self.weakPerson = self.strongPerson;
    self.weakPerson = nil;
    NSLog(@"strongStr = %@, weakStr = %@",self.strongPerson, self.weakPerson);
    
    // 打印结果:说明weak修饰的属性只是对对象的弱引用,并不会真正的持有该对象。
    strongStr = <Person: 0x600000007c40>, weakStr = (null)
    

    再次修改代码验证:

    Person *p = [Person new];
    self.strongPerson = p;
    self.weakPerson = self.strongPerson;
    p = nil;
    NSLog(@"strongStr = %@, weakStr = %@",self.strongPerson, self.weakPerson);
    
    //打印结果:说明strong属性会强引用该对象并使该对象的引用计数+1,
    //所以即使把p设置为nil,该对象也并没有释放,要想释放该对象,
    //还得把strongStr设置为nil
    strongStr = <Person: 0x600000200b40>, weakStr = <Person: 0x600000200b40>
    
    self.strongPerson = nil;
    // 打印结果:
    strongStr = (null), weakStr = (null)
    
    • assign: 主要用于修饰基本数据类型,如NSIntegerCGFloat,这些数值主要存在于栈上,统一由系统进行内存管理。
    • weakassign对比:weak 一般用来修饰对象,assign一般用来修饰基本数据类型。原因是assign修饰的对象被释放后,指针的地址依然存在,造成野指针,在堆上容易造成崩溃。而栈上的内存系统会自动处理,不会造成野指针。
    • copystrong对比:copystrong类似,不同之处是strong的复制是多个指针指向同一个地址,而copy的复制每次会在内存中拷贝一份对象,指针指向不同地址。copy一般用在修饰有可变对应类型的不可变对象上,如NSString, NSArray, NSDictionary
    • unsafe_unretained:跟 weak 类似,声明一个弱引用,但是当引用计数为 0 时,变量不会自动设置为 nil,不过现在基本不用,都用weak了。
    • Objective-C 中,基本数据类型的默认关键字是atomic, readwrite, assign;对象属性的默认关键字是atomic, readwrite, strong
    再来看看copy关键字
    // 在ViewController里面加个属性:
    @property (nonatomic, copy) NSObject *c;
    
    // 在.m中
    NSObject *a = [[NSObject alloc]init];
    self.c = a;
    a = nil;
    NSLog(@"%@",self.c);
    

    毫无疑问,输出结果不为nil:
    <NSObject: 0x600000010e80>

    • 注意:在使用 NSMutableArray, NSMutableDictionary等可变集合对象的时候,千万不要用copy进行修饰,这里用copy很可能会出错,因为当你给该属性赋值时,它会自动调用对象的copy方法,从而将可变集合转换成不可变集合,把一个不可变集合赋值给一个可变集合,再调用addObject等方法就会报错,因为变成了不可变对象。
    2.请说明并比较以下关键词:__weak__block

    *__weakweak基本相同。前者用于修饰变量(variable),后者用于修饰属性(property)。__weak 主要用于防止block中的循环引用。

    • __block也用于修饰变量。它是引用修饰,所以其修饰的值是动态变化的,即可以被重新赋值的。__block用于修饰某些block内部将要修改的外部变量。
    • __weak__block的使用场景几乎与block息息相关。而所谓block,就是Objective-C对于闭包的实现。闭包就是没有名字的函数,或者理解为指向函数的指针。
    3. 请说明并比较以下关键词:atomatic, nonatomic
    • atomic修饰的对象会保证settergetter的完整性,任何线程对其访问都可以得到一个完整的初始化后的对象。因为要保证操作完成,所以速度慢。它比nonatomic安全,但也并不是绝对的线程安全,例如多个线程同时调用setget就会导致获得的对象值不一样。绝对的线程安全就要用关键词synchronized
    • nonatomic修饰的对象不保证settergetter的完整性,所以多个线程对它进行访问,它可能会返回未初始化的对象。正因为如此,它比atomic快,但也是线程不安全的。
    4. 请说明并比较synthesize和@dynamic,分别有什么作用?

    我们平时完成属性定义后,编译器自动编写访问这些属性所需的方法,用以访问给定类型中具有给定名称的变量,这个过程叫做“自动合成”( autosynthesis),简单讲就是:@property = getter + setter

    @interface Person : NSObject
    @property NSString *firstName;
    @property NSString *lastName;
    @end
    

    上述代码与下面等效:

    @interface Person : NSObject
    - (NSString *)firstName;
    - (void)setFirstName:(NSString *)firstName;
    - (NSString *)lastName;
    - (void)setLastName:(NSString *)lastName;
    @end
    

    上面的过程由编译器在编译期间帮我们完成,所以编辑器里看不到这些“合成方法”(synthesized method)的源代码。除了生成方法代码 gettersetter之外,编译器还要自动向类中添加对应类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。在前例中,会生成两个实例变量,其名称分别为 _firstName_lastName。当然我们也可以在类的实现代码里通过@synthesize语法来指定实例变量的名字。

    @implementation Person
    @synthesize firstName = _myFirstName;
    @synthesize lastName = myLastName;
    @end
    

    @property有两个对应的词,一个是@synthesize,一个是@dynamic。如果两个都没写,那么默认就是@syntheszie var = _var;

    • @synthesize的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法。

    • @dynamic告诉编译器:属性的settergetter方法由用户自己实现,不自动生成(对于readonly的属性只需提供getter即可; 假如一个属性被声明为@dynamic var,然后你没有提供@setter方法和@getter方法,编译的时候没问题,但是当程序运行到instance.var = someVar,由于缺setter方法会导致程序崩溃;或者当运行到 someVar = var时,由于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定

    5. 什么是ARC
    • ARC全称是 Automatic Reference Counting,是Objective-C的内存管理机制。简单地来说,就是代码中自动加入了retain/release,原先需要手动添加的用来处理内存管理的引用计数的代码可以自动地由编译器完成了。

    • ARC的使用是为了解决对象retainrelease匹配的问题。以前手动管理造成内存泄漏或者重复释放的问题将不复存在。

    • 以前需要手动的通过retain去为对象获取内存,并用release释放内存。所以以前的操作称为MRC (Manual Reference Counting)

    相关文章

      网友评论

          本文标题:Objctive-C - 基础知识点整理(持续更新)

          本文链接:https://www.haomeiwen.com/subject/febfvctx.html