ios面試總結(jié)

UIView與CALayer的區(qū)別吃溅?

UIView繼承于UIResponder->NSObject
CALayer繼承于NSObject

UIView能夠響應事件,CALayer不可以
UIView主要是對顯示內(nèi)容的管理而 CALayer 主要側(cè)重顯示內(nèi)容的繪制鸯檬。
在做 iOS 動畫的時候决侈,修改非 RootLayer的屬性(譬如位置、背景色等)會默認產(chǎn)生隱式動畫,而修改UIView則不會赖歌。
UIView與CALayer的區(qū)別

UIbutton繼承鏈枉圃,UIControl UIResponder區(qū)別

UIButton繼承鏈:UIButton-UIControl-UIView-UIResponder-NSObject
UIControl發(fā)起action,UIResponder處理action庐冯。UIResponder可以通過重寫touchesBegan:withEvent:等方法接收到UIEvent和UITouch的詳細信息孽亲,然后處理。

為什么要在主線程刷新UI?

UIKit并不是一個 線程安全 的類展父,UI操作涉及到渲染訪問各種View對象的屬性返劲,如果異步操作下會存在讀寫問題,而為其加鎖則會耗費大量資源并拖慢運行速度栖茉。另一方面因為整個程序的起點UIApplication是在主線程進行初始化篮绿,所有的用戶事件都是在主線程上進行傳遞(如點擊、拖動)吕漂,所以view只能在主線程上才能對事件進行響應亲配。而在渲染方面由于圖像的渲染需要以60幀的刷新率在屏幕上 同時 更新,在非主線程異步化的情況下無法確定這個處理過程能夠?qū)崿F(xiàn)同步更新惶凝。

UIImage *image = [UIImage imageNamed:/imageWithContentOfFile:]; // 這兩個的區(qū)別

  1. imageNamed:

返回的對象會保存在緩存中吼虎,只有退出程序才會釋放內(nèi)存,但下一次調(diào)用很快梨睁,直接從緩存中讀取即可鲸睛。

2.imageWithContentOfFile:

返回的對象不會保存在緩存中,一旦對象銷毀就會釋放內(nèi)存

所以只有在一些整個程序生命周期里經(jīng)常用到的圖像采用imageNamed來處理坡贺,其他的(尤其是圖像文件非常大的)文件都應該用imageWithContentOfFile來處理官辈。

try、try?與try!

try:手動捕捉異常
try?:系統(tǒng)幫我們處理遍坟,出現(xiàn)異常返回nil拳亿;沒有異常返回對應的對象
try!:直接告訴系統(tǒng),該方法沒有異常愿伴。如果出現(xiàn)異常程序會crash

如果頁面 A 跳轉(zhuǎn)到 頁面 B肺魁,A 的 viewDidDisappear 方法和 B 的 viewDidAppear 方法哪個先調(diào)用?

答:順序 A-B-A-B
1隔节、調(diào)用A的viewwilldisappear
2鹅经、調(diào)用B的viewwillappear
3鹿榜、調(diào)用A的viewDidDisappear
4欢峰、調(diào)用B的viewDidAppear

2尝胆、A present C
答:順序A-C-C-A
1鲤孵、調(diào)用A的viewWillDisappear
2、調(diào)用C的viewWillAppear
3仔引、調(diào)用C的viewDidAppear
4咱筛、調(diào)用A的viewDidDisappear

drawRect 與 layoutSubviews的調(diào)用時機

首先兩個方法都是異步執(zhí)行胚嘲。layoutSubviews方便數(shù)據(jù)計算,drawRect方便視圖重繪强胰。

layoutSubviews在以下情況下會被調(diào)用:

1舱沧、init初始化不會觸發(fā)layoutSubviews。
2偶洋、addSubview會觸發(fā)layoutSubviews熟吏。
3、設置view的Frame會觸發(fā)layoutSubviews涡真,當然前提是frame的值設置前后發(fā)生了變化分俯。
4肾筐、滾動一個UIScrollView會觸發(fā)layoutSubviews哆料。
5、旋轉(zhuǎn)Screen會觸發(fā)父UIView上的layoutSubviews事件吗铐。
6东亦、改變一個UIView大小的時候也會觸發(fā)父UIView上的layoutSubviews事件。
7唬渗、直接調(diào)用setLayoutSubviews典阵。

drawRect在以下情況下會被調(diào)用:

1、如果在UIView初始化時沒有設置rect大小镊逝,將直接導致drawRect不被自動調(diào)用壮啊。 drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 兩方法之后掉用的.所以不用擔心在 控制器中,這些View的drawRect就開始畫了.這樣可以在控制器中設置一些值給View(如果這些View draw的時候需要用到某些變量 值).
2、該方法在調(diào)用sizeT o Fit后被調(diào)用撑蒜,所以可以先調(diào)用sizeToFit計算出size歹啼。然后系統(tǒng)自動調(diào)用drawRect:方法。
3座菠、通過設置contentMode屬性值為UIViewContentModeRedraw狸眼。那么將在每次設置或更改frame的時候自動調(diào)用drawRect:。
4浴滴、直接調(diào)用setNeedsDisplay拓萌,或者setNeedsDisplayInRect:觸發(fā)drawRect:,但是有個前提條件是rect不能為0升略。
以上1,2推薦微王;而3,4不提倡

什么是離屏渲染,以及為什么會產(chǎn)生離屏渲染品嚣?

正常渲染流程
APP中的數(shù)據(jù)經(jīng)過CPU計算和GPU渲染后炕倘,將結(jié)果存放在幀緩沖區(qū),利用視頻控制器從幀緩沖區(qū)中取出腰根,并顯示到屏幕上激才。
在GPU的渲染流程中,顯示到屏幕上的圖像是遵循大畫家算法按照由遠及近的順序,依次將結(jié)果存儲到幀緩沖區(qū)
視屏控制器從幀緩沖區(qū)中讀取一幀數(shù)據(jù)瘸恼,將其顯示到屏幕上后劣挫,會立即丟棄這幀數(shù)據(jù),不會做任何保留东帅,這樣做的目的是可以節(jié)省空間压固,且在屏幕上是各自顯示各自的,互相不影響靠闭。

離屏渲染流程

當App需要進行額外的渲染和合并時帐我,例如按鈕設置圓角,我們是需要對UIButton這個控件中的所有圖層都進行圓角+裁剪愧膀,然后再將合并后的結(jié)果存入幀緩存區(qū)拦键,再從幀緩存中取出交由屏幕顯示,這時檩淋,在正常的渲染流程中芬为,我們是無法做到對所有圖層進行圓角裁剪的,因為它是用一個丟一個蟀悦。所以我們需要提前將處理好的結(jié)果放入離屏緩沖區(qū)媚朦,最后將幾個圖層進行疊加合并,存放到站緩沖區(qū)日戈,最后屏幕上就是我們想實現(xiàn)的效果询张。

