內(nèi)存分區(qū)情況
棧區(qū) - 由編譯器分配和釋放,存放函數(shù)參數(shù)和局部變量平斩,該區(qū)域是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)亚享,是一段連續(xù)的內(nèi)存區(qū)域
堆區(qū) - 由開(kāi)發(fā)者負(fù)責(zé)分配和釋放,該區(qū)域是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)绘面,是一段不連續(xù)的內(nèi)存區(qū)域
全局區(qū) - 存放全局變量和靜態(tài)變量的區(qū)域欺税,初始化的全局變量和靜態(tài)變量放在一個(gè)區(qū)域,未初始化的全局變量和靜態(tài)變量放在相鄰的區(qū)域揭璃,程序結(jié)束后由系統(tǒng)釋放
常量區(qū) - 存放常量字符串晚凿,程序結(jié)束后由系統(tǒng)釋放
代碼區(qū) - 存放代碼的二進(jìn)制數(shù)據(jù)的區(qū)域
weak
什么情況下會(huì)只用weak關(guān)鍵字,與assign有什么區(qū)別瘦馍?
在會(huì)出現(xiàn)循環(huán)引用的情況下會(huì)使用weak歼秽,比如delegate;在使用IBOutlet外鏈對(duì)象時(shí)也會(huì)使用weak情组。
weak表示一種非擁有關(guān)系燥筷,為這種屬性設(shè)置值時(shí),既不會(huì)保留新值院崇,也不會(huì)釋放舊值肆氓,這一點(diǎn)與assign類(lèi)似,但是在指向?qū)ο蟊讳N(xiāo)毀時(shí)亚脆,屬性值也會(huì)被置空做院,而assign只是簡(jiǎn)單的賦值操作;
weak只能修飾OC對(duì)象,而assign用于修飾非OC對(duì)象键耕。IBOutlet外鏈對(duì)象可不可以用strong寺滚?
可以,而且官方還強(qiáng)烈推薦使用strong屈雄,除了一些會(huì)出現(xiàn)循環(huán)引用的情況村视。
首先看下weak和strong同時(shí)修飾一個(gè)控件時(shí)的持有關(guān)系:
weak-VC會(huì)持有View,View會(huì)強(qiáng)引用控件酒奶,VC對(duì)控件是弱引用
strong-VC會(huì)持有View蚁孔,View會(huì)強(qiáng)引用控件,VC對(duì)控件是強(qiáng)引用
至于早期為什么蘋(píng)果推薦使用weak去修飾惋嚎,這是因?yàn)樵缙趇Phone內(nèi)存比較小杠氢,當(dāng)內(nèi)存過(guò)低時(shí)會(huì)釋放View,而此時(shí)如果使用strong另伍,則控件不會(huì)被釋放鼻百,所以需要我們手動(dòng)去釋放,而使用weak控件會(huì)因?yàn)関iew被釋放而釋放摆尝;但是現(xiàn)在隨著設(shè)備的性能越來(lái)越高温艇,再也不會(huì)出現(xiàn)需要釋放view的情況,這兩這個(gè)修飾符帶來(lái)的結(jié)果也就一樣了堕汞,所以蘋(píng)果現(xiàn)在推薦使用strong來(lái)修飾外鏈對(duì)象weak是如何實(shí)現(xiàn)的勺爱?
runtime對(duì)注冊(cè)的類(lèi),會(huì)維護(hù)一個(gè)weak表讯检,表中以weak指向?qū)ο蟮膬?nèi)存地址為key琐鲁,對(duì)象為valueweak需要在dealloc中置空嗎?
不需要视哑,當(dāng)此對(duì)象的引用計(jì)數(shù)為0時(shí)绣否,會(huì)自動(dòng)調(diào)用dealloc方法誊涯,接著會(huì)以weak對(duì)象指向的內(nèi)存地址為key在weak表中搜索挡毅,找到所有以這個(gè)內(nèi)存地址為key的對(duì)象并置空weak屬性set方法的大致實(shí)現(xiàn)
- (void)setObject:(id) object {
objc_setAssociatedObject(self, "object", object, OBJC_ASSOCIATION_ASSIGN);
[object cyl_runAtDealloc{ object = nil }];
}
copy
- 如何讓自己的類(lèi)用copy修飾符?
通過(guò)實(shí)現(xiàn)NSCopying協(xié)議暴构,這個(gè)協(xié)議只有一個(gè)方法copyWithZone跪呈,讓我們自己的類(lèi)具有拷貝功能;如果我們的類(lèi)還分為可變版本取逾,那么就需要再實(shí)現(xiàn)NSMutableCopying協(xié)議耗绿, - 如何重寫(xiě)copy關(guān)鍵字的setter方法?
- (void) setObject:(id)object {
_object = [object copy];
}
- 淺拷貝和深拷貝
淺拷貝砾隅,不拷貝對(duì)象本身误阻,僅僅是拷貝指針;
深拷貝,直接拷貝整個(gè)對(duì)象到另一塊內(nèi)存中究反。
copy 淺拷貝
NSString *str1 = @"123";
NSString *str2 = [str1 copy];
NSLog(@"str1 p:%p, str2 p:%p", str1, str2);
打印
str1 p:0x10ea830e8, str2 p:0x10ea830e8
通過(guò)打印信息寻定,可以看到str1和str2指向同一塊內(nèi)存,只針對(duì)內(nèi)存地址進(jìn)行了拷貝
那如果此時(shí)我將str1進(jìn)行重新賦值精耐,str2會(huì)發(fā)生變化嗎狼速?
NSString *str1 = @"123";
NSString *str2 = [str1 copy];
str1 = @"abc";
NSLog(@"str p:%p, str2 p:%p", str1, str2);
打印
str p:0x1045a5108, str2 p:0x1045a50e8
通過(guò)打印發(fā)現(xiàn)源對(duì)象指向的內(nèi)存地址發(fā)生了改變,這是為什么呢卦停?
copy擁有自己的特點(diǎn):修改源對(duì)象的屬性不會(huì)影響副本對(duì)象向胡,修改副本對(duì)象的屬性也不會(huì)影響源對(duì)象。
這個(gè)特點(diǎn)是為什么呢惊完,因?yàn)樽铋_(kāi)始str1僵芹、str2指向的同一個(gè)不可變字符串,這個(gè)時(shí)候系統(tǒng)為了優(yōu)化性能小槐,只生成了一個(gè)指針即可淮捆;但是當(dāng)str1值發(fā)生變化時(shí),這個(gè)不可變@"123"本股,是不可能變成@"abc"的攀痊,在互不影響的原則下,系統(tǒng)就重寫(xiě)開(kāi)辟了一塊內(nèi)存空間
copy 一個(gè)可變數(shù)組
NSMutableArray *ary1 = [@[@"a", @"b", @"c"] mutableCopy];
NSMutableArray *ary2 = [ary1 copy];
NSLog(@"\nary1 class:%@ p:%p\nary2 class:%@ p:%p", [ary1 class], ary1, [ary2 class], ary2);
打印
ary1 class:__NSArrayM p:0x60000153f390
ary2 class:__NSArrayI p:0x60000153f450
通過(guò)打印ary2賦值是ary1經(jīng)過(guò)copy的拄显,它的類(lèi)型是不可變數(shù)組苟径,而ary1是可變數(shù)組,ary2的copy是一次深拷貝躬审,指針和內(nèi)容都被拷貝了一份棘街,這個(gè)原因和上面的一樣,都是遵循互不影響原則承边,重新開(kāi)辟了一個(gè)內(nèi)存
copy總結(jié):
- copy修飾或者賦值的變量肯定是不可變的
- 用copy賦值的遭殉,要看源對(duì)象是否可變,來(lái)決定是淺拷貝還是深拷貝
- 使用mutableCopy賦值的博助,肯定是深拷貝
- 對(duì)象之間賦值之后险污,再改變,遵循互不影響的原則
property的本質(zhì)是什么富岳?ivar蛔糯、setter、getter是如何生成的
property的本質(zhì)就是實(shí)例變量ivar加上存取方法setter/getter窖式。
編譯器在編譯期會(huì)通過(guò)自動(dòng)合成蚁飒,生成訪問(wèn)這些屬性需要的方法,并生成一個(gè)帶_的實(shí)例變量萝喘,也可以通過(guò)synthesize去指定實(shí)例變量的名字
生活如此美好淮逻,今天就點(diǎn)到為止琼懊。。爬早。