IOS屬性的作用

一、類和對象。


說明:在學習屬性前先理清屬性跟類和對象的關係。所以先說明一下類和對象。

類:

類是抽象概念,用於抽象描述具有相同屬性和行爲的某一類對象。比如:人、車等。

對象:

對象是類的實例化,具體描述這個類別中的一個實體。

類是抽象的,不佔內存;對象是具體的,佔內存。

舉例:
“人”是一個類,人的屬性有名字、身高、性別、膚色、國籍等等。人的行爲有吃飯、睡覺、尿尿等等。但是,在類別裏這些都是抽象的,是用來描述“人”這一類對象。
小紅是一個對象,她的名字是小紅、性別是女,國籍是中國。她的行爲是正在睡覺。這些都是具體存在的,這些具體存在描述了小紅這個對象

二、屬性


a.引入屬性的原因:

編譯器遇到關鍵字@property會自動爲這個屬性添加setter/getter方法,避免了每次手動添加的麻煩。

b.屬性與對象、類的關係。

關係:屬性是一個類中用來描述對象的抽象概念,一個類可以有很多屬性,一個屬性可以描述對象的一個特徵。

c.屬性、實例變量、成員變量之間的關係。

以下面的屬性代碼舉例:

@property (copy, nonatomic) NSString *myTitle;//聲明屬性

表面關係:
當我們聲明一個屬性的時候,編譯器就會爲我們自動生成對應的實例變量_myTitle,當然,我們也可以通過關鍵字synthesize手動生成對應的實例變量myTitle;

實質原因:鏈接
首先要知道屬性是OC的一種新的語言機制,聲明的屬性必須要有相對應的實例變量。

  • 在蘋果使用LLVM編譯器之前,屬性的使用方式是:也就是手動聲明實例變量,代碼如下:
***.h***
@interface ViewController : UIViewController
{
    //屬性的實例變量
    NSString *myTitle;
}
//編譯器遇到@property會自動聲明對應的setter/getter
@property (copy, nonatomic) NSString *myTitle;
@end

***.m***
//編譯器遇到@synthesize會自動實現setter/getter方法
//編譯器遇到@synthesize回去訪問myTitle的同名變量,如果沒找到就報錯。
@synthesize myTitle;
  • 而蘋果開始使用LLVM編譯器後,編譯器就可以自動爲屬性生成一個名字帶下劃線的實例變量,詳解如下

屬性改變步驟:
1.第一版,最早版本

***.h***
@interface ViewController : UIViewController
{
    NSString *myTitle;
}
//編譯器遇到@property會自動聲明對應的setter/getter
@property (copy, nonatomic) NSString *myTitle;
@end

***.m***
//編譯器遇到@synthesize會自動實現setter/getter方法
//編譯器遇到@synthesize回去訪問myTitle的同名變量,如果沒找到就報錯。
@synthesize myTitle;

2.第二版,不需要自己手動聲明一個成員變量,關鍵字@synthesize會默認去訪問myTitle的同名變量,如果找不到則會自動生成一個

***.h***
@interface ViewController : UIViewController
@property (copy, nonatomic) NSString *myTitle;
@end

***.m***
/*
 1.編譯器遇到@synthesize會自動實現setter/getter方法;
 2.編譯器遇到@synthesize回去訪問myTitle的同名變量;
 3.如果找不到同名的變量,會自動生成一個私有同名變量myTitle
 4.因此現在開始就不用再手動聲明一個實例變量了,
 */
@synthesize myTitle;

3.第三版,考慮到變量名和getter的方法名、setter的參數名一樣,容易讓人誤會,引起警告,所以默認給屬性生成的同名變量名帶下劃線。

/*
 1.指定_myTitle作爲myTitle的實例變量
 2.這樣我們就可以去使用_myTitle,避免和setter名同名產生誤會了
 */
@synthesize myTitle = _myTitle;

4.第四版,在IOS4.5後,也@synthesize可以省略了,最終就變成這樣了

@property (copy, nonatomic) NSString *myTitle;

如果我們把上面的過程全部顯示出來的話,本質如下:

**.h**
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
/*
***被隱藏的代碼:***
1.這個默認是@synthesize myTitle = _myTitle;生成的
2.所以如果我們手動設置@synthesize myTitle,那麼我們編譯器
  生成的變量就是NSString *myTitle,相當於@synthesize myTitle = myTitle,
  如果設置@synthesize myTitle = youTitle,那麼編譯器生成的變量就是NSString *youTitle了
  這要注意。
*/
    NSString *_myTitle;
}
@property (copy, nonatomic) NSString *myTitle;
//***被隱藏的代碼***
//編譯器遇到@property會自動聲明setter/getter方法
- (void)setMyTitle:(NSString *)myTitle;
- (NSString *)myTitle;
@end

**.m**
/*
***被隱藏的代碼***
1.@synthesize關鍵字會自動實現setter/getter的方法
2.@synthesize myTitle = _myTitle指明瞭屬性myTitle的實例變
量是_myTitle,setter/getter操作的對象就是_myTitle.

*/
@synthesize myTitle = _myTitle;
- (void)viewDidLoad {
    [super viewDidLoad];
    _myTitle = @"123";

}

//***被隱藏的代碼***
//由關鍵字@synthesize自動實現
- (NSString *)myTitle{
    return _myTitle;
}
- (void)setMyTitle:(NSString *)myTitle{
    _myTitle = myTitle;
}

代碼說明:
1.編譯器遇到關鍵字@property,自動聲明setter/getter方法。
2.編譯器遇到@synthesize,自動實現setter/getter方法。
3.@synthesize myTitle = _myTitle;爲屬性myTitle生成了一個實例變量_myTitle,所以我們對屬性的操作self.myTitle實質上都是在操作_myTitle變量。

所以屬性、實例變量和成員變量的關係是:
聲明屬性的時候編譯器自動生成的實例變量,實例變量的本質就是成員變量,self.myTitle操作屬性的時候實質上是在操作成員變量_myTitle(也就是實例變量)。


同時重寫setter/getter的問題:
我們會發現,當我們同時重寫setter/getter時會報錯,爲什麼呢?這是因爲當我們同時重寫setter/getter時,編譯器自動添加的代碼@synthesize myTitle = _myTitle;失效,就不會自動爲我們生成實例變量_myTitle了,setter/getter操作的對象就不存在了。所以我們要加上@synthesize myTitle = _myTitle;,手動指定setter/getter要操作的實例對象是_my

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章