離屏緩存區(qū)就是一個臨時的緩沖區(qū),用來存放在后續(xù)操作使用浙炼,但目前并不使用的數(shù)據(jù)份氧。

離屏渲染再給我們帶來方便的同時,也帶來了嚴重的性能問題鼓拧。由于離屏渲染中的離屏緩沖區(qū)半火,是額外開辟的一個存儲空間,當它將數(shù)據(jù)轉(zhuǎn)存到Frame Buffer時季俩,也是需要耗費時間的钮糖,所以在轉(zhuǎn)存的過程中,仍有掉幀的可能酌住。

離屏緩沖區(qū)的空間并不是無限大的店归, 它是又上限的,最大只能是屏幕的2.5倍

為什么我們明知有性能問題時酪我,還是要使用離屏渲染呢消痛?

可以處理一些特殊的效果,這種效果并不能一次就完成都哭,需要使用離屏緩沖區(qū)來保存中間狀態(tài)秩伞,不得不使用離屏渲染逞带,這種情況下的離屏渲染是系統(tǒng)自動觸發(fā)的,例如經(jīng)常使用的圓角纱新、陰影展氓、高斯模糊、光柵化等

可以提升渲染的效率脸爱,如果一個效果是多次實現(xiàn)的遇汞,可以提前渲染,保存到離屏緩沖區(qū)簿废,以達到復用的目的空入。這種情況是需要開發(fā)者手動觸發(fā)的。

圓角中離屏渲染的觸發(fā)時機族檬?

首先說明下CALayer的構(gòu)成歪赢,如圖所示,它是由backgroundColor导梆、contents轨淌、borderWidth&borderColor構(gòu)成的。跟我們即將解釋的圓角觸發(fā)離屏渲染息息相關看尼。
官方文檔告訴我們,設置cornerRadius只會對CALayer中的backgroundColor 和 boder設置圓角盟步,不會設置contents的圓角藏斩,如果contents需要設置圓角,需要同時將maskToBounds / clipsToBounds設置為true却盘。

所以我們可以理解為圓角不生效的根本原因是沒有對contents設置圓角狰域,而按鈕設置的image是放在contents里面的,所以看到的界面上的就是image沒有進行圓角裁剪黄橘。

在離屏渲染觸發(fā)的場景中兆览,按照性能影響從高到低排序,如下所示

shadows(陰影)
conerRadius > 0 + maskToBounds = true(常見的圓角設置手段)
mask(遮罩)
allowsGroupOpacity(組不透明)
edge antialiasing(抗鋸齒)

針對不同場景說明為什么以及怎么解決離屏渲染問題

添加了陰影的layer(layer.shadow)

layer本身是一塊矩形區(qū)域塞关,而陰影是作用于在整個非透明區(qū)域抬探,并顯示在所有l(wèi)ayer的最下方。
根據(jù)畫家算法帆赢,由遠及近的渲染小压,陰影是第一個被渲染的,但是陰影渲染有一個前提:我們必須畫完所有的layer和子layer后椰于。
所以這時我們就需要一個臨時緩存怠益,這個緩存區(qū)就是離屏緩沖區(qū),用來將所有l(wèi)ayer都渲染完成瘾婿,再根據(jù)所有l(wèi)ayer和子layer組合后的圖層的形狀蜻牢,添加陰影到FrameBuffer烤咧,最后顯示到屏幕上

優(yōu)化方案
使用陰影必須保證 layer 的masksToBounds = false,因此陰影與系統(tǒng)圓角不兼容抢呆。但是注意髓削,只是在視覺上看不到,對性能的影響依然镀娶。通常使用指定路徑來避免離屏渲染

方案1:指定路徑
在上述代碼的基礎上增加以下兩行代碼

let path = UIBezierPath(rect:btn.bounds)
btn.layer.shadowPath = path.cgPath

需要進行裁剪的layer(layer.masksToBounds / view.clipsToBounds)

這種場景就是我們常用的圓角處理立膛,當我們需要繪制一個帶有圓角并且需要剪切圓角以外內(nèi)容的容器時,就會觸發(fā)離屏渲染梯码,例如UIButton宝泵、UIImageView等

注意:iOS官方針對UIImageView有一些優(yōu)化,
==> 在iOS9之前轩娶,UIImageView和UIButton通過cornerRadius+masksToBounds設置圓角都會觸發(fā)離屏渲染儿奶,
==> 但是UIImageView在ios9以后,針對UIImageView中的image設置圓角并不會觸發(fā)離屏渲染鳄抒,如果加上了背景色或者陰影等其他效果還是會觸發(fā)離屏渲染的

優(yōu)化方案
對于content無內(nèi)容或者內(nèi)容非背景透明(不涉及到圓角以外的區(qū)域)的layer闯捎,直接設置layer的backgroundColor + cornerRadius 屬性繪制圓角

后臺繪制,前臺設置圖片

- (void)setCircleImage {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        UIImage *circleImage = [image imageWithCircle];
        dispatch_async(dispatch_get_main_queue(), ^{
            imageView.image = circleImage;
        });
    });
}

#import "UIImage+Addtions.h"
@implementation UIImage (Addtions)
//返回一張圓形圖片
- (instancetype)imageWithCircle {
    UIGraphicsBeginImageContextWithOptions(self.size, NO, 0);
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0,0,self.width,self.height)];
    [path addClip];
    [self drawAtPoint:CGPointZero];
    UIImage *image = UIGraphcisGetImageFromCurrentImageContext();
    UIGraphcisEndImageContext();

    return image;
}
  1. 使用混合圖層许溅,在layer上方疊加相應mask形狀的半透明layer
sublayer.contents = (id)[UIImage imageNamed:@"xxxx"].CGImage;
[view.layer addSublayer:sublayer];

繪制了文字的 layer (UILabel, CATextLayer, Core Text 等)
優(yōu)化方案
直接通過label的layer設置背景色 + cornerRadius

label.layer.backgroundColor = aColor
label.layer.cornerRadius = 5

總結(jié)

RoundedCorner(圓角) 在僅指定cornerRadius時不會觸發(fā)離屏渲染瓤鼻,僅適用于特殊情況:contents為 nil 或者contents不會遮擋背景色時的圓角。
Shawdow 可以通過指定路徑來取消離屏渲染贤重。
Mask 無法取消離屏渲染茬祷,可以利用混合圖層來進行優(yōu)化。

