博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
理解 Objective-c "属性"
阅读量:5328 次
发布时间:2019-06-14

本文共 3226 字,大约阅读时间需要 10 分钟。

理解 Objective-c "属性"

@property 是OC中能够快速定义一个属性的关键字,如下我们定义一个属性。

@property   NSString        *String;

这样我们就可以使用这个属性

属性的实质

  • 在属性被加入OC以前我们每次声明一个实例变量都要自己声明并实现存取方法
//// Created by chao on 15/8/29.// Copyright (c) 2015 ___FULLUSERNAME___. All rights reserved.//#import 
@interface Person : NSObject{ NSString *firstName; NSString *lastName;}- (void)setFirstName:(NSString *)first;- (NSString *)firstName;- (void)setLastName:(NSString *)last;- (NSString *)lastName;@end//在.m文件里实现#import "Person.h"@implementation Person {}- (void)setFirstName:(NSString *)first { firstName = [first copy];}- (NSString *)firstName { return firstName;}- (void)setLastName:(NSString *)last { lastName = [last copy];}- (NSString *)lastName { return lastName;}@end

现在有了@property只要简单的声明一下就可以让编译器替我们做以上哪些繁杂的工作。

@property   NSStrinng   *firstNmae;@property   NSString    *lastName;
  • 声明属性 编译器除了生成存取方法代码外,还要自动向类中添加适当类型的实例变量。

编译器会自动在属性名之前添加下划线,一次作为实例变量的名字,在上面的声明中会生成两个实例变量

_firstNam, _lastName.我们也可以使用@synthesize语法指定实例变量的名字。

@synthesize firstName   =   _myFirstName; //使用指定的实例变量名称@synthesize lastName = _myLastName;//如果没有特殊需要尽量使用系统默认的名称
  • 如果不想令编译器合成存取方法, 则可以自己实现,如果只实现了其中一个存取方法, 则另外一个还是会由编译器重新合成,你可以使用@dynamic 关键字阻止编译器自动合成存取方法。

@dynamic关键字

@property   NSStrinng   *firstNmae;@property   NSStrinng   *firstNmae;@dynamic    firstName, lastname;    //编译器不会自动为这两个属性合成存取方法,或实例变量。

属性的特性

存取类型

  • readwrite (默认)编译器自动创建存方法和取方法
  • readonly 不生成存方法,如果一个属性不允许修改则可以将其声明为存方法。

在为以上类添加一个只读的ID和weight属性。

@property   (readonly)  NSInteger   ID;@property   (readwrite) NSInteger   height;

如果我们这程序中试图修改person 的ID属性编译器就会报错

readonly error

生命周期类型(内存管理类型)

生命周期类型的特性包括, assign, strong, weak和copy 这些特性决定了存方法如何处理与其相关的内存管理问题

  • assign (默认)最简单的,存入的值会将传入的值直接赋给实例变量。
@property   (assign)    NSInteger   ID;这段代码等同于实现了一下存方法- (void)setID:(NSInteger)d {    ID = d; }
  • strong 特性要求保留传入的对象,并放弃原有对象(如果原有对象不在有其他拥有方,就会被释放)。凡是指向对象的实例变量,通常都应该使用strong
  • weak 要求不保留传入的对象,相应的存取方法会将传入的对象直接赋给实例变量。如果该对象被释放,那么相应的实例变量会呗自动置nil
  • copy 特性要求拷贝传入对象,并将新对象赋给实例变量。

copy 详解

看了很多博客讲解的copy都只是简单的说了一下,copy特性要求拷贝传入对象。并没有进行深入的讲解,比如为什么要copy传入对象,下面我写一下我自己对copy的理解

  1. 在OC中有些类会有特定的可修改的子类,比如 像NSString 和 NSMutableString 这些类我们平常使用时一般都声明为copy。像下面我们定义一个NSString 属性,但是给其存方法传入 NSMutableString 是合法的,声明为 copy,就可以避免修改 原对象对实例变量的影响
@property   (strong)    NSString        *firstName;@property   (copy)  NSString        *lastName;NSMutableString  *name = [[NSMutable alloc] initWithString:@"Li"];[person     setFirstNmae:name];[person setLastName:name];//这样修改name 不会对实例变量产生影响。//看以下程序的输出 NSMutableString  *firstName = [NSMutableString stringWithString:@"Zhang"]; NSMutableString  *lastName  = [NSMutableString stringWithString:@"San"];person.firstName = firstName;person.lastName = lastName;NSLog(@"修改前的 :%@%@", person.firstName, person.lastName);[firstName appendString:@"fe"];[lastName appendString:@"aefa"];NSLog(@"修改后的 :%@%@", person.firstName, person.lastName);NSLog(@"%@%@", firstName, lastName);

copy mark

2.如果传入的对象是不可修改的,copy方法实际是在调用copyWithZone:一般我们自定义的对象如果要求copy,应该重写 copyWithZone:方法从而优化copy过程

- (id)copyWithZond {    return self;}
  1. copy返回的值总是不可修改的,如果需要copy出可修改的对象,需要使用对应的mutableCopy方法

atomic 和nonatomic

  • 如果不声明默认是atomic,atomic属性的存方法并不会对多线程下的安全有太大帮助,所以一般用nonatomic,而且atomic会影响性能。(确保线程安全必定会有额外开销)

转载于:https://www.cnblogs.com/code-changeworld/p/4782705.html

你可能感兴趣的文章
centos系统python2.7更新到3.5
查看>>
C#类与结构体究竟谁快——各种函数调用模式速度评测
查看>>
我到底要选择一种什么样的生活方式,度过这一辈子呢:人生自由与职业发展方向(下)...
查看>>
poj 题目分类
查看>>
windows 安装yaml支持和pytest支持等
查看>>
读书笔记:季羡林关于如何做研究学问的心得
查看>>
面向对象的优点
查看>>
套接口和I/O通信
查看>>
阿里巴巴面试之利用两个int值实现读写锁
查看>>
浅谈性能测试
查看>>
Winform 菜单和工具栏控件
查看>>
CDH版本大数据集群下搭建的Hue详细启动步骤(图文详解)
查看>>
巧用Win+R
查看>>
浅析原生js模仿addclass和removeclass
查看>>
Python中的greenlet包实现并发编程的入门教程
查看>>
java中遍历属性字段及值(常见方法)
查看>>
深入理解jQuery框架-框架结构
查看>>
YUI3自动加载树实现
查看>>
python知识思维导图
查看>>
当心JavaScript奇葩的逗号表达式
查看>>