http://rypress.com/tutorials/objective-c/properties
在一個class中宣告的string, array, dictionary或者是其他object,在obj-c中可以使用property來定義此object被其他class使用getter, setter存取時的屬性,而obj-c有一些關鍵字可以讓我們來使用及定義,如weak, strong, copy, retain, assign,下面會一一來介紹
首先瞭解obj-c的memory management control方式
從這張圖可以清楚的了解,obj-c的回收機制就是系統會判斷一個物件的owner有幾個,當一個物件沒有人來own時,就會回收此物件
使用ARC的話,我們可以不用去擔心哪時要回收此物件,因為compiler會幫我們做好判斷,但我們仍然是需要瞭解porpery的屬性,這樣才能設定正確的存取關係,避免造成retain cycles
strong : 基本上這是最常用的屬性,以下圖的sample code來說明,首先我們宣告了一個person物件,接著我們又宣告了一個car物件,並在car物件中宣告了使用person物件並使用strongㄕ
// 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.h
#import
<Foundation/Foundation.h>
#import
"Person.h"
@interface
Car
:NSObject
@property
(
nonatomic
)
NSString
*
model
;
@property
(
nonatomic
,
strong
)
Person
*
driver
;
@end
接著考慮下面這段code
// 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
;
}
如此一來我們能夠確保在car物件需要person物件時,person物件是會一直存在以供使用的
weak : 接下來考慮下面的sample code,假設在person物件中也宣告了一個car物件,而屬性也設定成strong
// Person.h
#import
<Foundation/Foundation.h>
@class
Car
;@interface
Person
:NSObject
@property
(
nonatomic
)
NSString
*
name
;
@property
(
nonatomic
,
strong
)
Car
*
car
;
@end
接著在main.m加上這段code
honda
.
driver
=
john
;
john
.
car
=
honda
;
// Add this line
如此一來,很明顯的就會造成retain cycles了,以圖示來表示的話就像下面這樣
這兩個物件彼此互相擁有,任何一個物件的ownership永遠不會為0,系統無法回收這兩個物件就算他們沒人使用了,然後就會造成memory leak,之後你的app就會crash,此時老闆就不開心了.要解決這個問題,就是不使用strong屬性而使用weak
@property
(
nonatomic
,
weak
)
Car
*
car
;
以圖來表示的話像是下面這樣:
可以看到car物件的owner是0,所以當honda被回收時,john也可以跟著說再見了,而不會死賴著不走造成crash
copy : copy屬性,copy屬性有點類似strong,但不同的是不會增加一個owners,而會如其名的複製一個物件給他,而通常開發者會在NSString中使用copy屬性.
// Car.h
@property
(
nonatomic
,
copy
)
NSString
*
model
;
上面的code中我們在car物件宣告了一個model string並使用了copy,接著來看下面的code
// main.m
#import
<Foundation/Foundation.h>
#import
"Car.h"
int
main
(
int
argc
,
const
char
*
argv
[])
{
@autoreleasepool
{
Car
*
honda
=
[[
Car
alloc
]
init
];
NSMutableString
*
model
=
[
NSMutableString
stringWithString:
@"Honda Civic"
];
honda
.
model
=
model
;
NSLog
(
@"%@"
,
honda
.
model
);
[
model
setString:
@"Nissan Versa"
];
NSLog
(
@"%@"
,
honda
.
model
);
// Still "Honda Civic"
}
return
0
;
}
我們就能夠明白,當我們對honda物件的model屬性設定好值之後,model string是被複製到car物件的,而不是共用ownership,從sample code來看,當我們再回去修改model的內容值為Nissan Versa時,honda的model value仍是Honda Civic而不是Nissan Versa,但copy不是人人能用,只有符合NSCopying Protocol的物件才能使用.
其他的屬性:
retain : 非ARC才會用到,但現在似乎沒人不使用ARC?!
assign : 基本類型的物件如float, int等等會使用到,這屬性並不會牽扯到任何memory management,就是給基本類型的物件來使用的
沒有留言:
張貼留言