原文鏈接:https://blog.csdn.net/lin1109221208/article/details/107341640
原文鏈接:https://blog.csdn.net/lin1109221208/article/details/107185268

有關HTTP問題

HTTP:超文本傳輸協(xié)議并蝗,用戶客戶端與服務端的傳輸規(guī)則祭犯,可傳輸任意類型的數(shù)據(jù)
HTTP請求包含的要素:請求行,請求頭滚停,請求體沃粗,響應行,響應頭键畴,實體內(nèi)容

請求行:POST /lyric/3g_lyric HTTP/1.1
請求行包含:請求方法最盅,請求統(tǒng)一資源標識符URI,HTTP版本
請求方法:GET,POST,HEAD,PUT等
HTTP與服務器交互基本的方法有4種镰吵,GET,POST,PUT,DELETE
GET: 請求獲取Request-URI所標識的資源
POST: 在Request-URI所標識的資源后附加新的數(shù)據(jù)
HEAD: 請求獲取由Request-URI所標識的資源的響應消息報頭
PUT: 請求服務器存儲一個資源檩禾,并用Request-URI作為其標識
DELETE: 請求服務器刪除Request-URI所標識的資源
TRACE: 請求服務器回送收到的請求信息,主要用于測試或診斷
CONNECT: 保留將來使用
OPTIONS: 請求查詢服務器的性能疤祭,或者查詢與資源相關的選項和需求

請求頭:存放客戶端給服務的的附加信息
Host:目標服務器的網(wǎng)絡地址
Accept:讓服務端知道客戶端所能接受的數(shù)據(jù)類型 text/html
Content-Type:body中的數(shù)據(jù)類型盼产,如application/json,charset=UTF-8
Accept-Encoding:客戶端支持的數(shù)據(jù)壓縮格式勺馆,如gzip
User-Agent:客戶端的軟件環(huán)境
Connection:keep-alive戏售,HTTP1.1才開始有的侨核,告訴服務端這是一個持久連接
Content-Length: body的長度,如果body為空則該字段值為0灌灾。一般POST請求中才會有
Cookie:記錄著用戶信息的保存在本地的數(shù)據(jù)

//添加請求頭

[NSMutableURLRequest addValue: forHTTPHeaderField”];

//獲取當前請求設置的field

[NSURLRequest allHTTPHeaderFields];

響應狀態(tài)行:服務端返回給客戶端的狀態(tài)信息搓译,包含HTTP版本號,狀態(tài)碼锋喜,狀態(tài)碼對應的英文名稱

錯誤碼分為以下幾類:
1XX:信息提示些己。不代表成功或者失敗,表示臨時響應嘿般,100表示繼續(xù)段标,101 表示切換協(xié)議
2XX:成功
3XX:重定向 304(NOT MODIFIED):該資源在上次請求之后無修改
4XX:客戶端錯誤,404文件為找到炉奴,說明URI有問題逼庞,414URI太長, 403:無權(quán)限
5XX:服務器錯誤瞻赶,504網(wǎng)關超時
http服務器常用狀態(tài)碼及其含義

HTTPS與HTTP的區(qū)別

一赛糟、https協(xié)議需要到ca申請證書,一般免費證書很少砸逊,需要交費璧南。
二、http是超文本傳輸協(xié)議痹兜,信息是明文傳輸穆咐,https 則是具有安全性的ssl加密傳輸協(xié)議。
三字旭、http和https使用的是完全不同的連接方式,用的端口也不一樣崖叫,前者是80遗淳,后者是443。
四心傀、http的連接很簡單屈暗,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進行加密傳輸脂男、身份認證的網(wǎng)絡協(xié)議养叛,比http協(xié)議安全。

HTTP請求全過程

注:不知道抄的誰的了

Swift中Class和Struct區(qū)別宰翅?

類是引用類型弃甥,結(jié)構(gòu)體是值類型。值類型在傳遞和賦值時將進行復制汁讼,而引用類型則只會使用引用對象的一個"指向"淆攻。所以他們兩者之間的區(qū)別就是兩個類型的區(qū)別阔墩。

classTemperature { 
    varvalue: Float = 37.0
}

classPerson {
    vartemp: Temperature? 
    func sick() {
         temp?.value = 41.0
    } 
}

let A = Person()
let B = Person()
let temp = Temperature() 
A.temp = temp 
B.temp = temp

由于 Temperature 是 class ,為引用類型瓶珊,故 A 的 temp 和 B 的 temp指向同一個對象啸箫。A 的 temp修改了,B 的 temp 也隨之修改伞芹。這樣 A 和 B 的 temp 的值都被改成了41.0忘苛。如果將 Temperature 改為 struct,為值類型唱较,則 A 的 temp 修改不影響 B 的 temp扎唾。

內(nèi)存中,引用類型諸如類是在堆(heap)上绊汹,而值類型諸如結(jié)構(gòu)體實在棧(stack)上進行存儲和操作稽屏。相比于棧上的操作,堆上的操作更加復雜耗時西乖,所以蘋果官方推薦使用結(jié)構(gòu)體狐榔,這樣可以提高 App 運行的效率。

class有這幾個功能struct沒有的:

class可以繼承获雕,這樣子類可以使用父類的特性和方法
類型轉(zhuǎn)換可以在runtime的時候檢查和解釋一個實例的類型
可以用deinit來釋放資源
一個類可以被多次引用

struct也有這樣幾個優(yōu)勢:

結(jié)構(gòu)較小薄腻,適用于復制操作,相比于一個class的實例被多次引用更加安全届案。
無須擔心內(nèi)存memory leak或者多線程沖突問題

在封裝SDK中:

1庵楷、swift調(diào)用oc

iOS 制作framework時,swift調(diào)用OC楣颠,不支持橋接尽纽,故得換一種方式調(diào)用。

步驟:

點擊target ->Build Settings -> Allow Non-modular Includes In Framework Modules 設置為YES

然后在 Build Phases 中 Headers 的把你想要調(diào)用的oc文件暴露到Public中去

然后在對外的統(tǒng)一接口文件中暴露這個頭文件

2童漩、oc調(diào)用swift

同樣的方式弄贿,在SDK中會提示找不到Product Module Name -Swift.h 這個頭文件

步驟:

這里需要將Product Module Name -Swift.h這個頭文件的引用改為引用#import 這個頭文件

【JWEmotionTrackeriOSSDK就是你封裝的SDK名稱】

