欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

舉例講解Objective-C中@property屬性的用法

 更新時(shí)間:2016年03月25日 09:12:30   作者:子龍山人  
這篇文章主要介紹了Objective-C中@property屬性的用法,包括@property的屬性關(guān)鍵字的整理,需要的朋友可以參考下

學(xué)過(guò)c/c++的朋友都知道,我們定義struct/class的時(shí)候,如果把訪問限定符(public,protected,private)設(shè)置為public的話,那么我們是可以直接用.號(hào)來(lái)訪問它內(nèi)部的數(shù)據(jù)成員的。比如

//in Test.h
class Test
{
public:
  int i;
  float f;
};

  我在main函數(shù)里面是可以通過(guò)下面的方式來(lái)使用這個(gè)類的:(注意,如果在main函數(shù)里面使用此類,除了要包含頭文件以外,最重要的是記得把main.m改成main.mm,否則會(huì)報(bào)一些奇怪的錯(cuò)誤。所以,任何時(shí)候我們使用c++,如果報(bào)奇怪的錯(cuò)誤,那就要提醒自己是不是把相應(yīng)的源文件改成.mm后綴了。其它引用此類的文件有時(shí)候也要改成.mm文件)

  //in main.mm
  Test test;
  test.i =1;
  test.f =2.4f;
  
  NSLog(@"Test.i = %d, Test.f = %f",test.i, test.f);

  但是,在objc里面,我們能不能這樣做呢?請(qǐng)看下面的代碼:(新建一個(gè)objc類,命名為BaseClass)

復(fù)制代碼 代碼如下:

//in BaseClass.h
@interface BaseClass : NSObject{
@public
    NSString *_name;
}

 接下來(lái),我們?cè)趍ain.mm里面:
復(fù)制代碼 代碼如下:

    BaseClass *base= [[BaseClass alloc] init];
    base.name =@"set base name";
    NSLog(@"base class's name = %@", base.name);
   

  不用等你編譯,xcode馬上提示錯(cuò)誤,請(qǐng)看截圖:

201632591128870.jpg (700×100)

請(qǐng)大家注意看出錯(cuò)提示“Property 'nam' not found on object of type BaseClass*",意思是,BaseClass這類沒有一個(gè)名為name的屬性。即使我們?cè)陬^文件中聲明了@public,我們?nèi)匀粺o(wú)法在使用BaseClass的時(shí)候用.號(hào)來(lái)直接訪問其數(shù)據(jù)成員。而@public,@protected和@private只會(huì)影響繼承它的類的訪問權(quán)限,如果你使用@private聲明數(shù)據(jù)成員,那么在子類中是無(wú)法直接使用父類的私有成員的,這和c++,java是一樣的。

  既然有錯(cuò)誤,那么我們就來(lái)想法解決啦,編譯器說(shuō)沒有@property,那好,我們就定義property,請(qǐng)看代碼:

復(fù)制代碼 代碼如下:

//in BaseClass.h
@interface BaseClass : NSObject{
@public
    NSString *_name;
}
@property(nonatomic,copy) NSString *name;
//in BaseClass.m
@synthesize name = _name;

  現(xiàn)在,編譯并運(yùn)行,ok,很好。那你可能會(huì)問了@prperty是不是就是讓”."號(hào)合法了呀?只要定義了@property就可以使用.號(hào)來(lái)訪問類的數(shù)據(jù)成員了?先讓我們來(lái)看下面的例子:
復(fù)制代碼 代碼如下:

@interface BaseClass : NSObject{
@public
    NSString *_name;
}
//@property(nonatomic,copy) NSString *name;

-(NSString*) name;
-(void) setName:(NSString*)newName;


  我把@property的定義注釋掉了,另外定義了兩個(gè)函數(shù),name和setName,下面請(qǐng)看實(shí)現(xiàn)文件:
復(fù)制代碼 代碼如下:

//@synthesize name = _name;

-(NSString*) name{
    return _name;
}

-(void) setName:(NSString *)name{
    if (_name != name) {
        [_name release];
        _name = [name copy];
    }
}


  現(xiàn)在,你再編譯運(yùn)行,一樣工作的很好。why?因?yàn)槲覄倓傋龅墓ぷ骱拖惹奥暶鰼property所做的工作完全一樣。@prperty只不過(guò)是給編譯器看的一種指令,它可以編譯之后為你生成相應(yīng)的getter和setter方法。而且,注意看到面property(nonatomic,copy)括號(hào)里面這copy參數(shù)了嗎?它所做的事就是
復(fù)制代碼 代碼如下:

_name = [name copy];
  如果你指定retain,或者assign,那么相應(yīng)的代碼分別是:

//property(retain)NSString* name;
_name = [name retain];

