国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院

首頁 > 系統(tǒng) > iOS > 正文

iOS常見的幾個修飾詞深入講解

2019-10-21 18:39:52
字體:
供稿:網(wǎng)友

前言:

最近公司在擴招,做為公司僅有的唯一一個首席iOS開發(fā)工程師(手動滑稽),我不得不硬著頭皮上陣。

然后卻發(fā)現(xiàn)很多人的水平和年限嚴重不符,公司招的人都是3年+以上經(jīng)驗的人,然而這些人中有一半連修飾詞的作用也說的模棱兩可,加上自己水平也不高,對以后的職業(yè)生涯產(chǎn)生了嚴重的危機感,遂決定以后每周希望能寫一篇有價值的文章,與君共勉,今天就說說iOS常見的幾個修飾詞。

一、readOnly,readWrite

readOnly:

根據(jù)字面意思,大家都很容易知道是“只讀”的意思,意味著只生成了getter方法,而沒有生成setter方法,如果這時候調(diào)用setter方法,會報一個Assignment to readonly property錯誤

PS:這里順便說一下self.和_的區(qū)別

self.就是調(diào)用property自動生成的getter和setter方法,而_則是直接去調(diào)用實例變量(property會自動生成一個實例變量,如果你重寫了getter與setter方法,property自動生成的實例變量就無效了,需要手動去申明一個實例變量或者用@@synthesize).

回到正題,那么這意味著我們就完全沒辦法去修改readOnly的屬性了嗎?不然,如果你嘗試一下setValue:forKey:,你就會發(fā)現(xiàn)竟然改變成功了,amazing,讓我們來看看代碼:

@interface MyFirstClass : NSObject@property (nonatomic, copy, readonly) NSString * string;@end#import "MyFirstClass.h"@implementation MyFirstClass- (instancetype) init{ self = [super init]; if (self) { _string = @"來改變我啊"; } return self;}@end- (void)viewDidLoad { [super viewDidLoad]; MyFirstClass * class = [MyFirstClass new]; NSLog(@"string === %@", class.string); [class setValue:@"改變了" forKey:NSStringFromSelector(@selector(string))]; NSLog(@"string === %@", class.string);}Log如下:2018-03-16 11:08:58.932303+0800 PropertyDesc[5681:445705] string === 來改變我啊2018-03-16 11:08:58.932454+0800 PropertyDesc[5681:445705] string === 改變了

而如果這個時候在MyFirstClass里加入

@implementation MyFirstClass- (instancetype) init{ self = [super init]; if (self) { _string = @"來改變我啊"; }  return self;}+ (BOOL) accessInstanceVariablesDirectly{ return NO;}@end

在運行,boom,系統(tǒng)會報以下錯誤

2018-03-16 11:19:21.619747+0800 PropertyDesc[6016:478446] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MyFirstClass 0x6040000088f0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key string.'

沒有找到當前要賦值的屬性,那么accessInstanceVariablesDirectly究竟是什么呢,我們打開蘋果的官方文檔找到Key-Value Coding Programming Guide

iOS,修飾詞

在這里可以看到,如果這個方法設(shè)為YES,訪問器就會去尋找名稱為_<key>, _is<Key>, <key>, or is<Key>的成員變量,如果為NO,就會跳到第6步,第6步就會報[valueForUndefinedKey:]錯誤。

總結(jié):

readOnly并不能完全保證只讀,我們可以通過KVC嘗試去修改其值。

PS:有興趣的小伙伴可以嘗試去修改別人的SDK,包括蘋果爸爸的

readWrite:

這個實在沒什么可說的,默認的修飾詞就是readWrite,代表可讀可寫

二、nonatomic、atomic

我們先看一下官方文檔

iOS,修飾詞

蘋果官網(wǎng)對兩者的說法

atomic:

默認的屬性修飾詞,按官方文檔上說即使從不同的線程通過getter或setter方法去訪問屬性也能完全的獲取到或設(shè)置值,從這里也可以看出,atomic并不是線程安全的,因為atomic只能保證通過setter和getter方法能獲取到一個完整的value,如果A線程在getter,B、C線程在setter,可能A獲取到的值是BC執(zhí)行之后的值,也可能是BC線程執(zhí)行完之前的值,也可能是B C線程任何一個線程執(zhí)行完的值。

因此atomic的偽代碼大概如下:

- (void)setString:(NSString *)string{ @synchronized(self) { if (_string != string) {  [_string release];//MRC  _string = [string copy]; } }}- (NSString *) string{ @synchronized(self) { return _ string; }}

nonatomic:

相對而言,通過nonatomic修飾的屬性,并沒有做鎖的操作,多線程同時進行setter/getter操作,并不能保證得到一個完整的value,所以相對atomic來說nonatomic修飾的屬性訪問速度更快,而且平時對線程安全我們更傾向于使用信號量、NSLock和synchronized去控制線程安全,他們都能保證代碼塊的原子性,所以幾乎所有的屬性都用nonatomic去修飾。

三、assign、weak與strong

assign:

一般來說,我們都用assign去修飾OC的基本數(shù)據(jù)類型,but why?

因為assign并不會使對象的引用計數(shù)加1,也就是說如果用assign去修飾一個對象,這個對象會立即被釋放,重要的是assgin在被釋放的時候是不會自動置為nil,還是保留對象的指針地址,會形成野指針,這個時候向其發(fā)送消息就會崩潰,簡單實驗的代碼如下:

@interface MySecondClass : NSObject@property (nonatomic, assign) NSMutableArray * array;@end- (void) testMethodTwo{ MySecondClass * class = [[MySecondClass alloc] init]; self.secondClass = class; self.secondClass.array = [NSMutableArray array]; [self.secondClass.array addObject:@(0)];}

在運行到最后一步的時候程序會崩潰報EXC_BAD_ACCESS的錯誤,如果打斷點的話會發(fā)現(xiàn)在執(zhí)行到這步的時候array還是有地址的。

weak:

如果把上面的代碼
@property (nonatomic, assign) NSMutableArray * array;換成
@property (nonatomic, weak) NSMutableArray * array;

.這個時候程序并不會崩潰,如果你打個斷點的話會發(fā)現(xiàn)array被自動置為nil,而OC的特性使得像nil發(fā)送消息并不會崩潰,這就是weak和assgin最大的區(qū)別,此外weak必須用于修飾對象,這和他自動置為nil相關(guān),如果強行使用weak修飾基本數(shù)據(jù)類型,編譯器會報一個大大的紅色錯誤!

strong:

strong的作用和assign和weak恰恰相反,strong也是屬性默認的修飾詞,代表著被修飾的對象引用計數(shù)+1

如果把上面的代碼
@property (nonatomic, assign) NSMutableArray * array;換成
@property (nonatomic, strong) NSMutableArray * array;

self.secondClass.array = [NSMutableArray array];

最后一句代碼可以解釋為[NSMutableArray array]創(chuàng)造了一個對象A,此時A的引用計數(shù)為1,self.secondClass.array做為對象B,把A賦值給B的時候,A的引用計數(shù)加1,此時A的引用計數(shù)為2,B指向了A,然后編譯器會自動對A進行釋放操作(因為是局部變量),A的引用計數(shù)-1。在擁有B的對象不釋放的時候,A的引用計數(shù)永遠不可能為0,除非你手動釋放或者把B指向一個新的對象,這樣A永遠不會被釋放,這就是所謂的強引用。

weak和strong的區(qū)別:weak和strong不同的是 當一個對象不再有strong類型的指針指向它的時候 它會被釋放 ,即使還有weak型指針指向它。一旦最后一個strong型指針離去 ,這個對象將被釋放,所有剩余的weak型指針都將被清除。

copy與retain:

  • copy其實是建立了一個相同的對象,而retain不是.
  • copy是內(nèi)容拷貝,retain是指針拷貝.
  • copy是內(nèi)容的拷貝 ,對于像NSString,的確是這樣,如果拷貝的是NSArray這時只是copy了指向array中相對應(yīng)元素的指針.這便是所謂的"淺復制".

atomic是Objc使用的一種線程保護技術(shù),基本上來講,是防止在寫未完成的時候被另外一個線程讀取,造成數(shù)據(jù)錯誤。而這種機制是耗費系統(tǒng)資源的,所以在iPhone這種小型設(shè)備上,如果沒有使用多線程間的通訊編程,那么nonatomic是一個非常好的選擇。

四、copy與mutableCopy

iOS,修飾詞

蘋果官網(wǎng)對對象拷貝的說法

在說copy與mutableCopy之前我們先看看官方文檔對深拷貝與淺拷貝的闡釋,如下

深拷貝:

對象拷貝 - 重新申請一片內(nèi)存保留這個對象,與原對象之間沒有半點關(guān)系。

淺拷貝:

指針拷貝 - 實際上相當于引用計數(shù)+1,被拷貝的和拷貝的引用同一個對象。

接下來我們分兩個方面做測試:

1.對非集合類對象的copy操作,以NSString為例

對immutableObject做copy操作

 NSString * string = [NSString stringWithFormat:@"1"]; NSString * copyString = [string copy]; NSString * mutableCopyString = [string mutableCopy]; NSLog(@"string:%p", string); NSLog(@"copyString:%p", copyString); NSLog(@"mutableCopyString:%p", mutableCopyString);

Log如下:

2018-03-19 15:51:38.785253+0800 PropertyDesc[10283:759804] string:0xa000000000000311
2018-03-19 15:51:38.785435+0800 PropertyDesc[10283:759804] copyString:0xa000000000000311
2018-03-19 15:51:38.785518+0800 PropertyDesc[10283:759804] mutableCopyString:0x608000055150

可以看出對string和copyString的地址是一樣的,而mutableCopyString則不同。

對mutableObject做copy操作

 NSMutableString * string = [NSMutableString stringWithFormat:@"1"]; NSString * copyString = [string copy]; NSString * mutableCopyString = [string mutableCopy]; NSLog(@"string:%p - %@", string, string); NSLog(@"copyString:%p - %@", copyString, copyString); NSLog(@"mutableCopString:%p - %@", mutableCopyString, mutableCopyString); [string appendString:@",2"]; NSLog(@"copyString:%p - %@", copyString, copyString); NSLog(@"mutableCopString:%p - %@", mutableCopyString, mutableCopyString);

Log如下:

2018-03-19 15:51:38.785670+0800 PropertyDesc[10283:759804] string:0x60400005a940 - 1
2018-03-19 15:51:38.785784+0800 PropertyDesc[10283:759804] copyString:0xa000000000000311 - 1
2018-03-19 15:51:38.785834+0800 PropertyDesc[10283:759804] copyString:0xa000000000000311 - 1
2018-03-19 15:51:38.785891+0800 PropertyDesc[10283:759804] mutableCopyString:0x60400005a910 - 1
2018-03-19 15:51:38.786037+0800 PropertyDesc[10283:759804] mutableCopyString:0x60400005a910 - 1

可以看出對string與copyString、mutableCopyString三者的地址都是不同的。

即使改變了原string的value,copyString與mutableCopystring也沒有改變,這與下文對集合類對象得出的結(jié)論正好相反。

結(jié)論:

對 immutableObject進行 copy 操作是指針拷貝,mutableCopy 操作時對象拷貝。

對 mutable Object進行 copy 和 mutableCopy 都是對象拷貝。簡單的表格圖如下:

 

Object Handle Result
immutableObject copy 指針拷貝
immutableObject mutableCopy 深拷貝
mutableObject copy 深拷貝
mutableObject mutableCopy 深拷貝

 

2.對集合類對象的copy操作

對immutableObject做copy操作

 NSArray * array = [NSArray arrayWithObject:@"1"]; NSArray * copyArry = [array copy]; NSMutableArray * mutableCopyArray = [array mutableCopy];  NSLog(@"array:%p", array); NSLog(@"copyArry:%p", copyArry); NSLog(@"mutableCopyArray:%p", mutableCopyArray);

Log如下

2018-03-19 15:51:38.786167+0800 PropertyDesc[10283:759804] array:0x6000000094c0
2018-03-19 15:51:38.786278+0800 PropertyDesc[10283:759804] copyArray:0x6000000094c0
2018-03-19 15:51:38.786385+0800 PropertyDesc[10283:759804] mutableCopyArray:0x600000240030

可以看出array與copyArray的地址是一樣的,而mutableCopyArray則不同。

對mutableObject做copy操作

 NSMutableString * string = [NSMutableString stringWithFormat:@"1"]; NSMutableArray * array = [NSMutableArray arrayWithObject:string]; NSArray * copyArry = [array copy]; NSMutableArray * mutableCopyArray = [array mutableCopy];  NSLog(@"array:%p", array); NSLog(@"copyArry:%p", copyArry); NSLog(@"mutableCopyArray:%p", mutableCopyArray); [array addObject:@"2"]; [string appendString:@"1"];  NSLog(@"array:%p - %@", array, array); NSLog(@"copyArry:%p - %@", copyArry, copyArry); NSLog(@"mutableCopArray:%p - %@", mutableCopyArray, mutableCopyArray);

Log如下

2018-03-26 13:36:38.786499+0800 PropertyDesc[10283:759804] array:0x600000240150
2018-03-26 13:36:38.786600+0800 PropertyDesc[10283:759804] copyArry:0x6000000095f0
2018-03-26 13:36:38.786698+0800 PropertyDesc[10283:759804] mutableCopyArray:0x6000002400f0
2018-03-26 13:36:38.786865+0800 PropertyDesc[10283:759804] array:0x600000240150 - (
    11,
    2
)
2018-03-26 13:36:38.787018+0800 PropertyDesc[10283:759804] copyArry:0x6000000095f0 - (
    11
)
2018-03-26 13:36:38.787142+0800 PropertyDesc[10283:759804] mutableCopyArray:0x6000002400f0 - (
    11
)

What??不管是copy還是mutableCopy我們可以看到當我們修改了string的值后,數(shù)組中的值都變了,但是在 [array addObject:@"2"];的時候兩個復制出來的數(shù)組的對象并沒有變化?

這里我們要提到一個新概念 不完全深拷貝(也有人說是單層深拷貝 )------ 即雖然新開辟了內(nèi)存地址,但是存放在內(nèi)存上的值(也就是數(shù)組里的元素仍然指向原數(shù)組元素值,并沒有另外復制一份),所以說上文中的array和mutableCopArray類似于有一個或多個相交點的相交鏈表。

而且我們也可以看到不管是copy還是mutableCopy都是不完全深拷貝,三者的地址都是不一樣的。

結(jié)論:

對immutableObject做copy是指針拷貝,做mutableCopy是不完全深拷貝。

對mutableObject做copy或mutableCopy都是不完全深拷貝。

有趣的是,這與上文的結(jié)論有類似之處。簡單的表格圖如下:

Object Handle Result
immutableObject copy 指針拷貝
immutableObject mutableCopy 不完全深拷貝
mutableObject copy 不完全深拷貝
mutableObject mutableCopy 不完全深拷貝

并且如果打個斷點可以發(fā)現(xiàn)對任何對象做copy操作返回的是一個不可變的對象,對任何對象做mutableCopy返回的是一個可變的對象(有興趣的請自行驗證)。

五、是用copy還是strong?

通過上述對copy與strong的描述,copy和strong最終都會返回一個引用計數(shù)為1的對象,所以單單從內(nèi)存管理上說copy和strong并無任何區(qū)別,但是copy始終會返回一個不可變對象,他的值是不會被修改的。

而strong不同,被strong修飾的對象,可能會被可變對象賦值,從而在外部導致不可預料的被更改的情況。

總而言之,是否使用copy或strong還是根據(jù)具體場景來定,這里還有個性能優(yōu)化的小技巧,如果copy的是可變的對象,會對它做一次完全深拷貝/不完全深拷貝,性能上是肯定不如strong直接引用計數(shù)+1來的快。

六、結(jié)尾

這次的修飾詞講解到此就告一段落了,然后想一下這周寫什么樣的文章。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識閱讀請移步到IOS開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院
国产视频精选在线| 国产精品偷乱一区二区三区 | 最近久乱中文字幕| 国产三区在线观看| 1区2区3区在线| 国产成人福利| 国产三级自拍| 国产极品视频| 国产精品美女一区二区视频| 蜜桃视频网站在线| 在线观看精品视频一区二区三区 | 中文字幕在线资源| 国产精品福利视频一区二区三区| 国产不卡在线| 另类综合图区| 91欧洲在线视精品在亚洲| 亚洲精品自拍区在线观看| 超碰在线网站| 99久热re在线精彩视频| 国产黄色片在线播放| 精品一区二区观看| 黄色激情网址| 欧美精品另类| 成人欧美亚洲| 国产成在线观看免费视频| 伊人免费视频| 五月天天在线| 午夜在线视频| 国产麻豆高清视频在线第一页| 国产美女免费观看| 2019中文字幕视频| 国产在线你懂得| av免费在线播放| 国产午夜精品一区理论片| 亚洲综合在线免费| 中文字幕av网| 国产成人va亚洲电影| 国产经典自拍视频在线观看 | 国产精品偷乱一区二区三区| 日本国产在线| 免费在线超碰| 国产毛片视频| 国产一级又黄| 国产精品日日爱| 国产福利小视频在线观看| 国产网站av| 国产精品美女一区二区三区四区 | 国产精品理人伦一区二区三区 | 国产婷婷视频在线| 国产精品久久人| 99热国产在线| 欧美精品另类| 国产在线免费观看| 国产天堂在线播放视频| 国产网友自拍电影在线 | 午夜免费福利在线观看| 久久久久久久久免费视频| 久草在线资源福利| 中文字幕久热在线精品| 国产区在线观看| 在线成人综合色一区| 久草一本av| 国产福利在线免费观看| av在线不卡免费| 国产美女高潮| 在线中文字幕第一页| wwww亚洲| √天堂资源中文www| 免费在线播放av| 综合激情亚洲| 欧美日韩亚洲第一页| 国产日韩欧美第一页| 三级小说一区| 91国内在线| 国产午夜在线| 欧美午夜电影一区二区三区| 五月婷婷开心综合| 羞羞视频在线免费看| 最好2018中文免费视频| 亚洲第一成人在线视频| 国产精品天堂| 人成在线免费视频| 国产黄色免费| 国产精品一区二区三区视频网站 | 国产无遮挡又黄又爽免费网站| 在线观看av中文| 91精品国产91久久久久久青草| 九九热在线视频| 亚洲xxxxxx| 天堂网中文在线| 亚洲精品影视在线| 亚洲尤物在线视频| 亚洲成人在线播放| gogogogo高清视频在线| 99reav| 午夜视频99| 国产一级大片| 国产网站麻豆精品视频| 中文字幕第一页在线| 国产色视频网站| 国产亚洲精品久久久久久青梅| 成在线人视频免费视频| 国产尤物视频| 国产无套粉嫩白浆在线2022年 | 国产又色又爽又黄刺激在线视频| eeuss影院在线观看第一页| 精品精品导航| 中文字幕av高清在线观看| 伊人影院在线观看| 日日夜夜中文字幕| 狠狠狠狠狠狠操| 九九视频精品在线| 国产丝袜在线| 99re热视频在线| 免费午夜一级| 中文字幕在线资源| 精品偷拍激情视频在线观看| 中文资源在线官网| 免费看的毛片| 国产精品久久久久久福利| 精品欧美不卡一区二区在线观看| 国产对白在线| av在线网页| 最好看更新中文字幕| 国产超碰在线| 国产在线激情视频| 91激情在线| 中文字幕色视频| 日韩亚洲一区中文字幕| 国产亚洲精品拍拍拍拍拍| 夜夜操天天干| 国产一级视频| 青青在线视频| 在线免费看黄| 国产三级在线| 天堂在线亚洲| 91最新在线| 最新天堂资源在线资源| 一个人看的www免费观看视频| 国产精品一区二三区| 香蕉视频在线观看网站| 国产高清一级片| 天天操天天操一操| 亚洲欧美精选| 国产福利在线看| 国产系列在线观看| 最好看更新中文字幕| 麻豆视频在线观看免费网站| 国产va在线观看| 最近最好的中文字幕2019免费| 99中文字幕一区| 国产天堂素人系列在线视频| 豆国产97在线|亚洲| 久久久久久久久久久久久91| 在线国产1区| 亚洲欧美中文字幕在线观看| 国产精品视频福利一区二区| 国内自拍视频在线看免费观看| www.eeuss影院| 日本高清中文字幕| 久蕉依人在线视频| 导航福利在线| 尤物在线网址| 国产对白国语对白| 在线视频观看亚洲| 一本大道香蕉久久| 伊人影院蕉久影院在线播放| 精品51国产黑色丝袜高跟鞋| 91视频久色| eeuss影院网站免费观看| www.xxx黄| 国产精品亚洲第五区在线| 国产美女视频网站| 国产人成高清视频观看| 国产精品久久麻豆| 亚洲人av在线| 五月婷婷丁香激情| 在线视频观看亚洲| 久久99精品久久久久久野外| 尤物网站在线| 精品国产一区二区三区不卡在线| 国产国语**毛片高清视频| 一区二区精品区| 黄色毛片在线看| 国产成人午夜精品| 欧美艹逼视频| 国产成人久久精品77777| 亚洲wwwwww| 国产精品伦理一区二区三区 | 国产婷婷视频在线| 伊人春色在线| 99热在线免费观看| 亚洲精品天堂在线| 国产区视频在线观看| 亚洲日本伊人| 国产嫩草在线视频| 91精品国产高久久久久久五月天| 欧美精品另类| 精品亚洲成a人片在线观看| 黄网址在线播放免费|