總結(jié):oc通過xxx-swift.h調(diào)用swift【系統(tǒng)自動生成】。swift通過xxx-Bridging-Header.h調(diào)用oc【系統(tǒng)提示生成或手動創(chuàng)建】創(chuàng)建oc項目矫膨,xcode不會自動創(chuàng)建橋接文件差凹。需要先創(chuàng)建xxx-Bridging-Header.h,才會生成xxx-swift.h文件侧馅。這句話很重要危尿,如果不創(chuàng)建橋接文件,那么會提示 添加好 頭文件之后 調(diào)用的時候馁痴,Bad receiver type XXX谊娇,這時候,需要手動創(chuàng)建橋接文件弥搞。

觸摸事件是如何從屏幕轉(zhuǎn)移到APP內(nèi)的邮绿?

1.手指觸摸屏幕渠旁,屏幕感到觸摸產(chǎn)生事件交給IOKit
2.IOKit會把事件包裝成IOHIdEvent,經(jīng)由mach_port交給SpringBoad
mach_port 進程端口船逮,各進程通信都是靠它
SpringBoad 是系統(tǒng)進程顾腊,也可以說是系統(tǒng)界面進程,處理和接受觸摸事件

3.SpingBoad進程接收到觸摸事件挖胃,觸發(fā)了主線程runloop的Source1事件回調(diào)
/*
SpingBoad進程接受到觸摸事件的時候杂靶,會分析觸摸事件發(fā)生的時候 用戶是在屏幕上界面翻頁還是在某app內(nèi),如果是前者會喚起SpingBoad本身主線程的runloop的Source0事件回調(diào)酱鸭,將事件交由桌面系統(tǒng)去消耗吗垮,如果是后者,觸摸事件通過IPC傳遞給前臺APP進程凹髓,接下來的事情便是APP內(nèi)部對于觸摸事件的響應了
*/

簡單點說 Source1就是系統(tǒng)干的事 Source0就是我們干的事
正經(jīng)說 Source1基本就是系統(tǒng)事件烁登,Source0基本就是應用層事件

Source1 :基于mach_Port的,來自系統(tǒng)內(nèi)核或者其他進程的事件,可以主動喚醒休眠中的RunLoop(開發(fā)過程中我們一般不主動使用IPC《進程間通信》)蔚舀。mach_port大家就理解成進程間相互發(fā)送消息的一種機制就好饵沧。
Source0 :非基于Port的 處理事件,什么叫非基于Port的呢赌躺?就是說你這個消息不是其他進程或者內(nèi)核直接發(fā)送給你的狼牺。

鏈接:http://www.reibang.com/p/d547e5393373

響應鏈和事件傳遞

事件的分發(fā)和傳遞。

1.當iOS程序中發(fā)生觸摸事件后礼患,系統(tǒng)會將事件加入到UIApplication管理的一個任務隊列中
2.UIApplication將處于任務隊列最前端的事件向下分發(fā)是钥。即UIWindow。
3.UIWindow將事件向下分發(fā)缅叠,即UIView悄泥。
4.UIView首先看自己是否能處理事件,觸摸點是否在自己身上肤粱。如果能码泞,那么繼續(xù)尋找子視圖。
5.遍歷子控件狼犯,重復以上兩步。
6.如果沒有找到领铐,那么自己就是事件處理者悯森。
7.如果自己不能處理,那么不做任何處理绪撵。
其中 UIView不接受事件處理的情況主要有以下三種
1)alpha <0.01
2)userInteractionEnabled = NO
3.hidden = YES.

怎么尋找最合適的view

// 此方法返回的View是本次點擊事件需要的最佳View

  • (UIView)hitTest:(CGPoint)point withEvent:(UIEvent)event

// 判斷一個點是否落在范圍內(nèi)

  • (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event

// 因為所有的視圖類都是繼承BaseView

  • (UIView)hitTest:(CGPoint)point withEvent:(UIEvent)event {
    // 1.判斷當前控件能否接收事件
    if(self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
    // 2. 判斷點在不在當前控件
    if([self pointInside:point withEvent:event] == NO) return nil;
    // 3.從后往前遍歷自己的子控件
    NSInteger count = self.subviews.count;
    for(NSInteger i = count - 1; i >= 0; i--) {
    UIViewchildView = self.subviews[I];
    // 把當前控件上的坐標系轉(zhuǎn)換成子控件上的坐標系
    CGPointchildP = [self convertPoint:point toView:childView];
    UIView
    fitView = [childView hitTest:childP withEvent:event];
    if(fitView) {
    // 尋找到最合適的view
    return fitView;
    }
    }
    // 循環(huán)結(jié)束,表示沒有比自己更合適的view
    return self;
    }

響應者鏈

響應鏈是從最合適的view開始傳遞瓢姻,處理事件傳遞給下一個響應者,響應者鏈的傳遞方法是事件傳遞的反方法音诈,如果所有響應者都不處理事件幻碱,則事件被丟棄绎狭。我們通常用響應者鏈來獲取上幾級響應者,方法是UIResponder的nextResponder方法褥傍。

__weak儡嘶,__block區(qū)別,及實現(xiàn)原理恍风,為何__block修飾的值可以改變蹦狂,__weak修飾的值不能改變?

__weak用于修飾變量,后者用戶修飾屬性朋贬,__weak主要用于防止block中的循環(huán)引用凯楔。
__block也用于修飾變量。它是引用修飾锦募,其修飾的值是動態(tài)變化的摆屯,可以被重新賦值。
__block用于修飾block內(nèi)部將要修改的外部變量糠亩。

使用__weak和__unsafe_unretained修飾符合一解決循環(huán)引用的問題虐骑,__weak會使block內(nèi)部將指針變?yōu)槿踔羔槨?/p>

__weak 和 __unsafe_unretained的區(qū)別。

__weak不會產(chǎn)生強引用削解,指向的對象銷毀時富弦,會自動將指針置為nil
__unsafe_unretained不會產(chǎn)生強引用,不安全氛驮,指向的對象銷毀時腕柜,指針存儲的地址值不變

__strong 和 __weak

在block內(nèi)部重新使用__strong修飾self變量是為了在block內(nèi)部有一個強指針指向weakSelf避免在block調(diào)用的時候weakSelf已經(jīng)被銷毀。

__block修飾的變量為什么能在block里面能改變其值矫废?

__block用于解決block內(nèi)部不能修改auto變量值的問題盏缤,__block不能修飾靜態(tài)變量和全局變量
_block 所起到的作用就是只要觀察到該變量被 block 所持有,就將“外部變量”在棧中的內(nèi)存地址放到了堆中蓖扑。進而在block內(nèi)部也可以修改外部變量的值唉铜。

block本質(zhì)

runtime如何實現(xiàn)weak變量的自動置nil?

runtime對注冊的類, 會進行布局,對于weak對象會放入一個hash表中律杠。 用weak指向的對象內(nèi)存地址作為key潭流,當此對象的引用計數(shù)為0的時候會dealloc.假如weak指向的對象內(nèi)存地址是A,那么就會以A為鍵柜去, 在這個weak表中搜索灰嫉,找到所有以A為鍵的weak對象,從而設置為nil.

#import跟 #include 有什么區(qū)別嗓奢,@class呢讼撒,#import<> 跟 #import””有什么區(qū)別?
1). #import是Objective-C導入頭文件的關鍵字,#include是C/C++導入頭文件的關鍵字根盒,使用#import頭文件會自動只導入一次钳幅,不會重復導入。
2). @class告訴編譯器某個類的聲明炎滞,當執(zhí)行時敢艰,才去查看類的實現(xiàn)文件,可以解決頭文件的相互包含厂榛。
3). #import<>用來包含系統(tǒng)的頭文件盖矫,#import””用來包含用戶頭文件。

