[iOS] 属性关键字

发布于:2025-09-12 ⋅ 阅读:(17) ⋅ 点赞:(0)

前言

属性关键字是一个非常重要的部分在 iOS 开发中,这篇博客是对前面内容的复习以及一些补充。

属性关键字

@propety

属性用于封装对象中的数据,属性的本质是 ivar(实例变量) + setter + getter。

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

@synthesize

这是用于自动合成 setter + getter 方法的实现,目前已经不需要这个关键字来帮助我们来实现 setter + getter 方法了,现在可以自动生成相关的方法,可以通过这个关键字来定制我们的 ivar 的名字

就比如举个例子

@property (nonatomic, strong) NSString *name;

如果我这么写编译器会默认生成一个实例变量*_name这时会自动@synthesize name =_name这样其实self.name实际上就是访问_name*。

@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@end

@implementation Person
// 手动指定 ivar 名字
@synthesize name = myCustomName;
@end

这时self.name其实是访问myCustomName

@dynamic

这个是让我们的编译器不用自动进行*@synathesize*,我们会自己实现,无需产生警告,但是他不会影响*@property*生成的 getter 和 setter 方法的声明,这里体现的是 OC 是一种动态运行的语言。

分类中有关@property 的使用

分类中可以通过*@property这个语法来添加属性,但是这里不会生成对应的实例变量,我们不可以用@synathesize*来合成成员变量。原因是

  1. Category 不能添加成员变量因为运行期内存布局已经固定,如果添加实例变量会破坏类的内部布局。
  2. @synthesize是用来合成成员变量的,而分类中不可以添加成员变量。

重要的几个属性关键词

原子性
  • atomic

    • 含义:生成 getter/setter 是线程安全的,会加锁。
    • 优点:保证多线程小爱取值和赋值不会读写冲突。
    • 缺点:性能差,开发中几乎不用。
  • nonatomic

    • 含义:不保证线程安全,getter/setter 直接操作。
    • 优点:性能好,开发中大部分用它。
内存管理相关
  • strong

    • 含义:强引用,持有对象,引用计数 + 1;
    • 适用:OC 对象的属性(NSString、NSArray、自定义类等)。
  • copy

    • 含义:创建副本(调用 copy 方法),不受外部修改影响。
    • 适用:NSString、NSArray、NSDictionary(尤其是 NSString 防止外部传入 NSMutableString 改变值)。

下面有段代码可以形象的展示出 copy 和 strong 的区别

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Person1 : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) BOOL age;
@end

NS_ASSUME_NONNULL_END
#import <Foundation/Foundation.h>
#import "Person1.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person1 *p1 = [[Person1 alloc] init];
        NSMutableString *s1 = [NSMutableString stringWithString:@"Apple"];
        p1.name = s1;
        [s1 appendString:@"Android"];
        NSLog(@"%@", p1.name);
    }
    return 0;
}

这是打印结果

请添加图片描述

如果我把属性中的copy换成strong那么打印结果会发生改变

请添加图片描述

这里的原因就是person.name的属性是copy,所以创建了新的字符串,这个属于深拷贝,拷贝出来一个新的对象,后面的操作都是对新的对象操作,而我们的实际调用还是原来的对象,所以值不会改变。

而改成strong以后,引用计数会加一本质上是浅拷贝,指针拷贝,这时我们操作,更改他的值就会使原本的对象发生改变。

  • weak

    • 含义:弱引用,不增加引用计数。
    • 特点:当对象释放时,weak 指针会自动置为nil,避免野指针。
    • 适用:delegate 属性,或者避免循环引用。
  • assign

    • 含义:直接赋值,不改变引用计数。
    • 适用:基本数据类型(int、float、BOOL、struct)。
    • 缺点:如果用于对象,会产生野指针。

总结

这里我给出一个表格来去介绍大部分的属性关键字

分类 关键字 作用 说明
原子性 atomic (默认) 保证多线程读写安全 性能差,一般不用
nonatomic 不保证线程安全 性能更好,iOS 开发中几乎都用这个 性能更好,iOS 开发中几乎都用这个
内存管理 strong 对象持有(引用计数 +1) 常用于 OC 对象属性
weak 不持有对象,释放后自动置 nil 常用于避免循环引用(如 delegate) 常用于避免循环引用(如 delegate)
assign 直接赋值,不改变引用计数 适合基本数据类型(int、float、struct),对对象可能产生野指针 适合基本数据类型(int、float、struct),对对象可能产生野指针
unsafe_unretained 和 assign 类似,但对象释放不会置 nil ARC 前常用,ARC 后几乎不用 ARC 前常用,ARC 后几乎不用
copy 创建副本(调用 copy 方法) 常用于 NSString、NSArray、NSDictionary 等不可变对象,防止外部修改 常用于 NSString、NSArray、NSDictionary 等不可变对象,防止外部修改
读写性 readwrite (默认) 生成 getter & setter 外部可读可写
readonly 只生成 getter 外部只读,可在类内写 外部只读,可在类内写
方法名 getter=methodName 自定义 getter 方法名 如 getter=isFinished
setter=methodName 自定义 setter 方法名 如 setter=setFinishedState: 如 setter=setFinishedState:
多线程(很少用) atomic 多线程安全 系统默认,但实际开发常配合 nonatomic

网站公告

今日签到

点亮在社区的每一天
去签到