self.用法
我們經常會在官方文檔里看到這樣的代碼:
?MyClass.h?[?/?lang?]?@interface?MyClass?:?NSObject?{?MyObject?*?myObject;?}?@property?(?nonatomic,?retain?)?MyObject?*?myObject;?@end?MyClass.m?@synthesize?myObject;?-?(?id?)?init?{?if
我們經常會在官方文檔里看到這樣的代碼:
MyClass.h
[/lang]
@interface?MyClass?:?NSObject?{
????MyObject?*myObject;
}
@property?(nonatomic,?retain)?MyObject?*myObject;
@end
?
MyClass.m
?
@synthesize?myObject;
?
-(id)init{
????if(self?=?[super?init]){
????????MyObject?*?aMyObject?=?[[MyObject?alloc]?init];
????????self.myObject?=?aMyObject;
????????[aMyObject?release];
????}
????return?self;
}
有人就問,?為什么要這么復雜的賦值??為什么要加self.???直接寫成self.myObject?=?[[MyObject?alloc]?init];不是也沒有錯么??不加self有時好像也是正常的??現在我們來看看內存管理的內容:
??先看間接賦值的:
????1.加self.:
?
????????MyObject?*?aMyObject?=?[[MyObject?alloc]?init];?//aMyObject?retainCount?=?1;
????????self.myObject?=?aMyObject;?//myObject?retainCount?=?2;
????????[aMyObject?release];//myObject?retainCount?=?1;
?
????2.?不加self.:
?
???????MyObject?*?aMyObject?=?[[MyObject?alloc]?init];?//aMyObject?retainCount?=?1;
????????myObject?=?aMyObject;?//myObject?retainCount?=?1;
????????[aMyObject?release];//對象己經被釋放?
?
再看直接賦值的:
????3.加self.:
?
self
.myObject
=?[[
MyObject
alloc]?init]
;
//myObject?retainCount?=?2;
?
????4.?不加self.:
?
????????myObject?=?[[MyObject?alloc]?init];?//myObject?retainCount?=?1;
?
現在是不是有點暈,?我們先來把代碼改一下,?官方的一種常見寫法:
MyClass.h
?
@interface?MyClass?:?NSObject?{
????MyObject?*?_myObject;
}
@property?(nonatomic,?retain)?MyObject?*myObject;
@end
?
MyClass.m
??@synthesize?myObject?=?_myObject;?
OK,?你現在再試下,?如果你用self._myObject?=?aMyObject;?或者?myObject?=?aMyObject;?你會得到一個錯誤,?為什么呢,?這里就是和Obj-c的存取方法有關了.?說白了很簡單?,?大家都知道,?@property?(nonatomic,?retain)?MyObject?*myObject;?是為一個屬性設置存取方法,?只是平時我們用的方法名和屬性名是一樣的,現在你把它寫成不同的名字,?就會很清楚了.?_myObject是屬性本身,?myObject是存取方法名.
現在我們知道self.是訪問屬性的存取方法了,?那存取方法又怎么工作的??self.myObject?=?[[MyObject?alloc]?init];?為什么會有內存泄露?
關于nonatomic我不多解釋了,?它不是我要講的重點,?而且我也沒完全搞清楚,?不誤導大家.?我只說assign,?retain?,copy.
get方法是:
?
-(MyObject*)myObject{
????return?_myObject;
}
?
Set方法是:
?
//?assign?
-(void)setMyObject:(id)newValue{
????_myObject?=?newValue;?
}
//?retain?
-(void)setMyObject:(id)newValue{
????if?(_myObject?!=?newValue)?{?
????????[_myObject?release];?
????????_myObject?=?[newValue?retain];?
????}??
}
//?copy?
-(void)setMyObject:(id)newValue{
????if?(_myObject?!=?newValue)?{?
????????[_myObject?release];?
????????_myObject?=?[newValue?copy];?
????}?
}
?
其實這些方法里還有別的內容,?并不只是這些.?而且這些方法可以被重寫.?比如你寫一個
?
-(MyObject*)myObject{
?
????return?_myObject;
}
?
放在你的類里,?你調用self.myObject時(不要把它放在等號左邊,?那會調用get方法)就會調用這個方法.
這里多說一句,?@property?是為你設置存取方法,?和你的屬性無關,?你可以只寫一句
?
@property?(readonly)?NSString?*name;
?
在你的類里實現
?
-(NSString*)name{
????NSLog(@"name");
????return?@"MyClass";
}
?
同樣可以用self.name調用.
現在回頭?說說我們開始的那四個賦值,?當不用self.的時候,??那句話只是一般的賦值,?把一個指針賦給另一個指針,?不會對分配的內存有任何影響,?所以2中不要最后[aMyObject?release];這句話和4是一回事.?這里就不多說了.我們看看1和3,?
當調用?setMyObject:方法時,?對newValue?做了一次retain操作,?我們必須把原來的newValue釋放掉,?不然就會內存泄露,?在1里,?我們有個aMyObject可以用來釋放,?在3里,?我們無法釋放它,?所以,?在3里,?我們會多出來一個retainCount.?內存泄露了.
說了這么多,?我只想讓大家清楚,?什么是調用屬性本身,?什么是調用存取方法.?怎么樣才能避免內存泄露,?而且,?以上例子里是在自己類里的調用,?如果這個類被別的類調用時,?更要注意一些,
順便說一下,?如果你想在其它類訪問對象屬性,?而不是通過存取方法,?你可以用myClass?->?myObject來訪問,?這樣是直接訪問對象本身,?不過你先要把myObject設成@public.?但這個是官方不提倡的,
總結
- 上一篇: 虚拟主机搭建微信公众号服务器,建web服
- 下一篇: 动网论坛