一、說一下對自動釋放池的理解
ARC中,主線程默認開啟一個runloop秉馏,runloop自動創(chuàng)建一個autoreleasepool,autorelease對象會自動被加入autoreleasepool中脱羡,一次runloop后清空自動釋放池萝究,用__autoreleasing修飾符修飾,或類方法創(chuàng)建會自動加入autoreleasepool中锉罐,添加到最近的autoreleasepool中帆竹。autoreleasepool是被一個棧區(qū)管理,當需要釋放一個autoreleasepool時脓规,會根據其中的哨兵對象(一個nil指針)栽连,對這個對象所在的autoreleasepool中所有對象引用計數-1,清空所有對象的內存地址侨舆,然后next指針會指向一個合適的位置秒紧,next根據表示begin()和end()來約束autoreleasepool是否存滿對象舷暮,是否需要創(chuàng)建新的autoreleasepool存儲新的autorelease對象。
二噩茄、說一下都有那些修飾詞并闡述作用
nonatomic、atomic复颈、assign绩聘、weak、retain耗啦、strong凿菩、copy、readonly帜讲、readwrite
nonatomic衅谷、atomic區(qū)別:
atomic:設置成員變量的@property屬性時,默認是atomic似将,提供多線程安全获黔,但不是絕對安全。
nonatomic:禁止多線程在验,變量保護玷氏,提高安全性。
atomic是OC使用的一種線程保護技術腋舌,防止在一個線程上的任務未完成時盏触,被其他線程讀取,造成數據錯誤块饺,這種機制是耗費資源的赞辩。一般不需要多線程間通訊編程,可以使用nonatomic授艰。
Assign辨嗽、 weak的區(qū)別
引用計數都不會?1。
assign 修飾基本數據類型想诅,例如int float召庞,在MRC環(huán)境下不會自動置為nil。
weak 修飾的變量會在棧中自動清空来破,賦值為nil篮灼。
eg:delegate在MRC環(huán)境下,用assign修飾徘禁,是為了不造成循環(huán)引用诅诱,需要在-dealloc方法中手動設置self.delegate=nil;以免造成野指針。而在ARC環(huán)境下送朱,直接用weak修飾就可以了娘荡。
原理:一個對象干旁,所有指向它的weak指針都存放在一個hash表中,key是對象所占內存地址炮沐,value是一個weak指針數組争群,當對象被銷毀的時候,系統(tǒng)會遍歷這個數組中的所有weak指針大年,并將它們都會指向nil换薄。
retain、strong翔试、copy的區(qū)別
retain 是MRC下使用的修飾詞轻要,在ARC下可用strong替代。
當修飾不可變對象時垦缅,三者的作用是一樣的冲泥,對象不會跟著原本的引用對象的改變而改變,因為是淺拷貝的指針壁涎,當源數值發(fā)生改變凡恍,就會產生新的指針地址。
當修飾可變對象的時候怔球,retain和strong是一樣的咳焚,對象會跟著原本引用對象的數值改變而改變,因為原對象是可變的庞溜,不會出現(xiàn)新的內存革半。而copy的對象不會跟著改變,因為copy是深拷貝的新的內容流码,開辟了新的存儲空間和指針又官。
readonly、readwrite的區(qū)別
readonly 這個屬性只生成了getter方法漫试,沒有setter方法六敬,只能讀。
readwrite 這個屬性getter setter方法都有驾荣,可讀可改外构。
三、ARC和MRC的區(qū)別
ARC下播掷,內存交給系統(tǒng)自動管理审编,系統(tǒng)會在編譯的時候自動插入retain/release,而MRC下歧匈,需要手動管理對象的引用計數垒酬,需要手動發(fā)送release或者autorelease消息。
四、簡述category和extension的區(qū)別
category 運行時決定勘究,只能添加方法矮湘,不能添加實例變量(可以添加屬性)。
extension 編譯時決定口糕,不僅可以添加方法缅阳,還可以添加實例變量和屬性,默認是私有的景描。但是extension沒有獨立的實現(xiàn)部分券时。
category細聊:
1)分類的方法名如果和原類中方法名沖突,優(yōu)先分類伏伯。
2)Category的方法可以被子類繼承。
3)利用runtime倒序遍歷方法列表捌袜,可以調用被覆蓋的原類的方法说搅。
4)一個類的兩個category,如果存在方法名相同的情況虏等,根據buildPhases->Compile Sources里面的從上至下順序編譯情況去調用弄唧,即后編譯的會被直接調用。
5)擴展一個類的方式霍衫,category比繼承要好候引,繼承需要定義子類,類目不需要定義子類來增加現(xiàn)有類的方法敦跌,且不會影響其他類和原有類的關系澄干。
五、說一下對內存管理的理解
內存管理機制
1柠傍、引用計數:當我們創(chuàng)建一個對象時麸俘,其引用計數會?1,系統(tǒng)會分配內存給到這個對象惧笛。每次引用這個對象从媚,它的引用計數都會?1。當指針不再指向這個對象患整,那么它的引用計數會?1拜效,直到引用計數為0,它的內存會釋放掉各谚,對象被銷毀紧憾。在ARC環(huán)境下,對象會被系統(tǒng)釋放昌渤,不需要手動釋放稻励,避免了內存泄漏和野指針的出現(xiàn)。
2、循環(huán)引用:當幾個對象互相強引用時望抽,會造成內存泄漏加矛,導致程序崩潰。例如煤篙,delegate如果用strong修飾斟览,那么就會造成兩個類之間的互相強引用,此時引入弱引用概念辑奈,即用weak修飾delegate苛茂,不會使delegate的引用計數?1,當delegate對象銷毀時鸠窗,指針會指向nil妓羊。
3、內存泄漏:沒有及時釋放掉內存稍计,例如計時器沒有釋放躁绸。
實際開發(fā)中如何避免內存泄漏
1、防止循環(huán)引用臣嚣,使用weak弱引用净刮,例如修飾delegate。
2硅则、及時釋放對象內存淹父,例如創(chuàng)建計時器NSTimer,在計時結束的時候怎虫,一定要調用invalidate方法暑认,將timer置為nil。
3大审、使用懶加載的方式創(chuàng)建對象扮超,在使用對象的時候再進行實例化优俘,還可以同時加入一些處理邏輯失仁,這樣利于內存管理颗胡。
六、循環(huán)引用
舉例:
1酷愧、UIViewController中創(chuàng)建UITableView驾诈,當實例一個tableView時,控制器的view對tableView進行了強引用溶浴,此時tableView的delegate又引用了控制器乍迄,這就形成了循環(huán)引用,此時需要用weak去修飾delegate士败。
2闯两、block內部調用了外部變量(控制器本身或者控制器的屬性)
此時需要用__weak typeof(self) weakSelf = self;來進行對控制器的弱引用褥伴,然后在block內部去調用。
3漾狼、關于定時器
使用定時器時重慢,要主動調用invalidated,一旦和控制器形成循環(huán)引用逊躁,控制器不會被自動銷毀似踱,不會調用dealloc方法,如果invalidated放在dealloc中稽煤,是不會被執(zhí)行的核芽。那么我們可以通過攔截點擊返回按鈕的方法,在該方法中主動調用invalidated方法酵熙,或者寫在ViewWillDisappear方法中轧简。請記住,創(chuàng)建一個NSTimer對象匾二,會形成一個runloop哮独,不止控制器會對該timer持有,iOS系統(tǒng)也會對其強引用假勿,所以不要以為設置timer=nil就可以釋放timer了,只有調用invalidated才會讓iOS系統(tǒng)釋放對timer的強引用态鳖。所以转培,[timer invalidated];timer=nil;要同時書寫,這是一種良好的代碼習慣和規(guī)范浆竭。
七浸须、關于block
1、block是一個OC的對象邦泄,它封裝了一段代碼删窒,這段代碼可以在任何時候執(zhí)行。Block可以作為函數參數或者函數的返回值顺囊,而其本身又可以帶輸入參數或返回值肌索。可以嵌套定義特碳,可以定義在方法內部和外部诚亚。
2、block的循環(huán)引用:在使用block的地方午乓,self.block,self持有了block站宗,在block代碼塊里處理邏輯,如果用到了self.xx益愈,那么block又會持有self梢灭,這樣當你離開界面的時候,并不會走self的dealloc析構函數,self不會釋放敏释,這是因為self和block的循環(huán)引用库快,導致了內存泄漏。為了避免這種情況颂暇,要使用__weak 在block外面修飾一下self缺谴,在block代碼塊里使用weakself處理邏輯,weakself只是指向了self耳鸯,它在一個弱引用表里湿蛔,self的引用計數沒有+1。
3县爬、按照上面的方式調用self的屬性阳啥,有可能會失敗,原因是财喳,weakself會因為析構函數被釋放察迟,那么weakself.xx就會是nil。為了避免這種情況耳高,在block代碼塊里扎瓶,需要用__strong修飾一下weakself,那么相當于一個臨時的strong指針指向了self泌枪,當邏輯處理完畢概荷,strong銷毀,不會產生內存泄漏問題碌燕。
八误证、關于WKWebview
1、相較于UIWebview修壕,WKWebview占內存小愈捅,加載快,增加了加載進度條慈鸠。
2蓝谨、出現(xiàn)白屏的原因和解決辦法:
① 網頁內存過大會白屏,需要在webViewWebContentProcessDidTerminate方法中調用[webview reload];方法青团。
② url中有中文字符像棘,需要后臺配合修改;
③ h5中使用了第三方組件壶冒,加載失敗缕题,先是白屏。一般正式環(huán)境下會恢復正常胖腾。3烟零、關于cookie
為了解決加載H5界面無法攜帶原生界面登錄用戶信息問題瘪松,除了在url上拼接用戶uid等信息的方法,還可以在請求的時候锨阿,攔截請求頭宵睦,將這些信息拼接起來,使用request的set value方法墅诡,將這些信息傳遞過去壳嚎。4、原生界面和H5界面的交互:
JS調用OC方法:WKWebview中有一個WKScriptMessageHandler協(xié)議末早,想要實現(xiàn)交互烟馅,需要定義一個方法名,使用[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"methodname"]方法設置然磷,并通過userContentController:didReceiveScriptMessage方法郑趁,獲取對應名稱的數據體進行解析。
OC調用JS:通過evaluateJavaScript方法調用JS方法姿搜,需要在HTML文件中定義方法名寡润,在原生這里調用。5舅柜、獲取網頁高度
① 在webviewdidFinishNavigation中獲取高度梭纹。
② 執(zhí)行evaluateJavaScript方法獲取網頁寬高,計算比例致份,再根據手機界面設置的寬高去設置变抽。
③ 在HTML標簽中加入特殊字符去接收高度,OC這邊通過evaluateJavaScript方法獲取知举。
九瞬沦、關于多線程
1太伊、關于多線程都有哪些了解雇锡?
NSThread NSOperation GCD 當我們需要大量耗時操作時候,可以在多線程中去執(zhí)行任務僚焦,避免主線程阻塞锰提。2、NSThread使用:
兩種方法:
① 創(chuàng)建實例對象:
NSThread*thread = [[NSThread alloc] initWithTarget:self selector:@selector(upload)? object:@"參數"];
[thread start];
② 類方法創(chuàng)建:
[NSThread detachNewThreadSelector:@selector(upload) toTarget:@"" withObject:@""];
③ NSThread可以設置優(yōu)先級? 取值范圍 0.0 ~ 1.0 之間 最高是1.0 默認優(yōu)先級是0.5
舉例:thread.threadPriority = 1.0;
④ 強制結束任務調用exit方法芳悲。3立肘、CGD使用
CGD會把任務從隊列中取出,自動放到對應的子線程中執(zhí)行名扛,不需要程序員去管理線程谅年,遵循FIFO原則,先進先出肮韧,后進后出融蹂。
如何使用:
① 創(chuàng)建隊列
//創(chuàng)建一個并行隊列? ?
dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);? ?
//創(chuàng)建一個串行隊列? ?
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_SERIAL);
//獲取全局并發(fā)隊列? ?
dispatch_queue_t queue3 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);? ?
//獲取主隊列(一個串行隊列旺订,放在主隊列的任務都會在主線程執(zhí)行)? ?
dispatch_queue_t queue4 = dispatch_get_main_queue();
② 執(zhí)行任務
dispatch_async(queue, ^{? ? ? 異步操作? ? ? });
dispatch_sync(queue, ^{? ? ? ? 同步操作? ? ? });
總結:
同一串行隊列中,同步+同步 死鎖超燃。同步+異步 正常区拳。異步+同步 死鎖。異步+異步 正常意乓。
同一并行隊列中樱调,都正常。
例如届良,需要請求1結束后再執(zhí)行請求2笆凌,需要用到dispatch_group_t。
① enter leave方法
② 信號量方法
4伙窃、NSOperation的使用
基于GCD的封裝菩颖,更加面向對象。如果是簡單的兩個網絡請求为障,請求A優(yōu)先級大于請求B晦闰,就可以用NSOperation。使用addDependency方法鳍怨,來設置先后順序呻右。如果同時下載多個圖片,可以使用NSOperation鞋喇,設置maxConcurrentOperationCount最大并發(fā)數声滥,然后使用NSBlockOperation創(chuàng)建對象去執(zhí)行任務。5侦香、其他應用:
① 調用NSObject方法落塑,[self perform.....]
② 延時處理 dispatch_after
③ 使用定時器
④ 創(chuàng)建單例,代碼只會執(zhí)行一次 dispatch_once_t onceToken;
⑤ 柵欄函數罐韩,前面的任務執(zhí)行完畢后才會執(zhí)行后面的任務憾赁。
dispatch_barrier_async(<#dispatch_queue_t? _Nonnull queue#>, <#^(void)block#>)
十、手勢傳遞
1散吵、當子view大小超出了父view龙考,怎么獲取并響應點擊事件?
重新父view的hintTest方法矾睦,遍歷父view上所有的子view晦款,判斷這個point是否在子view上,如果在枚冗,返回子view去響應事件缓溅,如果都沒有,返回父view去響應事件赁温。
2坛怪、擴大UIButton的點擊范圍
① 創(chuàng)建分類(Category)并重寫UIButton的pointInside:withEvent:方法
②創(chuàng)建分類(Category)并重寫UIButton的hitTest::withEvent:方法
十一州藕、離屏渲染
設置了layer會有離屏渲染
①、②酝陈、③床玻、④、⑤沉帮、⑥锈死、⑦、⑧穆壕、⑨待牵、⑩ ?、?喇勋、?缨该、?、?川背、?贰拿、?、?熄云、?膨更、?