IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【iOS】—— 属性关键字 -> 正文阅读

[移动开发]【iOS】—— 属性关键字

一.属性的含义

属性的本质就是:实例变量 + get方法 + set方法
众多属性关键字是对自动生成的get、set方法进行了修饰。

二.属性的功能

1.给现有的成员变量生成一对setter/getter方法。
2.如果没有声明成员变量,自动声明一个_属性名的私有变量(默认成员变量是受保护的)。

三.基本属性关键字

我们常用的属性关键字有:assign,weak,unsafe_unretained,strong,retain ,copy,readonly,readwrite , nonatomic,natomic及 __weak,__block ,@synthesize 和 @dynamic。

assign:(默认关键字)一般用来修饰基本数据类型,例如double,int等。

unsafe_unretained:与assign类似。

1.MRC:手动管理内存

retain:对象的属性声明,保存引用计数,如果别的对象使用当前对象,则该对象的引用计数加1,即两个对象同时指向同一块内存。

2.ARC:自动管理内存

strong:强指针,增加一个对象的引用权限(引用计数加1

weak:弱指针,不会增加对象的引用权限,不会影响对象是否释放,不能修饰基本数据类型,只能修饰对象类型。相对于assgin,unsafe_unretained在使用上更安全不会出现野指针情况,因为weak在指向的对象释放后会被自动赋值为nil。

strong和weak应用在对象类型的属性里面。
ARC下可以使用retain,copy。

3.不分环境

copy:对象的属性声明,直接拷贝对象作为一个新的副本,而被拷贝的对象的引用计数不会加1,即两个对象分别指向不同的内存,只是内存中的数据相同。例如常用来修饰NSString 类型。

注释:自定义对象需要实现NSCoping协议。

atomic:原子性在生成 set 和 get 方法时会考虑线程问题,增加多线程保护,有加锁操作,但是会使属性读写性能降低(默认参数)。

nonatomic:非原子性不考虑安全问题,没有加锁操作,访问速度快。

atomic是线程安全,其实这个说法是不准确的,atomic只是对属性的getter/setter方法进行了加锁操作,这种安全仅仅是set/get 的读写安全,并非真正意义上的线程安全,因为线程安全还有读写之外的其他操作(比如:如果当一个线程正在get或set时,又有另一个线程同时在进行release操作,可能会直接crash)

readwrite:读写属性,生成getter和setter方法(默认参数)。

readonly:只读属性,系统只生成getter方法,即只能访问,不能赋值。

setter和getter:重新命名生成属性的set和get方法的名字。

@property(nonatomic, copy, setter = testString:) NSString *firstString;
@property(nonatomic, copy, getter = ggString) NSString *secondString;

- (void)testString:(NSString *)firstString{
    _firstString = [firstString copy];
}
- (NSString *)ggString{
    return _secondString;
}

class:使属性通过类名加点语法获取。

static NSString *classStr = nil;

@property(nonatomic, class) NSString *string;

+ (void)setString:(NSString *)string{
    classStr = string;
}
+ (NSString *)string{
    return classStr;
}
NSLog(@"%@", OBJProperty.string);

四.属性关键字的使用

非对象类型 使用assign可省略。
对象类型 使用retain/strong
NSString 使用copy/strong

例如:

@property (nonatomic, assign) CGFloat duration;
@property (nonatomic, strong) GLProgram *program;
@property (nonatomic, copy) NSString *dirPath;

五.strong关键字

ARC下的strong等同于MRC下的retain都会把对象引用计数加1。

在ARC环境下,只要某一对象被一个strong指针指向,该对象就不会被销毁。如果对象没有被任何strong指针指向,那么就会被销毁。在默认情况下,所有的实例变量和局部变量都是strong类型的。可以说strong类型的指针在行为上跟MRC下得retain是比较相似的。

如果使用strong修饰不可变类型的NSArray,并且使用NSMutableArray可变类型给NSArray赋值,再去修改可变类型NSMutableArray值的时候,NSArray所指向的值也会发生改变(浅拷贝) 。

六.copy关键字

1.关于copy的一些概念

浅拷贝指针的复制,只是多了一个指向这块内存的指针,公用一块内存,会增加对象的引用计数,并没有发生内存分配。
深拷贝内存的复制,两块内存是完全不同的,也就是两个对象指针分别指向不同的内存,互不干涉,但是内存中的值相同,不会增加被拷贝对象的引用计数

  • 可变的对象的copy和mutableCopy都是深拷贝
  • 不可变对象的copy是浅拷贝,mutableCopy是深拷贝
  • copy方法返回的都是不可变对象
  • mutableCopy返回的都是可变对象

2.为什么NSString用copy修饰

NSString使用copy修饰不用strong修饰,用strong修饰一个name属性,如果赋值的是一个可变对象,当可变对象的值发生改变的时候,name的值也会改变,这不是我们期望的,是因为name使用strong修饰后,指向跟可变对象相同的一块内存地址,如果使用copy的话,则是深拷贝,会开辟一块新的内存空间,因此可变对象值变化时,也不会影响name的值。

3.copy的作用

copy就是建立一个索引计数为1的对象,然后释放旧对象。

4.copy的修饰对象

  • 使用copy修饰对象,该对象就是内容拷贝,会在内存里拷贝一份对象,两个指针指向不同的内存地址。一般用来修饰NSString、NSArray、NSDictionary等有对应可变类型的对象,因为它们有可能和对应的可变类型(NSMutableString)之间进行赋值操作,为确保对象中的字符串不被修改,应该在设置属性是拷贝一份,而若用strong修饰,如果对象在外部被修改会影响到属性。
  • block也经常使用copy关键字,具体原因见 官方文档:Working with Blocks

block 使用 copy 是从 MRC 遗留下来的“传统”,在 MRC 中,方法内部的 block 是在栈区的,使用 copy 可以把它放到堆区.在ARC中写不写都行:对于 block 使用 copy 还是 strong 效果是一样的,但写上 copy 也无伤大雅,还能时刻提醒我们:编译器自动对 block 进行了 copy 操作。如果不写 copy ,该类的调用者有可能会忘记或者根本不知道“编译器会自动对 block 进行了 copy 操作”,他们有可能会在调用之前自行拷贝属性值。这种操作多余而低效。

七.strong和copy修饰的区别

定义两个属性:

@property (nonatomic, strong) NSArray *arrayStrong;
@property (nonatomic, copy) NSArray *arrayCopy;
    NSArray *array = [[NSArray alloc] initWithObjects:@"1", @"2", nil];
    self.arrayStrong = array;
    self.arrayCopy = array;
    
    NSLog(@"array = %@, arrayStrong = %@, arrayCopy = %@", array, _arrayStrong, _arrayCopy);
    NSLog(@"array = %p, arrayStrong = %p, arrayCopy = %p", array, _arrayStrong, _arrayCopy);

23

若给这两个属性赋值的字符串为不可变字符串,使用strong修饰的不可变数组的地址和使用copy修饰的不可变数组和其原地址相同,所以为浅拷贝

    NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"3", @"4", nil];
    self.arrayStrong = array;
    self.arrayCopy = array;
    
    NSLog(@"array = %@, arrayStrong = %@, arrayCopy = %@", array, _arrayStrong, _arrayCopy);
    NSLog(@"array = %p, arrayStrong = %p, arrayCopy = %p", array, _arrayStrong, _arrayCopy);

若给这两个属性赋值的字符串为不可变字符串,使用strong修饰的不可变数组的地址和其原地址相同,所以为浅拷贝,而使用copy修饰的不可变数组和其原地址不同,所以为深拷贝

经过诸多测试得到一下结论,属性的类型不会对结果造成影响,即strong和copy修饰可变或不可变数组其复制下来的结果都是相同的,

若使用不可变数组对其进行赋值,那么它们都为浅复制,即两个属性的地址和该不可变数组的地址相同,
而若使用可变数组对其进行赋值,使用strong修饰的地址与该可变数组的地址相同为浅复制,使用copy修饰的地址与该可变数组的地址不同为深复制。

以上是我对属性关键字的一些基础了解,想要详细了解可以看看这篇文章:iOS开发中各种关键字的区别

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-07 12:12:20  更:2021-08-07 12:14:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 12:32:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码