自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

總結(jié)一些Objective-C的self.用法

移動開發(fā) iOS
關(guān)于什么時候用全局變量,什么時候用self.賦值的問題,其實(shí)是和Objective-c的存取方法有關(guān), 網(wǎng)上很多人也都這么解答的,不過如何與存取方式有關(guān)究竟他們之間的是什么樣的關(guān)系就很少有同學(xué)回答了。我總結(jié)了一下, 發(fā)出來給大家參考. 有什么問題請大家斧正.

進(jìn)入正題, 我們經(jīng)常會在官方文檔里看到這樣的代碼:

  1. MyClass.h 
  2.  
  3. @interface MyClass : NSObject { 
  4.     MyObject *myObject; 
  5. @property (nonatomic, retain) MyObject *myObject; 
  6. @end 
  7.  
  8. MyClass.m 
  9.  
  10.   
  11. @synthesize myObject; 
  12.   
  13. -(id)init{ 
  14.     if(self = [super init]){ 
  15.         MyObject * aMyObject = [[MyObject alloc] init]; 
  16.         self.myObject = aMyObject; 
  17.         [aMyObject release]; 
  18.     } 
  19.     return self; 

 

 

 

創(chuàng)建一個Student類,繼承NSObject類,代碼:

  1. #import <Foundation/Foundation.h> 
  2.   
  3. @interface Student : NSObject{ 
  4.   
  5.       NSString *idd; 
  6.       NSString *name; 
  7.   } 
  8.   @property (nonatomic, retain) NSString *idd; 
  9.   @property (nonatomic, retain) NSString *name; 
  10.     
  11.   @end 

.m文件 代碼:

  1. #import "Student.h" 
  2.    
  3.   @implementation Student 
  4.   @synthesize idd,name; 
  5.     
  6.   - (void)dealloc 
  7.   { 
  8.       [idd release]; 
  9.       [name release]; 
  10.      [super dealloc]; 
  11.   } 
  12.     
  13.    
  14.   @end 

使用@propety @synthesize實(shí)現(xiàn)Student的成員屬性的set get方法。通常我們在其他類里訪問Student的成員屬性的做法:

獲取student的名字通過student.name,給名字賦值[student setName:@“jordy”]; 其中student是Student類對象,如果在Student類內(nèi)部訪問其成員屬性使用[self setName:@”jordy”], 訪問使用self.name;

注意:上述的代碼,由于wordpress的原因,代碼中的字符會自動保存為中文格式。你在使用時記得改為英文格式。

在Student.h和Student.m文件,是我們習(xí)慣性的寫法,但似乎還是不能解釋什么加self和不加self的區(qū)別,請看下面代碼,是另一種習(xí)慣性的寫法,還以Student類為例:

.h文件 代碼:

  1. #import <Foundation/Foundation.h> 
  2. @interface Student : NSObject{ 
  3.   
  4.     NSString *_idd; 
  5.    NSString *_name; 
  6. @property (nonatomic, retain) NSString *idd; 
  7. @property (nonatomic, retain) NSString *name; 
  8. @end 

.m文件 代碼:

  1. #import "Student.h" 
  2.   
  3. @implementation Student 
  4.  @synthesize idd = _idd; 
  5. @synthesize name = _name; 
  6.   
  7.  - (void)dealloc 
  8.  { 
  9.     [_idd release]; 
  10.     _idd = nil; 
  11.      [_name release]; 
  12.     _name = nil; 
  13.      [super dealloc]; 
  14.  } 
  15. @end 

可以注意到上述代碼,與之前的代碼,在.h文件name變量改寫為了_name;在.m文件中@sythesize的寫法也發(fā)生了變化。

如果通過方法self._name獲取屬性的值,xcode編譯器會提示錯誤,其實(shí)這也就說明了,我們通常使用self.name實(shí)際使用的是student類name的get方法,同理name的set方法亦是如此。

有人就問, 為什么要這么復(fù)雜的賦值? 為什么要加self. ? 直接寫成self.myObject = [[MyObject alloc] init];不是也沒有錯么? 不加self有時好像也是正常的?

接下來從內(nèi)存管理來說明使用self.和不使用self的區(qū)別

現(xiàn)在我們來看看內(nèi)存管理的內(nèi)容:

ViewController.h文件,使用Student類,代碼如下:

  1. #import <UIKit/UIKit.h> 
  2.  @class Student; 
  3.   
  4.  @interface ViewController : UIViewController{ 
  5.       
  6.     Student *_student; 
  7.  } 
  8.      
  9.   @property (nonatomic, retain) Student *student; 
  10.     
  11.  @end 

 

 

ViewController.m文件,代碼:

  1. #import "ViewController.h" 
  2.  #import "Student.h" 
  3.     
  4.   @implementation ViewController 
  5.   @synthesize student = _student; 
  6.     
  7.   - (void)didReceiveMemoryWarning 
  8.   { 
  9.       [super didReceiveMemoryWarning]; 
  10.   } 
  11.     
  12.   #pragma mark - View lifecycle 
  13.     
  14.   - (void)viewDidLoad 
  15.   { 
  16.       [super viewDidLoad]; 
  17.   } 
  18.     
  19.   - (void) dealloc 
  20.   { 
  21.         [_student release]; 
  22.         _student = nil; 
  23.      [super dealloc]; 
  24.     } 

 

 

其它的方法沒有使用到,所以這里就不在顯示了。

在ViewController.m的viewDidLoad方法中創(chuàng)建一個Student類的對象

  1. Student *mystudent = [[Student alloc] init]; 
  2.  self.student = mystudent; 
  3.  [mystudent release]; 

這是相信有人會有疑問了,問什么創(chuàng)建student對象要這么復(fù)雜,似乎直接使用self.student = [[Student alloc] init]; 也沒有問題,不加self有時也是挺正常的呀?

接下來就需要從內(nèi)存角度來分析它們之間的區(qū)別了:

先看間接賦值的:

 

1.加self.

  1. MyObject * aMyObject = [[MyObject alloc] init]; //aMyObject retainCount = 1; 
  2. self.myObject = aMyObject; //myObject retainCount = 2; 
  3. [aMyObject release];//myObject retainCount = 1; 

 

2. 不加self.

  1. MyObject * aMyObject = [[MyObject alloc] init]; //aMyObject retainCount = 1; 
  2. myObject = aMyObject; //myObject retainCount = 1; 
  3. [aMyObject release];//對象己經(jīng)被釋放 

 

再看直接賦值的:

 

3.加self.

  1. self.myObject = [[MyObject alloc] init]; //myObject retainCount = 2; 

 

4. 不加self.

  1. myObject = [[MyObject alloc] init]; //myObject retainCount = 1; 

 

現(xiàn)在是不是有點(diǎn)暈, 我們先來把代碼改一下, 官方的一種常見寫法:

  1. MyClass.h 
  2. @interface MyClass : NSObject { 
  3.     MyObject * _myObject; 
  4. @property (nonatomic, retain) MyObject *myObject; 
  5. @end 
  6. MyClass.m 
  7. @synthesize myObject = _myObject; 

 

OK, 你現(xiàn)在再試下, 如果你用self._myObject = aMyObject; 或者 myObject = aMyObject; 你會得到一個錯誤, 為什么呢, 這里就是和Obj-c的存取方法有關(guān)了. 說白了很簡單 , 大家都知道, @property (nonatomic, retain) MyObject *myObject; 是為一個屬性設(shè)置存取方法, 只是平時我們用的方法名和屬性名是一樣的,現(xiàn)在你把它寫成不同的名字, 就會很清楚了. _myObject是屬性本身, myObject是存取方法名.

 

現(xiàn)在我們知道self.是訪問屬性的存取方法了, 那存取方法又怎么工作的? self.myObject = [[MyObject alloc] init]; 為什么會有內(nèi)存泄露?

關(guān)于nonatomic我不多解釋了, 它不是我要講的重點(diǎn), 而且我也沒完全搞清楚, 不誤導(dǎo)大家. 我只說assign, retain ,copy.

 

get方法是:

  1. -(MyObject*)myObject{ 
  2.     return _myObject; 

 

Set方法是:

  1. // assign 
  2. -(void)setMyObject:(id)newValue{ 
  3.     _myObject = newValue; 
  4. // retain 
  5. -(void)setMyObject:(id)newValue{ 
  6.     if (_myObject != newValue) { 
  7.         [_myObject release]; 
  8.         _myObject = [newValue retain]; 
  9.     }  
  10. // copy 
  11. -(void)setMyObject:(id)newValue{ 
  12.     if (_myObject != newValue) { 
  13.         [_myObject release]; 
  14.         _myObject = [newValue copy]; 
  15.     } 

 

其實(shí)這些方法里還有別的內(nèi)容, 并不只是這些. 而且這些方法可以被重寫. 比如你寫一個

  1. -(MyObject*)myObject{ 
  2.     return _myObject; 

 

放在你的類里, 你調(diào)用self.myObject時(不要把它放在等號左邊, 那會調(diào)用get方法)就會調(diào)用這個方法.

 

這里多說一句, @property 是為你設(shè)置存取方法, 和你的屬性無關(guān), 你可以只寫一句

  1. @property (readonly) NSString *name; 

 

在你的類里實(shí)現(xiàn)

  1. -(NSString*)name{ 
  2.     NSLog(@"name"); 
  3.     return @"MyClass"

 

同樣可以用self.name調(diào)用.

 

現(xiàn)在回頭說說我們開始的那四個賦值, 當(dāng)不用self.的時候,  那句話只是一般的賦值, 把一個指針賦給另一個指針, 不會對分配的內(nèi)存有任何影響, 所以2中不要最后[aMyObject release];這句話和4是一回事. 這里就不多說了.我們看看1和3,

當(dāng)調(diào)用setMyObject:方法時, 對newValue 做了一次retain操作, 我們必須把原來的newValue釋放掉, 不然就會內(nèi)存泄露, 在1里, 我們有個aMyObject可以用來釋放, 在3里, 我們無法釋放它, 所以, 在3里, 我們會多出來一個retainCount. 內(nèi)存泄露了.

 

說了這么多, 我只想讓大家清楚, 什么是調(diào)用屬性本身, 什么是調(diào)用存取方法. 怎么樣才能避免內(nèi)存泄露, 而且, 以上例子里是在自己類里的調(diào)用, 如果這個類被別的類調(diào)用時, 更要注意一些,

 

順便說一下, 如果你想在其它類訪問對象屬性, 而不是通過存取方法, 你可以用myClass -> myObject來訪問, 這樣是直接訪問對象本身, 不過你先要把myObject設(shè)成@public. 但這個是官方不提倡的,

 

代碼比較簡單, 我還是發(fā)出來, 高人們可以忽略了.

責(zé)任編輯:佚名 來源: 網(wǎng)絡(luò)整理
相關(guān)推薦

2011-07-20 13:34:37

Objective-C self.

2011-08-04 13:55:10

Cocoa Objective- 文件

2011-07-19 13:49:19

Objective-C 數(shù)據(jù)類型

2011-07-08 18:44:09

Objective-C Self Super

2011-07-07 17:17:23

Objective-C

2011-08-01 11:49:05

Objective-C

2011-07-25 13:05:37

Objective-C 委托

2013-08-21 15:06:31

iOSself.

2011-08-10 18:07:29

Objective-C反射

2011-05-11 15:58:34

Objective-C

2013-03-27 12:54:00

iOS開發(fā)Objective-C

2013-06-20 10:40:32

Objective-C實(shí)現(xiàn)截圖

2011-05-11 11:20:26

Objective-C

2011-06-27 15:48:09

Cocoa TouchObjective-C

2023-02-10 09:46:04

bash腳本變量

2017-09-05 09:17:47

Java編程用法總結(jié)

2014-07-29 09:44:35

2013-04-11 13:41:30

Objective-CiOS編程

2014-11-25 10:18:17

Objective-C

2009-09-21 17:46:25

Hibernate數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號