load方法和initalize方法有什么區(qū)別和共同點

initialize方法是在第一次調(diào)用該類的方法的時候調(diào)用击奶,load方法是在程序啟動之前就調(diào)用辈双,父類先于子類執(zhí)行,類先于分類執(zhí)行柜砾。
總結(jié):

1.load和initialize都會在實例化對象之前調(diào)用湃望,以main函數(shù)為分水嶺,前者是在main函數(shù)之前痰驱,后者是在main函數(shù)之后证芭。

2.load和initialize方法都不會顯示的調(diào)用父類的方法而是自動調(diào)用,即使子類沒有initialize方法也會調(diào)用父類的方法担映,load方法不會調(diào)用父類废士。

3.load和initialize方法內(nèi)部使用了鎖,因此他們是線程安全的蝇完,實現(xiàn)時要盡可能簡單官硝,避免線程阻塞,不要再次使用鎖短蜕。

4.load方法常用來method swizzle氢架,initialize常常用于初始化全局變量和靜態(tài)變量.

調(diào)用方式
1、load是根據(jù)函數(shù)地址直接調(diào)用
2朋魔、initialize是通過objc_msgSend調(diào)用
調(diào)用時刻
1岖研、load是runtime加載類、分類的時候調(diào)用(只會調(diào)用一次)
2警检、initialize是類第一次接收到消息的時候調(diào)用, 每一個類只會initialize一次(如果子類沒有實現(xiàn)initialize方法, 會調(diào)用父類的initialize方法, 所以父類的initialize方法可能會調(diào)用多次)
load和initializee的調(diào)用順序
1孙援、load:父子分
先調(diào)用類的load, 在調(diào)用分類的load
先編譯的類, 優(yōu)先調(diào)用load, 調(diào)用子類的load之前, 會先調(diào)用父類的load
先編譯的分類, 優(yōu)先調(diào)用load

2、initialize 分子父
先初始化分類, 后初始化子類
通過消息機制調(diào)用, 當子類沒有initialize方法時, 會調(diào)用父類的initialize方法, 所以父類的initialize方法會調(diào)用多次

對A類創(chuàng)建了分類B和C,都有同一個方法eat,B和C的方法實現(xiàn)不同扇雕,在A里面調(diào)用eat,實現(xiàn)是誰的

答:和分類的編譯順序有關赃磨,最后一個被編輯的執(zhí)行eat方法


WechatIMG37.jpeg

多線程

多線程傳送門

不手動指定autoreleasepool的前提下,一個autorealese對象在什么時刻釋放洼裤?

分兩種情況:手動干預釋放時機、系統(tǒng)自動去釋放。

手動干預釋放時機 - 指定autoreleasepool就是所謂的:當前作用域大括號結(jié)束時釋放腮鞍。
系統(tǒng)自動去釋放 - 不手動指定autoreleasepool
Autorelease對象出了作用域之后值骇,會被添加到最近一次創(chuàng)建的自動釋放池中,并會在當前的 runloop 迭代結(jié)束時釋放移国。
如果在一個vc的viewDidLoad中創(chuàng)建一個 Autorelease對象吱瘩,那么該對象會在 viewDidAppear 方法執(zhí)行前就被銷毀了。
黑幕背后的autorelease

ios 用過哪些鎖迹缀?哪些鎖的性能比較高使碾?

iOS中的鎖

RunLoop和線程的關系?runloop的mode作用是什么?

一、RunLoop和線程的關系:

1.RunLoop 的作用就是來管理線程的祝懂,當線程的 RunLoop開啟后票摇,線程就會在執(zhí)行完任務后,處于休眠狀態(tài)砚蓬,隨時等待接受新的任務矢门,而不是退出。

2.只有主線程的RunLoop是默認開啟的灰蛙,所以程序在開啟后祟剔,會一直運行,不會退出摩梧。其他線程的RunLoop如果需要開啟枉疼,就手動開啟,

二至会、runloop內(nèi)部是如何實現(xiàn)的:

1羊始、有一個判斷循環(huán)的條件,滿足條件驾霜,就一直循環(huán)

2案训、線程得到喚醒事件被喚醒,事件處理完畢以后粪糙,回到睡眠狀態(tài)强霎,等待下次喚醒

二、runloop的mode作用是什么?:

1.model 主要是用來指定事件在運行循環(huán)中的優(yōu)先級的蓉冈,分為:

  • NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默認城舞,空閑狀態(tài)
  • UITrackingRunLoopMode :ScrollView滑動時
  • UIInitializationRunLoopMode :啟動時
  • NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合

2.蘋果公開提供的 Mode有兩個:

  1. NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
  2. NSRunLoopCommonModes(kCFRunLoopCommonModes)
    原文https://blog.csdn.net/shihuboke/article/details/78417299
    RunLoop分析學習

KVC getter 和 setter 的搜索策略是什么?

setter實現(xiàn)原理
1寞酿、查找是否實現(xiàn)setter家夺、_setter方法,如果有伐弹,優(yōu)先調(diào)用setter方法完成賦值
2拉馋、當沒找到setter方法,調(diào)用accessInstanceVariableesDirectly詢問。
如果返回YES煌茴,順序匹配變量名與 _<key>, _is<Key>, <key>, is<Key>随闺,匹配到則設定其值
如果返回NO,結(jié)束查找蔓腐。并調(diào)用 setValue: forUnderfinedKey: 報異常
3矩乐、如果既沒有setter也沒有實例變量時,調(diào)用 setValue: forUnderfinedKey:

