Objective-C中的@property

1.@property是什么

@Property是聲明屬性的語法,它可以快速方便的為實例變量創建存取器,并允許我們通過點語法使用存取器。

存取器(accessor):指用于獲取和設置實例變量的方法。用于獲取實例變量值的存取器是getter,用于設置實例變量值的存取器是setter。

2.創建存取器

2.1 手工創建存取器

我們先看兩段代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//?Car.h
#import?<foundation foundation.h="">
@interface?Car?:?NSObject
{
????//?實例變量
????NSString?*carName;
????NSString?*carType;
}
//?setter???????????????????????????????????
-?(void)setCarName:(NSString?*)newCarName;?
//?getter
-?(NSString?*)carName;
//?setter
-?(void)setCarType:(NSString?*)newCarType;
//?getter
-?(NSString?*)carType;
@end</foundation>

上面的代碼中carName和carType就是Car的實例變量,并且可以看到分別對這兩個實例變量聲明了get/set方法,即存取器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#import?"Car.h"
@implementation?Car
//?setter
-?(void)setCarName:(NSString?*)newCarName
{
????carName?=?newCarName;
}
//?getter
-?(NSString?*)carName
{
????return?carName;
}
//?setter
-?(void)setCarType:(NSString?*)newCarType
{
????carType?=?newCarType;
}
//?getter
-?(NSString?*)carType
{
????return?carType;
}
@end

上面代碼是對實例變量存取器的實現。我們可以看到,存取器就是對實例變量進行賦值和取值。按照約定賦值方法以set開頭,取值方法以實例變量名命名。

我們看看如何使用:

1
2
3
4
5
6
7
8
9
10
11
12
//?main.m
#import?"Car.h"
int?main(int?argc,?char?*?argv[])
{
????@autoreleasepool?{
????????Car?*car?=?[[Car?alloc]?init];
????????[car?setCarName:@"Jeep?Cherokee"];
????????[car?setCarType:@"SUV"];
????????NSLog(@"The?car?name?is?%@?and?the?type?is?%@",[car?carName],[car?carType]);??????
????}
????return?0;
}

上面的代碼中我們注意到,對象Car使用了消息語法,也就是使用方括號的語法給存取器發送消息。 返回結果為:

1
The?car?name?is?Jeep?Cherokee?and?the?type?is?SUV

2.2 使用@Property創建存取器

1
2
3
4
5
6
7
8
9
10
11
//?Car.h
#import?<foundation foundation.h="">
@interface?Car?:?NSObject
{
????//?實例變量
????NSString?*carName;
????NSString?*carType;
}
@property(nonatomic,strong)?NSString?*carName;
@property(nonatomic,strong)?NSString?*carType;
@end</foundation>

上面代碼中,我們使用@property聲明兩個屬性,名稱與實例變量名稱相同(讓我們先忽略nonatomic和strong)。

1
2
3
4
5
6
//?Car.m
#import?"Car.h"
@implementation?Car
@synthesize?carName;
@synthesize?carType;
@end

在.m文件中我們使用@synthesize自動生成這兩個實例變量的存取器,并且隱藏了存取器,雖然我們看不到存取器,但它們確實是存在的。

1
2
3
4
5
6
7
8
9
10
11
//?main.m
int?main(int?argc,?char?*?argv[])
{
????@autoreleasepool?{
????????Car?*car?=?[[Car?alloc]?init];
????????car.carName?=?@"Jeep?Compass";
????????car.carType?=?@"SUV";
????????NSLog(@"The?car?name?is?%@?and?the?type?is?%@",car.carName,car.carType);?
????}
????return?0;
}

在上面的代碼中我們可以注意到,Car對象使用點語法給存取器發送消息,并且get與set的語法是相同的,所以這里的點語法可以根據語境判斷我們是要賦值還是取值。

當然我們也依然可以使用消息語法來使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//?main.m
int?main(int?argc,?char?*?argv[])
{
????@autoreleasepool?{
????????Car?*car?=?[[Car?alloc]?init];
????????//?點語法
//????????car.carName?=?@"Jeep?Compass";
//????????car.carType?=?@"SUV";
//????????NSLog(@"The?car?name?is?%@?and?the?type?is?%@",car.carName,car.carType);
????????//?消息語法
????????[car?setCarName:@"Jeep?Compass"];
????????[car?setCarType:@"SUV"];
????????NSLog(@"The?car?name?is?%@?and?the?type?is?%@",[car?carName],[car?carType]);???????
????}
????return?0;
}

上面兩段代碼的執行結果都是:

1
The?car?name?is?Jeep?Compass?and?the?type?is?SUV

總結:@property等同于在.h文件中聲明實例變量的get/set方法,@synthesize等同于在.m文件中實現實例變量的get/set方法。使用@property和synthesize創建存取器要比手動聲明兩個存取方法(getter和setter)更簡單。而且我們在使用屬性時可以使用點語法賦值或取值,語法更簡單,更符合面向對象編程。

3.不必單獨聲明示例變量

如果使用@Property,就不必單獨聲明實例變量了。因為在沒有顯示提供示例變量聲明的前提下,系統會自動幫你生成實例變量。我們通過以下代碼來說明:

1
2
3
4
5
6
7
//?Car.h
#import?<foundation foundation.h="">
@interface?Car?:?NSObject
@property(nonatomic,strong)?NSString?*carName;
@property(nonatomic,strong)?NSString?*carType;
-?(NSString?*)carInfo;
@end</foundation>

在.h文件中我們并沒有聲明實例變量,只是聲明了carName和carType兩個屬性,以及一個carInfo方法,返回值為NSString *。

1
2
3
4
5
6
7
8
//?Car.m
#import?"Car.h"
@implementation?Car
-?(NSString?*)carInfo
{
????return?[NSString?stringWithFormat:@"The?car?name?is?%@?and?the?type?is?%@",_carName,_carType];
}
@end

在.m文件中我們可以注意到,在carInfo方法中我們使用了_carName和_carType實例變量,這就是當我們沒有顯示聲明實例變量時,系統為我們自動生成的。命名規則是以_為前綴,加上屬性名,即_propertyName。

其實在.m文件中實際是存在@synthesize聲明語句的,只是系統將其隱藏了:

1
2
@synthesize?carName?=?_carName;
@synthesize?carType?=?_carType;

那么如果我們不喜歡默認的實例變量命名方法,或者我們希望使用更有語義的名稱,應該怎么做呢。其實很簡單:

1
2
3
4
5
6
7
8
9
10
//?Car.m
#import?"Car.h"
@implementation?Car
@synthesize?carName?=?i_am_car_name;
@synthesize?carType?=?i_am_car_type;
-?(NSString?*)carInfo
{
????return?[NSString?stringWithFormat:@"The?car?name?is?%@?and?the?type?is?%@",i_am_car_name,i_am_car_type];
}
@end

通過上述代碼可以看到,我們只需要通過@synthesize來聲明我們希望的實例變量名。

總結:如果我們希望使用默認的實例變量命名方式,那么我們在.m文件中就不需要使用@synthesize聲明,系統會幫我們自動完成。如果我們希望自己命名實例變量命,那么我們就使用@synthesize顯示聲明我們希望的實例變量名。

4.@property的特性

@property還有一些關鍵字,它們都是有特殊作用的,比如上述代碼中的nonatomic,strong:

1
2
@property(nonatomic,strong)?NSString?*carName;
@property(nonatomic,strong)?NSString?*carType;

我把它們分為三類,分別是:原子性存取器控制內存管理

4.1 原子性

atomic(默認):atomic意為操作是原子的,意味著只有一個線程訪問實例變量。atomic是線程安全的,至少在當前的存取器上是安全的。它是一個默認的特性,但是很少使用,因為比較影響效率,這跟ARM平臺和內部鎖機制有關。

nonatomic:nonatomic跟atomic剛好相反。表示非原子的,可以被多個線程訪問。它的效率比atomic快。但不能保證在多線程環境下的安全性,在單線程和明確只有一個線程訪問的情況下廣泛使用。

4.2 存取器控制

readwrite(默認):readwrite是默認值,表示該屬性同時擁有setter和getter。

readonly: readonly表示只有getter沒有setter。

有時候為了語意更明確可能需要自定義訪問器的名字:

1
@property?(nonatomic,?setter?=?mySetter:,getter?=?myGetter?)?NSString?*name;

最常見的是BOOL類型,比如標識View是否隱藏的屬性hidden。可以這樣聲明:

1
@property?(nonatomic,getter?=?isHidden?)?BOOL?hidden;

4.3 內存管理

@property有顯示的內存管理策略。這使得我們只需要看一眼@property聲明就明白它會怎樣對待傳入的值。

assign(默認):assign用于值類型,如int、float、double和NSInteger,CGFloat等表示單純的復制。還包括不存在所有權關系的對象,比如常見的delegate。

1
@property(nonatomic)?int?running;
1
@property(nonatomic,assign)?int?running;

以上兩段代碼是相同的。

在setter方法中,采用直接賦值來實現設值操作:

