[Object-C]_[初级]_[object类的对象和属性@property]
2017-10-24 18:20
309 查看
场景
object-c 的 @property 是我们常用的声明, 对属性类型描述涉及到 readonly,readwrite,assign,copy,retain,atomic,nonatomic,strong,weak. 如果对属性类型有理解的话, 对属性设置会有更加准确.常遇到的 retain,copy 到底有什么区别?
实例变量和 @property声明的 是否是同一个变量?
说明
object-c 对象由实例变量和方法组成, 在@property 后声明的变量不需要和 实例变量匹配, 因为 @property后声明的变量会在编译期自动生成. 因此如果只想类内部使用这个变量, 那么只需要声明实例变量, 不需要声明 @property. 注意@property声明了的变量需要在 @implement 里 使用@synthesize 来进行合成声明,匹配 @property里的声明数量.object-c 2.0 后支持 dot操作符
iVar.property = value来简化操作,编译器会自动转换setter,getter方法来访问属性, 也可以通过使用生成的getVariable 或 setVariable 来访问属性.
变量属性(property attribute)
(可写性)
– readwrite: 生成读写访问器, 该属性允许类外部读写.
– readonly: 生成读访问器, 该属性只允许类外部读.
(setter语义)
– assign: 默认类型, 简单赋值, 一般用在原始类型 int,…指针.
– retain: 用于对象, 不用于原始类型; [newObject retain], [oldObject release];
– copy: 用于对象, 不用于原始类型; 对象需要实现NSCopying协议, 如果是immutable对象, 比如NSString*, 那么 只需要 newObject retain], [oldObject release]; 如果非 immutable对象, 需要通过 alloc,init…来创建新对象, 或者通过调用父对象的 copyWithZone:来创建对象.
– strong: 默认情况下, 所有的指针对象都是 strong类型; 赋值一个新引用到这个对象, 这个引用对象会retain, 旧对象会自动先release;arc环境下, 所有的对象变量都是 strong类型, 你也可以显式使用
__strong Fraction *f1;来声明一个strong变量. 注意, @property默认不是 strong变量, 而是 unsafe_unretained 变量, 相当于 assign, 需要显式声明
@property (strong, nonatomic) NSMutableArray *birdNames;.
– weak: 只用于arc, 一般用于互相引用的变量,防止strong类型内存泄漏(互相引用不能释放), 比如NSView* 里的subviews和superview, superview就是weak变量.当主变量dealloc释放时, arc保证weak变量会被设置为nil. 这样对nil调用不会造成崩溃.
C++的类似,weak_ptr的使用场景
(原子性)
– 原子性表示先把值写入内存一个临时地址, 接着再写入想要的位置.
– atomic: 默认访问器就是 atomic, 这个更有利于在多线程环境下的并发访问问题.
– nonatomic: 非原子访问.
例子
以下例子设置项目为 Object-C Automatic Reference Counting 为 NO// // TestObject.h // TestObject-C // // Created by sai on 10/21/17. // Copyright (c) 2017 sai. All rights reserved. // #import <Foundation/Foundation.h> // http://www.binpress.com/tutorial/learn-objectivec-objects-part-2-properties/59 @interface TestObject : NSObject @property NSInteger id_; // default:readwrite,assign @property (readwrite,atomic) NSString* description_; @property (readwrite,atomic,assign) NSMutableArray* children_; @property (readonly) NSInteger status_; @property (readwrite,retain) NSMutableArray* books_; @property (readwrite,copy) NSString* bookmark_; // copy 的对象必须实现 NSCopying 协议, 不然运行时会崩溃. @property (strong,nonatomic) NSString* artist_; // 强引用对象, 相当于retain, 编译器保证再赋值前先 retain. // 所引用对象, 在 next_对象被dealloc 时, next_会被自动设置为nil, 而给 nil发送任何消息都不会崩溃,程序不做任何事情. // weak 模式只能在 arc 模式 或者 GC 模式下试用, 非 arc模式声明错误. //@property (weak,nonatomic) TestObject* next_; +(void) testProperty; @end
// // TestObject.m // TestObject-C // // Created by sai on 10/21/17. // Copyright (c) 2017 sai. All rights reserved. // #import "TestObject.h" #include <assert.h> @implementation TestObject @synthesize id_; @synthesize description_; @synthesize children_; @synthesize status_; @synthesize bookmark_; @synthesize books_; //@synthesize next_; @synthesize artist_; -(void)dealloc { // object-c的属性不会在dealloc时自动释放, 需要自己手动释放. NSLog(@"toA.artist_ retainCount %ld",[self.artist_ retainCount]); [super dealloc]; } +(void) testProperty { NSLog(@"========== testProperty ============"); TestObject *toA = [TestObject new]; TestObject *toB = [TestObject new]; NSLog(@"========== test default value begin ============"); // object-c成员变量对象自动被赋值为nil, primitive 对象被赋值为0 assert(toA.id_ == 0); assert(toA.description_ == nil); assert(toA.children_ == nil); assert(toA.status_ == 0); assert(toA.bookmark_ == nil); assert(toA.books_ == nil); // assert(toA.next_ == nil); assert(toA.artist_ == nil); NSLog(@"========== test default value end ============"); NSLog(@"========== test setter begin ============"); NSInteger retainCount1 = 0; NSInteger retainCount2 = 0; [toA setId_:1]; toA.id_ = 2; // dot 操作符也可以使用, 效果一样的, 编译器会进行 setter 转换. NSString* description = [NSString stringWithFormat:@" I like %d",7]; retainCount1 = [description retainCount]; toA.description_ = description; retainCount2 = [toA.description_ retainCount]; assert(toA.description_ == description); assert(retainCount1 == retainCount2 && retainCount1 == 1); NSMutableArray* children = [NSMutableArray new]; retainCount1 = [children retainCount]; toA.children_ = children; retainCount2 = [toA.children_ retainCount]; assert(toA.children_ == children); assert(retainCount1 == retainCount2 && retainCount1 == 1); // 错误, readonly 属性没有 setter 方法. // toA.status_ = 1; retainCount1 = [description retainCount]; toA.bookmark_ = description; retainCount2 = [toA.bookmark_ retainCount]; NSInteger retainCount3 = [description retainCount]; int64_t offset = (int64_t)toA.bookmark_; assert(offset == (int64_t)description); // NSString* 是 immutable 对象, 只需要retain即可. // 这里 retainCount2 == 3, 不清楚为什么不是2. // objc_setProperty_atomic_copy 也只是 retain了一次. assert(retainCount1== 1 && retainCount2 >=2); NSMutableArray* books = [NSMutableArray new]; retainCount1 = [books retainCount]; toA.books_ = books; retainCount2 = [books retainCount]; assert(retainCount2 == 2 && retainCount1 == 1); retainCount1 = [description retainCount]; toA.artist_ = description; retainCount2 = [toA.artist_ retainCount]; assert((retainCount2 - retainCount1) == 1); retainCount1 = [description retainCount]; toA.artist_ = description; retainCount2 = [toA.artist_ retainCount]; assert(retainCount2 == retainCount1); NSLog(@"========== test setter end ============"); [toA release]; } @end
输出
2017-10-24 17:58:03.308 TestObject-C[5307:303] ========== testProperty ============ 2017-10-24 17:58:03.309 TestObject-C[5307:303] ========== test default value begin ============ 2017-10-24 17:58:03.310 TestObject-C[5307:303] ========== test default value end ============ 2017-10-24 17:58:03.310 TestObject-C[5307:303] ========== test setter begin ============ 2017-10-24 17:58:06.822 TestObject-C[5307:303] ========== test setter end ============ 2017-10-24 17:58:06.823 TestObject-C[5307:303] toA.artist_ retainCount 5
参考
Learn Objective-C, Objects (Part 2): PropertiesProgramming in Objective-C Fourth Edition
相关文章推荐
- 步步为营VS 2008 + .NET 3.5(3) - C# 3.0新特性之Automatic Properties(自动属性)、Object Initializers(对象初始化器)、Collection Initializers(集合初始化器)和Ext
- JavaScript中Object 对象的Prototype属性
- 【JavaScript】(6)Object、String、Array、Date对象的方法、属性(constructor、prototype)
- 给object数组进行排序(排序条件是每个元素对象的属性个数)
- js为Object对象动态添加属性和值
- python创建只读属性对象的方法(ReadOnlyObject)
- ES6中object对象属性
- C# 3.0新特性之Automatic Properties(自动属性)、Object Initializers(对象初始化器)、Collection Initializers(集合初始化器)和Extension Methods(扩展方法)
- Object-C 获取对象的属性和值
- Object.assign() 方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
- ES6-对象的扩展-_proto_ 属性,Object.setPrototypeOf(),Object.getProtitypeOf()
- 理解ES6 第三章:对象 ---Object.assign给对象添加多个属性, super, 原型。。。
- python调用对象属性出错:AttributeError: 'function' object has no attribute '_name_'
- 将对象属性转object[]数组
- 代码练习在 C# 中得到一个 object (包含匿名对象)的属性和属性值
- Atiitt 对象转换json 序列化规范 Java 循环引用的解决 设置序列化层次深度 去除不必的属性 太长不方便月度 jsonObject.remove("num1"); Prety fo
- 3、步步为营VS 2008 + .NET 3.5(3) - C# 3.0新特性之Automatic Properties(自动属性)、Object Initializers(对象初始化器)、Collection Initializers(集合初始化器)和Extension Methods(扩展方法)
- IOS 根据对象属性值过滤数组中的元素 Filter NSMutableArray with object property
- 将Object对象转换成Map 属性名和值的形式
- Yii Object对象与属性相关的方法