【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:方法就对容器内的元素也实现深拷贝,即完全深拷贝。
注意:使用该方法对于容器内的容器类元素内的元素不能实现深拷贝

相关推荐
ehviwer238 小时前
MathType7.9绿色和谐版激活补丁包下载
android·macos·ios·cocoa·媒体
ios and Android9 小时前
【iOS逆向与安全】frida-trace命令大全
开发语言·javascript·ios
Johnny Tong10 小时前
iOS 18 适配 Xcode 16 问题
ios·cocoa·xcode
awonw10 小时前
[网络][CISCO]CISCO IOS升级
网络·ios
一只不会编程的猫12 小时前
高德地图绘图,点标记,并计算中心点
开发语言·ios·swift
sumatch14 小时前
Mac 创建 Python 虚拟环境
开发语言·python·macos
tubage202318 小时前
图像放大的软件PhotoZoom 9新功能介绍及安装激活使用指南
macos·电脑·photozoom·photozoom9
顶顶年华正版软件官方18 小时前
格式化u盘选择FAT还是NTFS U盘和硬盘格式化两者选谁
macos·ntfs格式
缘友一世20 小时前
mac系统安装最新(截止2024.9.13)Oracle JDK操作记录
java·macos·oracle
AUV110720 小时前
CleanClip for Mac 剪切板 粘贴工具 历史记录 安装(保姆级教程,新手小白轻松上手)
macos·mac·剪贴板·clipboard·剪贴板增强·复制历史·最强应用