【iOS】属性关键字

属性关键字

前言

在前期的学习中学习到了一些属性关键词的用法,今天来通过这篇博客对属性关键字进行一个总结,同时复习一下深浅拷贝的内容。

属性关键字

  1. @property: 声明属性,帮我们自动生成属性的setter和getter方法的声明。

  2. @synthesize: 帮我们自动生成setter和getter方法的实现以及合成实例变量。

  3. @dynamic: 告诉编译器不用自动进行@synthesize,会在运行时在提供这些方法的实现 ,不产生警告,同时他不会影响 @property 生成的 setter 和 getter 方法的声明。

现在编译器会自动帮我们的每一个@property添加@synthesize。

原子操作

可以将属性是否有原子性理解成线程是否安全。

  • atomic
    原子性,加同步锁,默认修饰符。 使用atomic会损耗性能,也不一定保证线程安全。如果保证线程安全需要使用其他锁机制。
  • nonatomic
    非原子性,不实用同步锁。 声明属性时基本设置为nonatomic。使用nonatomic能够提高访问性能,访问速度更快。

读写权限

  • readwrite
    属性拥有setter方法和getter方法
  • readonly
    仅有getter方法

默认为readwrite方法

内存管理

weak

  1. ARC 下才能使用;
  2. 修饰弱引用,不增加对象引用计数,主要可以用于避免循环引用;
  3. weak 修饰的对象在被释放之后,会自动将指针置为 nil,不会产生悬垂指针;

assign

  1. 既可以修饰基本数据类型,也可以修饰对象类型;
  2. setter 方法的实现是直接赋值,一般用于基本数据类型
  3. 修饰对象类型时,不增加其引用计数;
  4. 会产生悬垂指针(悬垂指针:assign 修饰的对象在被释放之后,指针仍然指向原对象地址,该指针变为悬垂指针。这时候如果继续通过该指针访问原对象的话,就可能导致程序崩溃)。

strong

  1. ARC 下才能使用;
  2. 原理同 retain;
  3. 但是在修饰 block 时,strong 相当于 copy,而 retain 相当于 assign。

retain

  1. MRC 下使用,ARC 下基本使用 strong;
  2. 修饰强引用,保留新值,释放旧值,再设置新值,同时将新对象的引用计数加 1;
  3. setter 方法的实现是 release 旧值,retain 新值,用于 OC 对象类型。

copy

setter 方法的实现是 release 旧值,copy 新值。用于 NSString、NSArray、NSDictionary 是为了保证赋值后是一个不可变对象,以免遭外部修改而导致不可预期的结果。

strong与copy

如果属性声明中指定了copy特性,合成方法会使用类的copy方法。
相同点: 用于修饰标识拥有关系的对象

不同点: strong的赋值是多个指针指向同一个地址,而copy的复制就是每次会在内存中复制一份对象,指针指向不同的地址。

strong与copy可以理解为深浅拷贝的区别。

深浅拷贝

笔者前期的学习中总结过一次深浅拷贝的内容【OC】深浅拷贝,这里对之前没有总结到位的地方进行一个补充说明。

自定义类

自定义对象实现copy、mutableCopy均为深拷贝,由于自定义的对象没有copyWithZone:和mutableCopyWithZone:两个方法,需要遵守NSCopying和NSMutableCopying协议来实现这两个方法。

容器类深拷贝

容器类深拷贝主要分为单层深拷贝和完全深拷贝两个类型。

单层深拷贝:对于副本对象是深拷贝,但是容器中的所有对象都是浅拷贝。

完全深拷贝:对于副本对象和容器中的所有对象都是深拷贝。

对于非可变类容器来说,mutablecopy时是单层深拷贝,可变类容器在使用copy和mutablecopy时都是单层深拷贝 ,当容器类对象中的对象是自定义对象或不为immutable对象,使用initWithArray:copyItems:方法(第二个参数设置为YES)可以实现完全深拷贝;当容器内对象是容器类时,使用initWithArray:copyItems:方法(第二个参数设置为YES)可以实现单层浅拷贝,这时就需要使用归档和解档来实现完全深拷贝。

objectivec 复制代码
-(void) test
{
    NSMutableArray* array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"1"],
                                  [NSMutableString stringWithString:@"2"],
                                  [NSMutableString stringWithString:@"3"],
                                  [NSMutableString stringWithString:@"4"],
                                  nil];
        NSMutableArray* array2 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"one"],
                                  [NSMutableString stringWithString:@"two"],
                                  [NSMutableString stringWithString:@"three"],
                                  array1,
                                  nil];
        NSMutableArray* array3 = [array2 mutableCopy];
        //NSMutableArray* array4 = [[NSMutableArray alloc] initWithArray:array2 copyItems:YES];
        NSMutableString* mutableString;
        mutableString = array2[0];
        [mutableString appendString:@"-ONE"];
        NSLog(@"array3:%@", array3);
        NSLog(@"array2:%@", array2);
}

效果图

可以看到,这里对容器内的元素实现的还是浅拷贝,并没有实现深拷贝。

objectivec 复制代码
-(void) test
{
    NSMutableArray* array1 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"1"],
                                  [NSMutableString stringWithString:@"2"],
                                  [NSMutableString stringWithString:@"3"],
                                  [NSMutableString stringWithString:@"4"],
                                  nil];
        NSMutableArray* array2 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"one"],
                                  [NSMutableString stringWithString:@"two"],
                                  [NSMutableString stringWithString:@"three"],
                                  array1,
                                  nil];
        NSMutableArray* array3 = [array2 mutableCopy];
        NSMutableArray* array4 = [[NSMutableArray alloc] initWithArray:array2 copyItems:YES];
        NSMutableString* mutableString;
        mutableString = array2[0];
        [mutableString appendString:@"-ONE"];
        NSLog(@"array2:%@", array2);
        NSLog(@"array4:%@", array4);
}

这里使用initWithArray:copyItems:方法就对容器内的元素也实现深拷贝,即完全深拷贝。
注意:使用该方法对于容器内的容器类元素内的元素不能实现深拷贝

相关推荐
非专业程序员Ping3 小时前
一文读懂字符、字形、字体
ios·swift·font
2501_915921434 小时前
iOS 应用代上架流程,多工具组合与使用 开心上架 跨平台自动化上传指南
android·ios·小程序·uni-app·自动化·cocoa·iphone
日日行不惧千万里4 小时前
2025最新仿默往 IM 即时通讯系统源码(PC + Web + iOS + Android)完整版发布!
android·ios
歪歪1004 小时前
React Native开发Android&IOS流程完整指南
android·开发语言·前端·react native·ios·前端框架
阿里超级工程师5 小时前
ios云打包证书申请不需要苹果电脑也是可以的
ios·证书·云打包
前端架构师-老李6 小时前
Java开发—JDK的安装和版本管理(macOS)
java·开发语言·macos
Digitally6 小时前
如何将 Android 联系人备份到 Mac 的 4 种简单
android·macos
2501_915918417 小时前
iOS 混淆与 IPA 加固一页式行动手册(多工具组合实战 源码成品运维闭环)
android·运维·ios·小程序·uni-app·iphone·webview
一勺菠萝丶8 小时前
在 macOS 上用 Docker 为 Java 后端 & 常见开发需求搭建完整服务(详尽教程)
java·macos·docker
RollingPin10 小时前
iOS八股文之 网络
网络·网络协议·ios·https·udp·tcp·ios面试