//property(assign)NSString* name;
_name = name;


  其它講到這里,大家也可以看出來(lái),@property并不只是可以生成getter和setter方法,它還可以做內(nèi)存管理。不過(guò)這里我暫不討論?,F(xiàn)在,@property大概做了件什么事,想必大家已經(jīng)知道了。但是,我們程序員都有一個(gè)坎,就是自己沒有完全吃透的東西,心里用起來(lái)不踏實(shí),特別是我自己。所以,接下來(lái),我們要詳細(xì)深挖@property的每一個(gè)細(xì)節(jié)。

  首先,我們看atomic 與nonatomic的區(qū)別與用法,講之前,我們先看下面這段代碼:

復(fù)制代碼 代碼如下:

@property(nonatomic, retain) UITextField *userName;    //1

@property(nonatomic, retain,readwrite) UITextField *userName;  //2

@property(atomic, retain) UITextField *userName;  //3

@property(retain) UITextField *userName;  //4

@property(atomic,assign) int i;         // 5

@property(atomic) int i;         //6
@property int i;               //7


  請(qǐng)讀者先停下來(lái)想一想,它們有什么區(qū)別呢?

  上面的代碼1和2是等價(jià)的,3和4是等價(jià)的,5,6,7是等價(jià)的。也就是說(shuō)atomic是默認(rèn)行為,assign是默認(rèn)行為,readwrite是默認(rèn)行為。但是,如果你寫上@property(nontomic)NSString *name;那么將會(huì)報(bào)一個(gè)警告,如下圖:

201632591159602.jpg (700×50)

 因?yàn)槭欠莋c的對(duì)象,所以默認(rèn)的assign修飾符是不行的。那么什么時(shí)候用assign、什么時(shí)候用retain和copy呢?推薦做法是NSString用copy,delegate用assign(且一定要用assign,不要問為什么,只管去用就是了,以后你會(huì)明白的),非objc數(shù)據(jù)類型,比如int,float等基本數(shù)據(jù)類型用assign(默認(rèn)就是assign),而其它objc類型,比如NSArray,NSDate用retain。

  在繼續(xù)之前,我還想補(bǔ)充幾個(gè)問題,就是如果我們自己定義某些變量的setter方法,但是想讓編譯器為我們生成getter方法,這樣子可以嗎?答案是當(dāng)然可以。如果你自己在.m文件里面實(shí)現(xiàn)了setter/getter方法的話,那以翻譯器就不會(huì)為你再生成相應(yīng)的getter/setter了。請(qǐng)看下面代碼:

復(fù)制代碼 代碼如下:

//代碼一:
@interface BaseClass : NSObject{
@public
    NSString *_name;
}
@property(nonatomic,copy,readonly) NSString *name;  //這里使用的是readonly,所有會(huì)聲明geter方法

-(void) setName:(NSString*)newName;

//代碼二:
@interface BaseClass : NSObject{
@public
    NSString *_name;
}
@property(nonatomic,copy,readonly) NSString *name;   //這里雖然聲明了readonly,但是不會(huì)生成getter方法,因?yàn)槟阆旅孀约憾x了getter方法。

-(NSString*) name;   //getter方法是不是只能是name呢?不一定,你打開Foundation.framework,找到UIView.h,看看里面的property就明白了)
-(void) setName:(NSString*)newName;

//代碼三:
@interface BaseClass : NSObject{
@public
    NSString *_name;
}
@property(nonatomic,copy,readwrite) NSString *name;  //這里編譯器會(huì)我們生成了getter和setter

//代碼四:
@interface BaseClass : NSObject{
@public
    NSString *_name;
}
@property(nonatomic,copy) NSString *name;  //因?yàn)閞eadwrite是默認(rèn)行為,所以同代碼三


  上面四段代碼是等價(jià)的,接下來(lái),請(qǐng)看下面四段代碼:  

復(fù)制代碼 代碼如下:

//代碼一:
@synthesize name = _name;  //這句話,編譯器發(fā)現(xiàn)你沒有定義任何getter和setter,所以會(huì)同時(shí)會(huì)你生成getter和setter

//代碼二:
@synthesize name = _name;  //因?yàn)槟愣x了name,也就是getter方法,所以編譯器只會(huì)為生成setter方法,也就是setName方法。

-(NSString*) name{
    NSLog(@"name");
    return _name;
}

//代碼三:
@synthesize name = _name;   //這里因?yàn)槟愣x了setter方法,所以編譯器只會(huì)為你生成getter方法

-(void) setName:(NSString *)name{
    NSLog(@"setName");
    if (_name != name) {
        [_name release];
        _name = [name copy];
    }
}

//代碼四:
@synthesize name = _name;  //這里你自己定義了getter和setter,這句話沒用了,你可以注釋掉。

-(NSString*) name{
    NSLog(@"name");
    return _name;
}