1
2
3
-(void)setRunning:(int)newRunning{??
????_running?=?newRunning;??
}

retian:在setter方法中,需要對傳入的對象進行引用計數加1的操作。

簡單來說,就是對傳入的對象擁有所有權,只要對該對象擁有所有權,該對象就不會被釋放。如下代碼所示:

1
2
3
4
5
6
7
8
-(void)setName:(NSString*)_name{??
?????//首先判斷是否與舊對象一致,如果不一致進行賦值。??
?????//因為如果是一個對象的話,進行if內的代碼會造成一個極端的情況:當此name的retain為1時,使此次的set操作讓實例name提前釋放,而達不到賦值目的。??
?????if?(?name?!=?_name){??
??????????[name?release];??
??????????name?=?[_name?retain];??
?????}??
}

strong:strong是在IOS引入ARC的時候引入的關鍵字,是retain的一個可選的替代。表示實例變量對傳入的對象要有所有權關系,即強引用。strong跟retain的意思相同并產生相同的代碼,但是語意上更好更能體現對象的關系。

weak:在setter方法中,需要對傳入的對象不進行引用計數加1的操作。

簡單來說,就是對傳入的對象沒有所有權,當該對象引用計數為0時,即該對象被釋放后,用weak聲明的實例變量指向nil,即實例變量的值為0。

注:weak關鍵字是IOS5引入的,IOS5之前是不能使用該關鍵字的。delegate 和 Outlet 一般用weak來聲明。

copy:與strong類似,但區別在于實例變量是對傳入對象的副本擁有所有權,而非對象本身。

轉載于:https://www.cnblogs.com/holyday/p/7987059.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/278996.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/278996.shtml
英文地址,請注明出處:http://en.pswp.cn/news/278996.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux基礎命令---findfs

findfs 查找指定卷標或者UUID的文件系統對應的設備文件。findfs將搜索系統中的磁盤&#xff0c;尋找具有標簽匹配標簽或與UUID相等的文件系統。如果找到文件系統&#xff0c;文件系統的設備名稱將打印在stdout上。 此命令的適用范圍&#xff1a;RedHat、RHEL、Ubuntu、CentOS、…

canvas 平滑運動_什么是電視上的運動平滑?人們為什么討厭它?

canvas 平滑運動Willy Barton/Shutterstock.com威利巴頓/Shutterstock.comIf you’ve just bought a new TV, you might be wondering why everything you watch feels eerily sped up and smooth, like you’re watching a live broadcast all the time. You’re not imaginin…

linux guard什么進程,使用linux系統性能監控工具KSysguard監控遠端主機介紹

KDE System Guard默認的窗口前端圖形界面使用傳感器(sensors)獲得要顯示的信息。傳感器返回的可以是一個簡單的數值或更復雜的信息如表格。針對不同的信息類型都提供了一個或多個顯示界面。這些顯示界面被組織在多個工作表中&#xff0c;工作表可以獨立存儲和加載。KSysguard主…

macbook充電_如何判斷MacBook是否正在充電

macbook充電2p2play / Shutterstock2p2play / ShutterstockForgetting to charge your MacBook properly overnight can leave you with a headache in the morning. And if you’re troubleshooting a broken MacBook, checking if it’s able to charge is one way to rule o…

mysql記錄

當沒有用EXISTS引入子查詢時&#xff0c;在選擇列表中只能指定一個表達式轉載于:https://www.cnblogs.com/niuben/p/9920741.html

PIL.Image convert to numpy array

當使用PIL.Image讀取圖像時&#xff0c;如果直接使用numpy.array()轉換會出現錯誤&#xff1a; lst list() for file_name in os.listdir(dir_image):image PIL.Image.open(file_name)lst.append(image) arr numpy.array(lst) 此時&#xff0c;上述最后一行在執行時會出現錯…

NFC服務器在Linux,linux 安裝 libnfc ,打開串口PN532

硬件準備&#xff1a;USB轉串口4針杜邦線PN532模塊IC卡一張(比如門禁卡&#xff0c;飯卡等)軟件準備&#xff1a;Ubuntu 物理機一臺能夠訪問互聯網1&#xff0c;將PN532與USB轉串口連接好,放一張IC卡靠近PN532模塊2&#xff0c;安裝libnfc&#xff1a;chunliubuntu:~$ sudo apt…

chrome同步_如何在Chrome中打開或關閉同步

chrome同步Google Chrome lets you sync up your Google account to your browser across any device. When enabled, bookmarks, history, passwords, extensions, and themes—among many other settings—sync from your Google account, creating a seamless experience no…

sublime text3搭建react native