getter實現(xiàn)原理
1回论、查找是否實現(xiàn)getter方法散罕,依次匹配‘-get<Key>’ 、 ‘-<key>’ 傀蓉、 ’is<Key>‘欧漱,如果找到,直接返回
2僚害、當沒有找到getter方法硫椰,調(diào)用accessInstanceVariablesDirectly詢問
如果返回YES,_<key>, _is<Key>, <key>, is<Key>萨蚕,找到了返回對應的值
如果返回NO靶草,結(jié)束查找,并調(diào)用 valueForUnderfinedKey: 報異常
3岳遥、如果沒有找到getter方法和屬性值奕翔,調(diào)用valueForUnderfinedKey: 報異常

KVC 有什么實際的應用

屬性賦值、添加私有成員變量浩蓉、KVC可以修改類的私有變量派继、KVC可以用來給model賦值
如UITextField的placeHolderText默認style在需求中達不到要求,我們可以直接通過KVC快速定義自己的style,代碼如下:

[textField setValue:[UIColor redColor] forKeyPath:@"placeholderLabel.textColor"];

引用計數(shù)原理

SideTable中包含三個成員:自旋鎖(slock)捻艳,引用計數(shù)表(RefcountMap)驾窟,弱引用表(weak_table_t)。引用計數(shù)表是個哈希表认轨,用來存儲對象的引用計數(shù)绅络。弱引用表也是哈希表,用來存放對象的弱引用指針嘁字。

SideTables是一個全局的哈希數(shù)組恩急,里面存儲了多張SideTable,在iOS的真機模式下纪蜒,最多8張衷恭,在MacOS或者模擬器模式下,最多64張随珠。每一個對象對應一個SideTable灭袁,每一個SideTable存儲多個對象的引用計數(shù)和弱引用指針牙丽。

nonpointer類型的對象简卧,引用計數(shù)存儲在isa的extra_rc和SideTable的RefcountMap中。當被retain或者realease時烤芦,先操作extra_rc,溢出或者為0時析校,才操作SideTable构罗。

非nonpointer類型的對象,引用計數(shù)只存儲在SideTable的RefcountMap中智玻。

TaggedPointer對象遂唧,內(nèi)存由系統(tǒng)管理,不用處理引用計數(shù)吊奢。

當對象被弱引用時盖彭,這個弱引用指針會存儲在SideTable的weak_table_t中。

當對象被釋放時页滚,會先執(zhí)行C++析構(gòu)函數(shù)召边,刪除關聯(lián)對象,清空引用計數(shù)裹驰,將弱引用指針設為nil后清空隧熙,最后free釋放內(nèi)存空間。

retainCount獲取的引用計數(shù)值要比對象的真實值多1幻林,最小為1贞盯。

alloc的對象引用計數(shù)為0。

鏈接:http://www.reibang.com/p/0ecd91dc34aa
自動釋放池底層實現(xiàn)
內(nèi)存管理

Swizzle 的優(yōu)缺點? 缺點會導致什么問題?

每一個OC實例對象都保存有isa指針和實例變量沪饺,其中isa指針所屬類躏敢,類維護一個運行時可接收的方法列表(MethodLists); 方法列表(MethodLists)中保存selector & IMP的映射關系整葡。在運行時件余,通過selecter找到匹配的IMP,從而找到的具體的實現(xiàn)函數(shù)掘宪。

開發(fā)中可以利用Objective-C的動態(tài)特性蛾扇,在運行時替換selector對應的方法實現(xiàn)(IMP),達到給hook的目的魏滚。下圖是利用 Method Swizzle 來替換selector對應IMP后的方法列表示意圖镀首。

@implementation NSObject (Swizzle)
+(void)load {
    //調(diào)換IMP
    Method originMethod = class_getInstanceMethod([NSObject class], @seletor(description));
    Method newMethod = class_getInstanceMethod([NSObject class], @seletor(replace_description));
    method_exchangeImplementations(originMethod,newMethod);
}

- (void)replace_description {
    NSLog(@"description 被 Swizzle 了");
    [self replace_description];
}

使用swizzle時,我們應該注意哪些問題呢鼠次?

問題一:繼承問題

如果 originalMethod 是其父類實現(xiàn)的更哄,那么直接 method_exchangeImplementations 是把父類中的 originalMethod 給替換了芋齿,導致該父類以及其他子類調(diào)用的 originalMethod 也會被替換

解決: 通過 class_addMethod 判斷 method 是不是屬于本類自己實現(xiàn)的?

class_addMethod 返回 YES -> addMethod 成功成翩,class中不存在 method觅捆,也就是存在父類中。addMethod之后麻敌,當前class也就存在method 了(覆蓋了父類的方法)
class_addMethod 返回 NO -> addMethod 失敗栅炒,class中存在 method,說明當前方法屬于當前class
判斷之后术羔,再執(zhí)行 exchange

如何做到對象級別的 swizzle赢赊?

只對某個對象進行 swizzle,不影響其他對象
方案:

1.類本身支持级历∈鸵疲可以標記一下,在執(zhí)行方法時寥殖,判斷是否存在標記來判斷是否執(zhí)行swizzle 之后的方法玩讳。可以參考:第三方庫 DZNEmptyDataSet(統(tǒng)一空白頁)
2.動態(tài)生成一個當前對象所屬類的子類嚼贡,并將當前對象與子類關聯(lián)熏纯。這樣的話,swizzle的都是其子類的方法编曼,不會影響父類豆巨。可以參考:第三方庫 Aspects

_objc_msgForward

_objc_msgForward 是一個函數(shù)指針(和 IMP 的類型一樣)掐场,是用于消息轉(zhuǎn)發(fā)的:當向一個對象發(fā)送一條消息往扔,但它并沒有實現(xiàn)的時候,_objc_msgForward 會直接走消息轉(zhuǎn)發(fā)熊户。

OC 消息轉(zhuǎn)發(fā)機制

眾所周知OC的一個對象在發(fā)送消息的時候首先在cache里找萍膛,如果找不到就在該類的struct objc_method_list列表中去搜索,如果找到則直接調(diào)用相關方法的實現(xiàn)嚷堡,如果沒有找到就會通過super_class指針沿著繼承樹向上去搜索蝗罗,如果找到就跳轉(zhuǎn),如果到了繼承樹的根部(通常為NSObject)還沒有找到蝌戒。那就會調(diào)用NSObjec的一個方法doesNotRecognizeSelector:串塑,這樣就會報unrecognized selector 錯誤。其實在調(diào)用doesNotRecognizeSelector:方法之前還會進行消息轉(zhuǎn)發(fā)---還有三次機會來補救北苟。也就是常說的OC消息轉(zhuǎn)發(fā)的三次補救措施桩匪。

總的來說一個OC消息的發(fā)送會經(jīng)歷四個階段(該四個階段都是搜索到NSObject再進入下階段)

