Objective-C Properties 詳解

來源:互聯網
上載者:User

標籤:

關於Objective-C 的property,很多iOS開發的新手都會很迷惑,也會包括有經驗的iOS開發程式員,

因為Objective-C的property,說多不多,說少卻也不少,從MRR(Manual Retain Release )到ARC模式,很多屬性功能類似

名稱卻不一樣,比如strony和retain,而且又牽扯到release, autorelease, alloc ,new,copy等一眾函數,

所以看著很容被繞進去,迷失在這眾多的property,

今天特地梳理支援ARC(iOS 5+) 的propterty的關鍵詞:

strong, weak, copy, readonly/readwrite, atomic/nonatomic,assign,retain

 

由於strong和retain功能相同,所以會在最後總結的時候,比較所有的這些關鍵詞異同點

 

1:定義一個property

如下,我們定義一個car 的interface, 該屬性有一個property 為 brand(品牌)

// Car.h
#import <Foundation/Foundation.h>@interface Car : NSObject@property NSString *brand;@end
//  Car.m#import "Car.h"@implementation car@synthesize brand = _brand;@end

 

2:屬性的getter 和setter方法和synthesize

編譯器會預設的為屬性產生getter 和setter方法

- (NSString *)brand{    return _brand;//_brand即使synthesize指定的屬性名稱}- (void)setBrand:(NSString *)brand{    _brand = brand;}

 

注意:synthesize 不是必須明確聲明,除非手動些屬性的getter和setter方法

否則,complier預設產生的code 如下格式

@synthesize brand = _brand

 

synthesize關鍵字預設方式是:將brand屬性對應的執行個體便令聲明為_brand,即_ + propertyname

當然可以自己指定比如brand = xxxbrand

 

編譯器預設會將getter方法和屬性同名,setter方法為set+屬性(首字母大寫),例如setBrand

可以指定屬性的getter和setter方法名稱

@property (nonatomic,getter=getBrand, setter = setBrand:)NSString *brand;

 

 3:readonly和readwrite

聲明 readonly屬性

@property (readonly,getter=getBrand)NSString *brand;

 

聲明了readonly的屬性,一定沒有setter方法,所以你可以使用getter或者 dot方法 擷取屬性的值,但肯定不可以使用

setter方法修改

Car *c = [[Car alloc]init];0    [c setBrand:@"tony"]; //Error        NSLog(@"%@", [c getBrand]);

 

聲明為readonly 不意味著我們不可以修改,propery 的accessor method 本來就是提供給其他介面調用的,

在我們內部,是直接操縱_brand執行個體的, 如下

// Car.h
- (void)setBrand:(NSString *)brand;

 

// Car.m
- (void )setBrand:(NSString *)brand;{ _brand = brand;}

 

readonly 對應的readwrite 屬性, readwrite 是default的behavior,可以不顯示聲明

@property (readwrite)NSString *brand;

 

4:atomic, nonatomic

atomic 原子的,default behavior,支援多線程操作, 代價是開銷比nonatomic大

如果聲明一個屬性,確定不會運行在多線程的環境,可以直接聲明為nonatomic

@property (nonatomic)NSString *brand;

 

記憶體管理

 

Ojective-C 記憶體模型中,不管是MRR,還是ARC,都是根據對象的引用計數來確定對象是否回收

當對象的 引用計數為0,就會被回收(不一定是立即回收)

 

 

從引用計數的原理出發,Objective-C 提出了三種相關的是屬性

strong, weak, copy

 

1:strony 屬性

strong屬性,即聲明一個對象擁有另外一個對象,引用計數 + 1

加入 A對象 有個strong 屬性的執行個體對象B, 則在A對象釋放之前,B是不會釋放的

看如下sample code 

聲明一個類Person,Person有一個屬性name

////  Person.h#import <Foundation/Foundation.h>@interface Person : NSObject@property (nonatomic) NSString *name;@end
//  Person.m#import "Person.h"@implementation Person- (NSString *)description{     return self.name;}@end

 

聲明一個Car 類,有兩個屬性 model和driver

//  Car.h#import <Foundation/Foundation.h>#import "Person.h"@interface Car : NSObject@property (nonatomic) NSString *model;@property (nonatomic,strong) Person *driver;@end

 

main.m

// main.m#import <Foundation/Foundation.h>#import "Car.h"#import "Person.h"int main(int argc, const char * argv[]) {    @autoreleasepool {        Person *john = [[Person alloc] init];        john.name = @"John";                Car *honda = [[Car alloc] init];        honda.model = @"Honda Civic";        honda.driver = john;                NSLog(@"%@ is driving the %@", honda.driver, honda.model);    }    return 0;}

可以看到,hoda對象對driver對象負責

 

2:weak屬性

 

strong 屬性,很直觀的顯示對象直接的關係,但也很容易引起記憶體泄露,

看如下代碼,我們稍微小改了Person.h ,增加了Car 屬性,

// Person.h#import <Foundation/Foundation.h>@class Car;@interface Person : NSObject@property (nonatomic) NSString *name;@property (nonatomic, strong) Car *car;@end

 

則在main.m 

增加一行

 

 john.car = honda;  

 

則此時,john和hoda互相持有對方

 

 

二者這件形成了 retain cycle(互相持有的迴圈),就是典型的記憶體泄露的一種情況

 

如果car聲明為weak,這個問題即迎刃而解

 @property (nonatomic, weak) Car *car; 

 

 

 

3:copy 屬性

copy不同於strong, 並不擁有copy的對象,而是複製該對象(必須conform NSCopying protocol )

 

sample code

#import <Foundation/Foundation.h>#import "Car.h"#import "Person.h"int main(int argc, char *argv[]){            Car *bmw = [[Car alloc]init];        Person *driver = [[Person alloc]init];        NSMutableString *name = [NSMutableString stringWithFormat:@"zhangsan"];//mutable 的name 為zhangsan        [driver setName:name];    [name setString:@"lisi"];//修改為lisi    [driver setCar:bmw];        [bmw setModel:@"X5"];    [bmw setDriver:driver];        NSLog(@"%@", [driver name]);//仍然是zhangsan}

copy 屬性在被賦值的時候就copy了該值,所以即使該值是mutable的,屬性的值也不會被修改,

 

現對於strong的持有對象,copy特別適合只是簡單儲存值得屬性

 

以上都是ARC支援的屬性。

4:屬性retain  

 等同於 strong

 

 

5:unsafe_unretained

類似於weak,和weak不同的是,如果weak 屬性指向的對象如果被銷毀後,weak 屬性被置為nil,

而 unsafe_unretained 不會,則又可能形成懸垂指標的問題

 

6:assign

預設的屬性,不需要顯示聲明

指定setter方法進行簡單的賦值 ,對基礎資料類型(NSInteger,CGFloat)

和C資料類型(int, float, double, char)等等。

 

 總結:

atomic //default

nonatomic

 

strong=retain //default

weak

assign //default

unsafe_unretained

copy

 

readonly

readwrite //default

 

 

引用:

http://rypress.com/tutorials/objective-c/properties

http://rypress.com/tutorials/objective-c/memory-management

http://stackoverflow.com/questions/8927727/objective-c-arc-strong-vs-retain-and-weak-vs-assign

Objective-C Properties 詳解

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.