Sublime Text 3 搭建React.js開發環境 Sublime有很強的自定義功能&#xff0c;插件庫很龐大&#xff0c;針對新語言插件更新很快&#xff0c;配合使用可以快速搭建適配語言的開發環境。 1. babel-sublime 支持ES6&#xff0c; React.js, jsx代碼高亮&#xff0c;對 JavaScript,…

linux系統輸入指令,詳解linux系統輸入輸出管理和vim的常用功能

####系統中輸入輸出的管理####1.理解系統的輸入輸出重定向輸入重定向是指把文件導入到命令中&#xff0c;而輸出重定向則是把原本要輸出到屏幕的數據信息寫入到指定文件中。2.管理輸入輸出的符號##輸出重定向> ##重定向正確輸2> ##重定向錯誤輸出&> …

Deep Learning(深度學習)學習筆記整理(二)

本文整理了網上幾位大牛的博客&#xff0c;詳細地講解了CNN的基礎結構與核心思想&#xff0c;歡迎交流 [1]Deep learning簡介 [2]Deep Learning訓練過程 [3]Deep Learning模型之&#xff1a;CNN卷積神經網絡推導和實現 [4]Deep Learning模型之&#xff1a;CNN的反向求導及練習 …

百度新聞 谷歌新聞_每日新聞摘要:到目前為止,Google I / O提供的最佳信息

百度新聞 谷歌新聞Google’s yearly developer conference started yesterday, and the keynote was chock-full of announcements, demos, and some utterly mind-blowing tech. From Assistant to Android, here’s some of the best stuff to come out of I/O 2019 so far. …

u盤裝服務器linux軟件,服務器維護給您的U盤安裝linux

服務器維護給您的U盤安裝linux如何做好服務器維護?北京艾銻無限科技與你談談IT人員必須知道的服務器維護信息服務器維護小知識因為現在linux普及率實在不高&#xff0c;很多地方都沒有安裝&#xff0c;包括高校機房。為了自身方便和宣傳推廣linux&#xff0c;決定在U盤上安裝一…

幾個WMS的問題處理

采購訂單沒有生成上傳訂單號pkg_inpurchase_task.p_rk_sc_rkd_zc iv_yzid ----- ZDA iv_djbh ---- KPD00014712 銷售訂單下傳下去后直接轉歷史表 select * from INTERFACE_OUT_SALE_M t where djbh like %XSGYMA00220297%日志表查詢結果ORA-01400: 無法將 NULL 插入 ("WMS…

yyblog2.0 數據庫開發規范

一、基礎規范 &#xff08;1&#xff09;必須使用InnoDB存儲引擎 解讀&#xff1a;支持事務、行級鎖、并發性能更好、CPU及內存緩存頁優化使得資源利用率更高 &#xff08;2&#xff09;表字符集默認使用utf8&#xff0c;必要時候使用utf8mb4 解讀&#xff1a;1、通用&#xff…

word2016 語法檢查_如何改進Microsoft Word的語法檢查器

word2016 語法檢查Microsoft Word comes with a powerful grammar checker, but many of its advanced grammar detection features are disabled by default. Grammarly is popular, but you don’t need it to add grammar checking to Word. Word itself contains a free al…

linux服務器硬件監控,Linux服務器實時監控加載硬件信息

Linux服務器監控之實時監控加載硬件信息Linux負有盛名的特點之一是其非凡的穩定性。然而&#xff0c;如果您的硬件有缺陷或配置不正確&#xff0c;即使是世界上最穩定的操作系統也不會對您有什么幫助。計算機系統是由軟件系統硬件系統組成的&#xff0c;檢測硬件狀態對于保障整…

Using Python with Oracle

2019獨角獸企業重金招聘Python工程師標準>>> Using Python with Oracle This page discusses using Python with Oracle. The page is based on the cx_oracle Python extension module. It was developed on a VM running Oracle Enterprise Linux 6U4 runnng Orac…

小米oj 反向位整數(簡單位運算)

反向位整數 序號&#xff1a;#30難度&#xff1a;一般時間限制&#xff1a;1000ms內存限制&#xff1a;10M 描述 輸入32位無符號整數&#xff0c;輸出它的反向位。 例&#xff0c;輸入4626149&#xff08;以二進制表示為00000000010001101001011011100101&#xff09;&#xff…

如何在Microsoft Word中插入簽名

Adding your signature to a Microsoft Word document is the ultimate way to personalize it as your own, especially for documents like letters or contracts. If you want to add a signature to a Word document, here’s how. 將簽名添加到Microsoft Word文檔是將其個…