-(void) setName:(NSString *)name{
    NSLog(@"setName");
    if (_name != name) {
        [_name release];
        _name = [name copy];
    }
}


  上面這四段代碼也是等價(jià)的??吹竭@里,大家對(duì)Property的作用相信會(huì)有更加進(jìn)一步的理解了吧。但是,你必須小心,你如果使用了Property,而且你自己又重寫了setter/getter的話,你需要清楚的明白,你究竟干了些什么事。別寫出下面的代碼,雖然是合法的,但是會(huì)誤導(dǎo)別人:
復(fù)制代碼 代碼如下:

//BaseClass.h
@interface BaseClass : NSObject{
@public
    NSArray *_names;
}
@property(nonatomic,assgin,readonly) NSArray *names;  //注意這里是assign

-(void) setNames:(NSArray*)names;

//BaseClass.m
@implementation BaseClass

@synthesize names = _names;

-(NSArray*) names{
    NSLog(@"names");
    return _names;
}

-(void) setNames:(NSArray*)names{
    NSLog(@"setNames");
    if (_name != name) {
        [_name release];
        _name = [name retain];  //你retain,但是你不覆蓋這個(gè)方法,那么編譯器會(huì)生成setNames方法,里面肯定是用的assign
    }
}


  當(dāng)別人使用@property來(lái)做內(nèi)存管理的時(shí)候就會(huì)有問題了??偨Y(jié)一下,如果你自己實(shí)現(xiàn)了getter和setter的話,atomic/nonatomic/retain/assign/copy這些只是給編譯的建議,編譯會(huì)首先會(huì)到你的代碼里面去找,如果你定義了相應(yīng)的getter和setter的話,那么好,用你的。如果沒有,編譯器就會(huì)根據(jù)atomic/nonatomic/retain/assign/copy這其中你指定的某幾個(gè)規(guī)則去生成相應(yīng)的getter和setter。

我們來(lái)整理一下@property中的屬性關(guān)鍵字:
1.原子性 nonatomic/atomic

在默認(rèn)的情況下,由編譯器合成的方法會(huì)通過(guò)鎖定機(jī)制確保其原子性(atomicity)。如果具備nonatomic特質(zhì),則不使用同步鎖。

2.讀/寫權(quán)限  readwrite/readonly

3.內(nèi)存管理語(yǔ)義

assign “設(shè)置方法” 只會(huì)針對(duì)“純量類型”(scalar type, CGFloat或NSInteger等)的簡(jiǎn)單賦值操作

strong “擁有關(guān)系” 為這種屬性設(shè)置新值時(shí),設(shè)置方法先保留新值,并釋放舊值,然后再將新值設(shè)置上去

weak “非擁有關(guān)系” 為這種屬性設(shè)置新值時(shí),設(shè)置方法既不保留新值,也不釋放舊值。此特質(zhì)同assign類似,然而屬性所指的對(duì)象遭到摧毀時(shí),屬性也會(huì)被清空(nil out)

unsafe_unretained 此特質(zhì)的語(yǔ)義和assign相同,但是它適用于“對(duì)象類型”(object type),該特質(zhì)表達(dá)一種“非擁有關(guān)系”(“不保留”,unretained),當(dāng)目標(biāo)對(duì)象遭到摧毀時(shí),屬性值不會(huì)自動(dòng)清空(“不安全”,unsafe),這一點(diǎn)與weak有區(qū)別

copy 此特質(zhì)所表達(dá)的所屬關(guān)系與strong類似。然而設(shè)置方法并不保留新值,而是將其“拷貝”(copy)

4.方法名

getter=<name>

@property (nonatomic, getter=isOn) BOOL on;

setter=<name> 不太常用


總結(jié)
  好了,說(shuō)了這么多,回到我們的正題吧。atomic和nonatomic的作用與區(qū)別:

  如果你用@synthesize去讓編譯器生成代碼,那么atomic和nonatomic生成的代碼是不一樣的。如果使用atomic,如其名,它會(huì)保證每次getter和setter的操作都會(huì)正確的執(zhí)行完畢,而不用擔(dān)心其它線程在你get的時(shí)候set,可以說(shuō)保證了某種程度上的線程安全。但是,我上網(wǎng)查了資料,僅僅靠atomic來(lái)保證線程安全是很天真的。要寫出線程安全的代碼,還需要有同步和互斥機(jī)制。

  而nonatomic就沒有類似的“線程安全”(我這里加引號(hào)是指某種程度的線程安全)保證了。因此,很明顯,nonatomic比atomic速度要快。這也是為什么,我們基本上所有用property的地方,都用的是nonatomic了。

  還有一點(diǎn),可能有讀者經(jīng)??吹剑谖业慕坛痰膁ealloc函數(shù)里面有這樣的代碼:self.xxx = nil;看到這里,現(xiàn)在你們明白這樣寫有什么用了吧?它等價(jià)于[xxx release];  xxx = [nil retain];(---如果你的property(nonatomic,retian)xxx,那么就會(huì)這樣,如果不是,就對(duì)號(hào)入座吧)。

  因?yàn)閚il可以給它發(fā)送任何消息,而不會(huì)出錯(cuò)。為什么release掉了還要賦值為nil呢?大家用c的時(shí)候,都有這樣的編碼習(xí)慣吧。

  int* arr = new int[10];    然后不用的時(shí)候,delete arr; arr = NULL;  在objc里面可以用一句話self.arr = nil;搞定。

