【iOS】属性关键字

目录

深浅拷贝

自定义类

容器类深拷贝

属性关键字

原子操作

atomic

nonatomic

读写权限

readwrite

readonly

内存管理

weak

assign

strong

retian

copy

strong与copy

补充

属性关键字格式

ARC下@property的默认属性


深浅拷贝

关于深浅拷贝,笔者在之前已经有博客进行过详细的阐述,下面附上深浅拷贝的链接

深浅拷贝

在这篇博客中,笔者讲述了深浅拷贝的基本概念和区别,也解释了一些有关于容器类深拷贝的知识,这里来做一些补充。

自定义类

自定义类无论是copy还是mutablecopy都为深拷贝,因为自定义类没有copyWithZone:和mutableCopyWithZone:两个方法,需要遵守NSCopying和NSMutableCopying协议自己实现这两个拷贝方法。

容器类深拷贝

容器类对象的深拷贝分为两种,一种是单层深拷贝,另一种是完全深拷贝。

  • 单层深拷贝:对于副本对象本身是深拷贝,但是容器中的所有对象都是浅拷贝
  • 完全深拷贝:对于副本对象本身与其里面的所有对象都是深拷贝

非可变容器类在mutablecopy时是单层深拷贝,可变容器类在使用copy和mutablecopy时都是单层深拷贝,那么要如何才能实现容器类的完全深拷贝呢?

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

比如:dataArray3 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:dataArray2]]

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"],
                              [NSMutableString stringWithString:@"four"],
                              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);
}

这段代码容器类对象使用mutablecopy,输出的结果是修改array2中的元素,array3也会发生改变,说明这是单层深拷贝,也就是说对于array2和array3是深拷贝,而对于数组中的元素却还是浅拷贝。

如果使用initWithArray:copyItems:方法呢?

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"],
                              [NSMutableString stringWithString:@"four"],
                              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);
    NSLog(@"array4:%@", array4);
}

可以看出,array4实现了完全深拷贝。

那如果是针对于容器类里的容器类对象呢?

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"],
                              [NSMutableString stringWithString:@"four"],
                              array1,
                              nil];
    NSMutableArray* array3 = [array2 mutableCopy];
    NSMutableArray* array4 = [[NSMutableArray alloc] initWithArray:array2 copyItems:YES];
    NSMutableString* mutableString;
    mutableString = array2[0];
    [mutableString appendString:@"--ONE"];
    NSMutableString* mutableString1;
    NSMutableArray* mutableArray = array2[4];
    mutableString1 = mutableArray[0];
    [mutableString1 appendString:@"--ONE"];
    NSLog(@"array3:%@", array3);
    NSLog(@"array2:%@", array2);
    NSLog(@"array4:%@", array4);
}

可以看出容器类中的容器类对象使用initWithArray:copyItems:只能实现单层的深拷贝。

属性关键字

@property

@synthesize

@dynamic

这三个关键字是有关于属性自动合成存取方法的关键字:

用 @property 语法来声明属性。@property 会帮我们自动生成属性的 setter 和 getter 方法的声明

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

@dynamic告诉编译器不用自动进行 @synthesize,你会在运行时再提供这些方法的实现,无需产生警告

现在的版本已经不再需要@synthesize 编译器会自动合成存取方法。

下面是一些修饰属性的关键字

原子操作

原子操作:属性是否有原子性可以理解为线程是否安全

atomic

原子性,加同步锁,默认修饰符。 使用atomic会损耗性能,也不一定保证线程安全。如果保证线程安全需要使用其他锁机制。

nonatomic

非原子性,不实用同步锁。 声明属性时基本设置为nonatomic。使用nonatomic能够提高访问性能。

读写权限

读写权限不写时默认为 readwrite

readwrite

属性拥有setter方法和getter方法

readonly

仅有getter方法

内存管理

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。

retian

  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可以理解为深浅拷贝的区别

补充

属性关键字格式

推荐按照下面的格式来定义属性

objectivec 复制代码
@property (nonatomic, readwrite, copy) NSString *name;

属性的修饰符应该按照上面的顺序排列:原子操作、读写权限、内存管理

ARC下@property的默认属性

对于基本数据类型:atomic、readwrite、assign

对于普通的Objective-C对象:atomic、readwrite、strong

相关推荐
HarderCoder10 小时前
iOS 知识积累第一弹:从 struct 到 APP 生命周期的全景复盘
ios
使一颗心免于哀伤21 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
叽哥21 小时前
Flutter Riverpod上手指南
android·flutter·ios
用户092 天前
SwiftUI Charts 函数绘图完全指南
ios·swiftui·swift
YungFan2 天前
iOS26适配指南之UIColor
ios·swift
权咚3 天前
阿权的开发经验小集
git·ios·xcode
用户093 天前
TipKit与CloudKit同步完全指南
ios·swift
法的空间3 天前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
_落纸3 天前
三大基础无源电子元件——电阻(R)、电感(L)、电容(C)
笔记
2501_915918413 天前
iOS 上架全流程指南 iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传 ipa 与审核实战经验分享
android·ios·小程序·uni-app·cocoa·iphone·webview