1)先在本類中搜索改方法的實現(xiàn),如果有則直接調(diào)用若果沒有則去父類中搜索直到NSObject友鼻,如果NSObject沒有則進入消息轉(zhuǎn)發(fā)(類的動態(tài)方法解析傻昙、備用接受者對象闺骚、完整的消息轉(zhuǎn)發(fā))。

2)類的動態(tài)方法解析:
在該類和父類中沒有找到該方法的實現(xiàn)則會執(zhí)行 +(BOOL)resolveClassMethod:(SEL)sel 或+(BOOL)resolveInstanceMethod:(SEL)sel 方法妆档。在+(BOOL)resolveClassMethod:(SEL)sel 或+(BOOL)resolveInstanceMethod:(SEL)sel 方法 中利用黑魔法runtime 動態(tài)添加方法實現(xiàn)

3)備用接受者: 在+(BOOL)resolveClassMethod:(SEL)sel 或+(BOOL)resolveInstanceMethod:(SEL)sel 方法返回NO的時候進入備用接受者階段 僻爽。
創(chuàng)建一個備用接受者類ForwardPerson 實現(xiàn)appendString:方法
在SonPerson類中實現(xiàn)- (id)forwardingTargetForSelector:(SEL)aSelector 方法 并返回一個備用接受者對象

4)完整的消息轉(zhuǎn)發(fā):當-(void)forwardInvocation:(NSInvocation*)anInvocation 方法方法nil的時候則進入消息轉(zhuǎn)發(fā)的最后階段,完整的消息轉(zhuǎn)發(fā)贾惦。也需要創(chuàng)建一個轉(zhuǎn)發(fā)對象ForwardInvocation

在SonPerson中實現(xiàn)
-(void)forwardInvocation:(NSInvocation*)anInvocation和

  • (NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector方法
-(void)forwardInvocation:(NSInvocation*)anInvocation{

    NSLog(@"forwardInvocation");

    if ([ForwardInvocation instancesRespondToSelector:anInvocation.selector]) {

        [anInvocation invokeWithTarget:self.invocation];

    }

}

/必須重新這個方法胸梆,消息轉(zhuǎn)發(fā)機制使用從這個方法中獲取的信息來創(chuàng)建NSInvocation對象 返回nil上面方法不執(zhí)行/

鏈接:http://www.reibang.com/p/1073daee5b92

@implementation Son : Father
- (id)init {
    self = [superinit];
    if(self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
  return self;
}

答案:都輸出 Son

self 是類的隱藏參數(shù),指向當前調(diào)用方法的這個類的實例须板。
super 是一個編譯器標示符乳绕,和 self 是指向的同一個消息接受者
當使用 self 調(diào)用方法時,會從當前類的方法列表中開始找逼纸,如果沒有,就從父類中再找济蝉;而當使用 super 時杰刽,則從父類的方法列表中開始找。然后調(diào)用父類的這個方法王滤。

當調(diào)用 [self class] 時贺嫂,實際先調(diào)用的是 objc_msgSend函數(shù),第一個參數(shù)是 Son當前的這個實例雁乡,然后在 Son 這個類里面去找 - (Class)class這個方法第喳,沒有,去父類 Father里找踱稍,也沒有曲饱,最后在 NSObject類中發(fā)現(xiàn)這個方法。而 - (Class)class的實現(xiàn)就是返回self的類別珠月,故上述輸出結(jié)果為 Son扩淀。

而當調(diào)用 [super class]時,會轉(zhuǎn)換成objc_msgSendSuper函數(shù)啤挎。第一步先構(gòu)造 objc_super 結(jié)構(gòu)體驻谆,結(jié)構(gòu)體第一個成員就是 self 。 第二個成員是 (id)class_getSuperclass(objc_getClass(“Son”)) , 實際該函數(shù)輸出結(jié)果為 Father庆聘。 第二步是去 Father這個類里去找 - (Class)class胜臊,沒有,然后去NSObject類去找伙判,找到了象对。最后內(nèi)部是使用 objc_msgSend(objc_super->receiver, @selector(class))去調(diào)用, 此時已經(jīng)和[self class]調(diào)用相同了澳腹,故上述輸出結(jié)果仍然返回 Son织盼。

IMP杨何、SEL Method 都表示什么意思?

Method
/// An opaque type that represents a method in a class definition.代表類定義中一個方法的不透明類型

typedef struct objc_method *Method;

struct objc_method {
    SEL method_name                                          OBJC2_UNAVAILABLE;
    char *method_types                                       OBJC2_UNAVAILABLE;
    IMP method_imp                                           OBJC2_UNAVAILABLE;
} 

我們來看下objc_method這個結(jié)構(gòu)體的內(nèi)容:

SEL method_name 方法名
char *method_types 方法類型
IMP method_imp 方法實現(xiàn)
在這個結(jié)構(gòu)體重,我們已經(jīng)看到了SEL和IMP沥邻,說明SEL和IMP其實都是Method的屬性危虱。

SEL
Objc.h
/// An opaque type that represents a method selector.代表一個方法的不透明類型
typedef struct objc_selector *SEL;

selector是SEL的一個實例
selector既然是一個string,我覺得應該是類似className+method的組合唐全,命名規(guī)則有兩條:

同一個類埃跷,selector不能重復
不同的類,selector可以重復

IMP
/// A pointer to the function of a method implementation. 指向一個方法實現(xiàn)的指針
typedef id (*IMP)(id, SEL, ...);

endif

指向最終實現(xiàn)程序的內(nèi)存地址的指針

綜上邮利,在iOS的runtime中弥雹,Method通過selector和IMP兩個屬性,實現(xiàn)了快速查詢方法及實現(xiàn)延届,相對提高了性能剪勿,又保持了靈活性。

關于重載和重寫的區(qū)別

oc是不支持的重載的
oc和swift都是支持重寫的方庭。關于重寫厕吉,只能發(fā)生在父類和子類之間

OC是否支持重載? 為什么?

理解 OC 中的方法調(diào)用

[self foo]
通過 clang 轉(zhuǎn)為 c++ 代碼為

((void (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("foo"));
foo 方法的調(diào)用,實際是調(diào)用了 objc_msgSend 這個函數(shù)械念,self头朱,sel 作為函數(shù)的參數(shù)。

再來看下上述兩個方法龄减。兩者的 sel 都是foo:项钮。對于一個類,其內(nèi)部有一個方法的列表希停。msgSend 函數(shù)的實現(xiàn)為根據(jù) sel 從方法列表中獲取 imp烁巫。因此上述兩個方法的 SEL 存在重復,msgSend 函數(shù)不能區(qū)分脖苏,找到對應的 imp程拭。因此,在 OC 語言中不存在上述的方法重載棍潘。

isa 指針是什么恃鞋?

struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};

通過注釋和代碼不難發(fā)現(xiàn),我們創(chuàng)建的一個對象或?qū)嵗鋵嵕褪且粋€struct objc_object結(jié)構(gòu)體亦歉,而我們常用的id也就是這個結(jié)構(gòu)體的指針恤浪。
這個結(jié)構(gòu)體只有一個成員變量,這是一個Class類型的變量isa肴楷,也是一個結(jié)構(gòu)體指針
面向?qū)ο笾忻恳粋€對象都必須依賴一個類來創(chuàng)建水由,因此對象的isa指針就指向?qū)ο笏鶎俚念惛鶕?jù)這個類模板能夠創(chuàng)建出實例變量、實例方法等赛蔫。