相關(guān)文章

  • Unity3d發(fā)布IOS9應(yīng)用時(shí)出現(xiàn)中文亂碼的解決方法

    Unity3d發(fā)布IOS9應(yīng)用時(shí)出現(xiàn)中文亂碼的解決方法

    這里給大家分享的是使用UNity3d發(fā)布IOS9應(yīng)用的時(shí)候,遇到出現(xiàn)中文亂碼的現(xiàn)象的解決方法,核心內(nèi)容非常簡(jiǎn)單就是批量修改NGUI的label字體,下面把代碼奉上。
    2015-10-10
  • iOS如何將照片保存到相冊(cè)

    iOS如何將照片保存到相冊(cè)

    這篇文章主要為大家詳細(xì)介紹了iOS將照片保存到相冊(cè)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • ios使用AVFoundation讀取二維碼的方法

    ios使用AVFoundation讀取二維碼的方法

    這篇文章主要介紹了ios使用AVFoundation讀取二維碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • iOS開發(fā)教程之Status Bar狀態(tài)欄設(shè)置的方法匯總

    iOS開發(fā)教程之Status Bar狀態(tài)欄設(shè)置的方法匯總

    iOS 的 Status Bar 狀態(tài)欄是一個(gè)比較坑的地方,所以下面這篇文章主要給大家介紹了關(guān)于iOS開發(fā)教程之Status Bar狀態(tài)欄設(shè)置的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-08-08
  • iOS粒子路徑移動(dòng)效果 iOS實(shí)現(xiàn)QQ拖動(dòng)效果

    iOS粒子路徑移動(dòng)效果 iOS實(shí)現(xiàn)QQ拖動(dòng)效果

    這篇文章主要為大家詳細(xì)介紹了iOS粒子路徑移動(dòng)效果,iOS實(shí)現(xiàn)QQ拖動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • iOS如何為圓角添加陰影效果示例代碼

    iOS如何為圓角添加陰影效果示例代碼

    最近一個(gè)項(xiàng)目中需要用到投影的效果,還要是圓角,通過(guò)查找相關(guān)的資料終于解決了,所以覺著有必要分享出來(lái),下面這篇文章主要給大家介紹了關(guān)于iOS如何為圓角添加陰影效果的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-10-10
  • iOS中Block的回調(diào)使用和解析詳解

    iOS中Block的回調(diào)使用和解析詳解

    剛剛進(jìn)入iOS開發(fā)行業(yè),發(fā)現(xiàn)開發(fā)中要用到大量的block回調(diào),由此可見它的重要性。本文主要講的是 Block 回調(diào)的使用,以及 Block 是如何實(shí)現(xiàn)這種神奇的回調(diào)兩部分來(lái)講的,下面來(lái)一起看看吧。
    2016-09-09
  • iOS 將系統(tǒng)自帶的button改裝成上圖片下文字的樣子

    iOS 將系統(tǒng)自帶的button改裝成上圖片下文字的樣子

    這篇文章主要介紹了 iOS 將系統(tǒng)自帶的button改裝成上圖片下文字的樣子,代碼是通過(guò)繼承UIButton,然后再重寫layoutSubviews方法,對(duì)自帶的圖片和titleLabel進(jìn)行重新的layout。下面通過(guò)本文給大家分享下實(shí)現(xiàn)代碼
    2016-12-12
  • iOS無(wú)障礙適配西瓜視頻Voice?Over實(shí)踐示例

    iOS無(wú)障礙適配西瓜視頻Voice?Over實(shí)踐示例

    本文從研發(fā)的視角出發(fā),講述了如何使用?Voice?Over、如何適配?Voice?Over?以及適配過(guò)程中如果遇到問題應(yīng)該如何解決。希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • iOS利用余弦函數(shù)實(shí)現(xiàn)卡片瀏覽工具

    iOS利用余弦函數(shù)實(shí)現(xiàn)卡片瀏覽工具

    這篇文章主要為大家詳細(xì)介紹了iOS利用余弦函數(shù)實(shí)現(xiàn)卡片瀏覽工具,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04

最新評(píng)論