【iOS】—— 属性关键字

属性关键字

在了解属性关键字前,先了解了解什么是属性,在刚开始学oc的时候,就学习了成员变量和属性,属性是一种特殊的成员变量,属性和成员变量最大的却别在于属性有自行合成的setter和getter方法。

在写UI控件的时候,我们很容易发现,如果我们在.m文件里新创建一个UI控件,并且对其进行操作,这个控件一般情况下只能在当前函数里进行随意调用。然而如果在属性里创建UI控件,在.m文件里访问时,控件名前面加个下划线或者用self.方法访问,这时这个控件就相当于一个全局变量,在每个函数里都可以调用,因此在写UI时建议把控件都以属性命名,这样简单方便,在调用时还不容易出错。

言归正传,在之前学习深拷贝和浅拷贝的时候就学习过copy和strong两个关键字:

copy修饰不可变对象,strong修饰可变对象。

copy修饰有四种情况:

  • copy修饰不可变对象、原对象为不可变对象时,将原对象赋值给属性,会将原对象进行copy,此时是浅复制,两个指针指向的是同一个地址。
  • copy修饰不可变对象,原对象为可变对象时,将原对象赋值给属性,会将原对象进行copy,此时是深复制,两个对象指向的不同的地址,属性所指的是可变对象的副本,原对象如果被修改的话,不会影响属性的值。
  • copy修饰可变对象,如果原对象是不可变对象并赋值给属性,那么进行的是浅复制,指向同一地址。
  • copy修饰可变对象,如果原对象是可变对象并赋值给属性,此时进行的是深复制,属性指向的是原对象的不可变副本,即此时属性为不可变对象,这时对属性进行增删改的操作,就会因为找不到方法而报错。

如下图:

请添加图片描述

刚刚讲到的copy属于setter相关修饰符,属性关键字主要分为四类:

  • 读写性控制
  • setter相关修饰符
  • 原子性修饰符
  • setter,getter相关修饰符

读写性控制

readOnly只读,只会生成getter方法,不会生成setter方法(但外部还是可以用KVC去赋值)
readWrite可读可写,会生成setter方法,也会生成getter方法(默认设置)
这个一般用处不大,除特殊情况外,保持默认readwrite方法即可。

setter相关控制符

assign , retain , copy

setter相关的修饰符表明setter方法应该如何实现
系统默认属性是assign。retain是指针的复制,copy是内容的复制

原子性修饰符:

atomic , nonatomic

atomic:表示是线程安全的。

nonatomic:表示是非线程安全的,使用此属性性能会提高一些。

系统默认是atomic

setter,getter相关修饰符

assign:用于非指针变量。用于基础数据类型(如NSInteger, CGFloat)和C数据类型(int, float, double, char等), 另外还有id类型。

retain:用于指针变量。一般用于字符串(NSString, NSMutableString), 数组(NSMutableArray, NSArray),字典对象,视图对象(UIView),控制器对象(UIViewController)等

strong类似于retain,weak类似于assign

通俗来说:

  • 使用assign:对基础数据类型(如NSInteger, CGFloat)和C数据类型(int, float, double, char等), 另外还有id类型
  • 使用copy:对NSString类型
  • 使用retain:对其它NSObject和其子类

对copy和strong测试:

//
//  ViewController.m
//  属性关键字测试
//
//  Created by 翟旭博 on 2022/8/7.
//

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) NSString* firstString;
@property (nonatomic, copy)   NSString* secondString;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    NSMutableString* textString = [[NSMutableString alloc] initWithString:@"str"];
    self.firstString = textString;
    self.secondString = textString;
    NSLog(@"textSting:%@,firstString:%@,secondStirng:%@",textString,_firstString,_secondString);
    NSLog(@"textSting:%p,firstString:%p,secondStirng:%p",textString,_firstString,_secondString);
    
    [textString appendString:@"str"];
    NSLog(@"textSting:%@,firstString:%@,secondStirng:%@",textString,_firstString,_secondString);
    NSLog(@"textSting:%p,firstString:%p,secondStirng:%p",textString,_firstString,_secondString);


}


@end

输出结果:
请添加图片描述
用strong修饰的内容改变了,copy修饰的并未改变。

关于容器类的测试:

//
//  ViewController.m
//  属性关键字测试
//
//  Created by 翟旭博 on 2022/8/7.
//

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) NSArray *firstarray;
@property (nonatomic, copy)   NSArray *secondarray;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    NSArray *testarray = [NSArray arrayWithObjects:@"hello",@"world", nil];
    _firstarray = testarray;
    _secondarray = testarray;
    
    NSLog(@"%@ %p",testarray, testarray);
    NSLog(@"%@ %p",_firstarray, _firstarray);
    NSLog(@"%@ %p",_secondarray, _secondarray);

}


@end


输出结果:
请添加图片描述

我们发现地址是相同的,可得结论:
若使用不可变数组对其进行赋值,那么它们都为浅拷贝,即两个属性的地址和该不可变数组的地址相同,
而若使用可变数组对其进行赋值,使用strong修饰的地址与该可变数组的地址相同为浅拷贝,使用copy修饰的地址与该可变数组的地址不同为深拷贝

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值