isa指針里面都存了什么?

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

struct objc_classs結(jié)構(gòu)體里存放的數(shù)據(jù)稱為元數(shù)據(jù)(metadata)砂客,通過成員變量的名稱我們可以猜測里面存放有指向父類的指針泥张、類的名字、版本鞠值、實例大小媚创、實例變量列表、方法列表彤恶、緩存钞钙、遵守的協(xié)議列表等,

Person *p = [[Person alloc] init];
//輸出1
NSLog(@"%d", [p class] == object_getClass?);
//輸出0
NSLog(@"%d", class_isMetaClass(object_getClass?));
//輸出1
NSLog(@"%d", class_isMetaClass(object_getClass([Person class])));
//輸出0
NSLog(@"%d", object_getClass(p) == object_getClass([Person class]));

通過代碼可以看出声离,一個實例對象通過class方法獲取的Class就是它的isa指針指向的類對象芒炼,而類對象不是元類,類對象的isa指針指向的對象是元類术徊。

一個NSObject對象占用多少內(nèi)存本刽?

答:一個指針變量所占用的大小(64bit占8個字節(jié)赠涮,32bit占4個字節(jié))

對象的isa指針指向哪里盅安?

答:instance對象的isa指針指向class對象,class對象的isa指針指向meta-class對象世囊,meta-class對象的isa指針指向基類的meta-class對象,基類自己的isa指針也指向自己窿祥。

OC的類信息存放在哪里株憾?

答:成員變量的具體值存放在instance對象。對象方法晒衩,協(xié)議嗤瞎,屬性,成員變量信息存放在class對象听系。類方法信息存放在meta-class對象贝奇。

鏈接:http://www.reibang.com/p/aa7ccadeca88

(APP)進程間8中常用通信方式總結(jié)

https://blog.csdn.net/kuangdacaikuang/article/details/78891379

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [self performSelector:@selector(sureTestMethod:)
               withObject:params
               afterDelay:3];
});
- (void)sureTestMethod:(id)objcet {
    NSLog(@"sureTestMethodCall");
}

performSelector: withObject: afterDelay:是在當前Runloop中延時執(zhí)行的,而子線程的Runloop默認不開啟靠胜,因此無法響應方法掉瞳。

dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [self performSelector:@selector(sureTestMethod:)
                   withObject:params
                   afterDelay:3];
        [[NSRunLoop currentRunLoop]run];
    });

這里有個坑需要注意,曾經(jīng)嘗試將 [[NSRunLoop currentRunLoop]run]添加在performSelector: withObject: afterDelay:方法前浪漠,但發(fā)現(xiàn)延遲方法仍然不調(diào)用陕习,這是因為若想開啟某線程的Runloop,必須具有timer址愿、source该镣、observer任一事件才能觸發(fā)開啟。

簡言之如下代碼在執(zhí)行 [[NSRunLoop currentRunLoop]run]前沒有任何事件添加到當前Runloop响谓,因此該線程的Runloop是不會開啟的损合,從而延遲事件不執(zhí)行省艳。

另附面試鏈接地址

iOS進階面試題總結(jié)(一)
iOS進階面試題總結(jié)(二)
面試題整理:https://ios.nobady.cn

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者嫁审。
  • 序言:七十年代末跋炕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子土居,更是在濱河造成了極大的恐慌枣购,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擦耀,死亡現(xiàn)場離奇詭異棉圈,居然都是意外死亡,警方通過查閱死者的電腦和手機眷蜓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門分瘾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吁系,你說我怎么就攤上這事德召。” “怎么了汽纤?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵上岗,是天一觀的道長。 經(jīng)常有香客問我蕴坪,道長肴掷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任背传,我火速辦了婚禮呆瞻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘径玖。我一直安慰自己痴脾,他們只是感情好,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布梳星。 她就那樣靜靜地躺著赞赖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪冤灾。 梳的紋絲不亂的頭發(fā)上薯定,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音瞳购,去河邊找鬼话侄。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的年堆。 我是一名探鬼主播吞杭,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼变丧!你這毒婦竟也來了芽狗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤痒蓬,失蹤者是張志新(化名)和其女友劉穎童擎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體攻晒,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡顾复,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鲁捏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芯砸。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖给梅,靈堂內(nèi)的尸體忽然破棺而出假丧,到底是詐尸還是另有隱情,我是刑警寧澤动羽,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布包帚,位于F島的核電站,受9級特大地震影響运吓,放射性物質(zhì)發(fā)生泄漏婴噩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一羽德、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迅办,春花似錦宅静、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至矾策,卻和暖如春磷账,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贾虽。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工逃糟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓绰咽,卻偏偏與公主長得像菇肃,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子取募,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容

  • iOS面試總結(jié) 1. 網(wǎng)絡 HTTP協(xié)議(HyperText Transfer Protocol)的請求和響應請求...
    崇山峻嶺閱讀 573評論 0 2
  • 2017年iOS面試總結(jié) 1琐谤、為什么說Objective-C是一門動態(tài)語言? 答:Objective-C類的類型和...
    我叫王可可閱讀 331評論 0 1
  • [toc]主要是一些視頻筆記和面試時候常問到的問題記錄玩敏。(持續(xù)更新) Runtime 什么是 Runtime斗忌?它的...
    youlookdeliciou閱讀 589評論 0 8
  • 我是一只勤勞的小蜜蜂。閑暇之余旺聚,總結(jié)下一直以來自己面試過程中所遇到的一些高概率問題织阳,分享給大家,共同成長翻屈。該貼后續(xù)...
    智障小魯班閱讀 440評論 0 12
  • ??絮:2020年到來了陈哑,隨著疫情的到來,我也失業(yè)了伸眶。一邊忙著抵抗病毒惊窖,一邊還得繼續(xù)準備面試。又該準備“造火箭”了厘贼,...
    七秒記憶的魚兒閱讀 6,143評論 25 81