前言
做iOS開發(fā)也有不短的時(shí)間,文章看過不少瘪弓, 還從來沒自己寫過垫蛆,這篇是第一次寫,如果有哪兒寫的不正確腺怯,或者有疑義的袱饭,歡迎大家指正,大家一起交流學(xué)習(xí)呛占。當(dāng)然網(wǎng)上有很多相關(guān)的文章虑乖,但老話說的好:好記性不如爛筆頭(筆者深有體會(huì),很多看過的沒過幾天就忘記了)晾虑。
正文
好了疹味,廢話少敘,直接開始進(jìn)入正題帜篇。
屬性的關(guān)鍵字是我們開發(fā)中最基本的糙捺,也是不可避免的一環(huán),大家可能平時(shí)開發(fā)過程中一直用笙隙,但是不會(huì)注意到它洪灯,但是開發(fā)久了,自然還是想知道一些竟痰,下面就給大家說一說這些關(guān)鍵字签钩。
property關(guān)鍵字一般分為三類:原子性(線程安全)相關(guān)轩端、引用計(jì)數(shù)(內(nèi)存管理)相關(guān)才顿、讀寫性相關(guān)
原子性相關(guān)
automatic:屬性默認(rèn)關(guān)鍵字糕珊,原子性的崖堤,線程安全的假消。保證了程序在運(yùn)行期間柠并,不會(huì)出現(xiàn)某一條線程還沒有執(zhí)行完set方法,另一條就執(zhí)行的情況發(fā)生富拗。
這里有一個(gè)值得注意的地方臼予,automatic只是對屬性的set方法加鎖,僅僅保證的是“寫”這個(gè)操作的線程安全性啃沪,而實(shí)際開發(fā)過程中一般要求的是“讀寫”過程整體的線程安全性粘拾。另外由于automatic加鎖的方式使用的是@synchronized,所以開銷較大创千,影響性能缰雇。所以日常開發(fā)中不會(huì)使用automatic來實(shí)現(xiàn)線程安全,究其原因就是上述了追驴,至于線程安全不是這篇文章的主題械哟,這里就不研究了。
nonautomatic:我們開發(fā)中默認(rèn)使用的property關(guān)鍵字殿雪,與automatic對應(yīng)暇咆。
讀寫性相關(guān)(沒有太多可寫的)
readwrite:默認(rèn)屬性,可讀可寫丙曙,生成setter和getter方法爸业。
readonly:只讀屬性,只生成getter方法亏镰,也就是說只能訪問變量扯旷,不能修改(當(dāng)然這只是代碼規(guī)范情況下)。
內(nèi)存管理相關(guān)
assign :用于非指針變量索抓。用于基礎(chǔ)數(shù)據(jù)類型 (例如NSInteger)和C數(shù)據(jù)類型(int, float, double, char, 等)钧忽,另外還有id 。setter?方法直接賦值纸兔,不進(jìn)行任何?retain?操作惰瓜。
用于對基本數(shù)據(jù)類型進(jìn)行復(fù)制操作,不更改引用計(jì)數(shù)汉矿。也可以用來修飾對象崎坊,但是,被assign修飾的對象在釋放后洲拇,指針的地址還是存在的奈揍,也就是說指針并沒有被置為nil曲尸,成為野指針。如果后續(xù)在分配對象到堆上的某塊內(nèi)存時(shí)男翰,正好分到這塊地址另患,程序就會(huì)crash。之所以可以修飾基本數(shù)據(jù)類型蛾绎,因?yàn)榛緮?shù)據(jù)類型一般分配在棧上昆箕,棧的內(nèi)存會(huì)由系統(tǒng)自動(dòng)處理,不會(huì)造成野指針租冠。
我們常見的id delegate往往是用assign方式的屬性而不是retain方式的屬性鹏倘,賦值不會(huì)增加引用計(jì)數(shù),就是為了防止delegation兩端產(chǎn)生不必要的循環(huán)引用顽爹。如果一個(gè)UITableViewController 對象a通過retain獲取了UITableView對象b的所有權(quán)纤泵,這個(gè)UITableView對象b的delegate又是a, 如果這個(gè)delegate是retain方式的镜粤,那基本上就沒有機(jī)會(huì)釋放這兩個(gè)對象了捏题。自己在設(shè)計(jì)使用delegate模式時(shí),也要注意這點(diǎn)肉渴。因?yàn)檠h(huán)引用而產(chǎn)生的內(nèi)存泄露也是Instrument無法發(fā)現(xiàn)的公荧,所以要特別小心。
weak:對對象的弱引用黄虱,不增加對象的引用計(jì)數(shù)稚矿,也不持有對象,當(dāng)對象消失后指針自動(dòng)指向nil捻浦,所以這里也就防止了野指針的存在晤揣。
修飾的對象在釋放后,指針地址會(huì)被置為nil朱灿,是一種弱引用昧识。在ARC環(huán)境下,為避免循環(huán)引用盗扒,往往會(huì)把delegate屬性用weak修飾跪楞,當(dāng)然對于控制器有時(shí)也需要用到weak,究其原因就是為了防止循環(huán)引用的發(fā)生侣灶。weak和strong不同的是:當(dāng)一個(gè)對象不再有strong類型的指針指向它的時(shí)候甸祭,它就會(huì)被釋放,即使還有weak型指針指向它褥影,那么這些weak型指針也將被清除池户。
strong:ARC之后的關(guān)鍵字,用于替代retain,強(qiáng)引用某對象校焦,即將對象的引用計(jì)數(shù)+1赊抖。
絕大多數(shù)情況下strong和retain的作用是相同的,日常開發(fā)中寨典,我們大部分對象屬性也都是用strong這個(gè)關(guān)鍵字氛雪,但在聲明Block時(shí),使用strong和retain會(huì)有截然不同的效果耸成。strong會(huì)等于copy报亩,而retain等于assign。日常開發(fā)中Block聲明時(shí)使用copy墓猎,為什么呢捆昏,這算是個(gè)歷史習(xí)慣問題吧赚楚,因?yàn)榉茿RC下不copy的Block會(huì)在棧中毙沾,ARC中的Block都會(huì)在堆上的。關(guān)于block的“姿勢”宠页,以后如果寫文章的話左胞,再議~~~~
copy(重點(diǎn),雖然用的地方就那幾個(gè)举户,但是值得關(guān)注):賦值時(shí)釋放舊值烤宙,然后對傳入值進(jìn)行拷貝,對象引用計(jì)數(shù)為1俭嘁。所以使用copy關(guān)鍵字的時(shí)候躺枕,你將一個(gè)對象復(fù)制給該屬性,該屬性并不會(huì)持有那個(gè)對象供填。而使用copy關(guān)鍵字的對象必須要實(shí)現(xiàn)NSCopying協(xié)議拐云。?
那么我們什么時(shí)候需要使用copy關(guān)鍵字呢,既然目的是持有一個(gè)對象近她,那直接用strong不就完了叉瘩?
修飾NSString、NSArray粘捎、NSDictionary等有對應(yīng)可變類型的對象薇缅,以及block類型對象時(shí)需要使用copy關(guān)鍵字!T苣ァ泳桦!這里就不貼圖或者上代碼了,百度可以出來一大片娩缰,但大同小異的都只是表明了現(xiàn)象灸撰,并沒有闡述理由,這里小小的吐槽一下,那樣的博文有什么意義梧奢,筆者也是看過許多的坑啊~~~~
簡而言之狱掂,因?yàn)樗麄冇锌赡芎蛯?yīng)的可變類型(例如NSMutableString)之間進(jìn)行賦值操作,為確保對象中的字符串不被修改 亲轨,應(yīng)該在設(shè)置屬性時(shí)拷貝一份趋惨。而若用strong修飾,如果對象在外部被修改了惦蚊,會(huì)影響到屬性器虾。
那么寫到這里就不得不提起copy的淺拷貝以及深拷貝,這里只說copy蹦锋,關(guān)于copy和mutablecopy的區(qū)別兆沙,不在本文主題內(nèi)……
先表明一下深淺拷貝的區(qū)別,最簡明的就是莉掂,淺拷貝是指針拷貝葛圃;深拷貝是內(nèi)容拷貝
需要記住的是copy總是返回一個(gè)不可變的對象,對于不可變類型對象進(jìn)行copy憎妙,是淺拷貝库正,對可變類型對象進(jìn)行copy,是深拷貝厘唾。
總結(jié):
以上就是日常開發(fā)中大家會(huì)使用到的關(guān)鍵字褥符,第一次寫文章,可能有的地方闡述的不準(zhǔn)確抚垃,再次歡迎大家指正E玳埂!鹤树!