iOS最新面試題解答最全-2023-05

1,內(nèi)存分布在哪幾個(gè)區(qū),哪些區(qū)地址是怎么分布的

iOS內(nèi)存的五大區(qū)域 :棧區(qū)(stack):存放函數(shù)參數(shù)值、局部變量的值, 0X7開頭;堆區(qū)(heap):以0x6開頭;全局區(qū)(又稱靜態(tài)區(qū))(static):存放全局變量和靜態(tài)變量,以0x1開頭;文字常量區(qū):存放常量:整型、字符型、浮點(diǎn)、字符串等;程序代碼區(qū):存放函數(shù)的二進(jìn)制代碼。


image.png

2,有了解mach-o文件嗎?里面是什么結(jié)構(gòu)

Mach-O:是Mach object的縮寫,是Mac\iOS上用于存儲(chǔ)程序、庫的標(biāo)準(zhǔn)格式。有很多種類型,

常見類型有:
1、MH_OBJECT:
1)、目標(biāo)文件(.o)
2)、靜態(tài)庫文件(.a),靜態(tài)庫其實(shí)就是N個(gè).o合并在一起的
2、MH_EXECUTE:可執(zhí)行文件

.app/xx
3、MH_DYLIB:動(dòng)態(tài)庫文件

.dylib
.framework/xx
4、MH_DYLINKER:動(dòng)態(tài)鏈接編輯器

/usr/lib/dyld
5、MH_DSYM:存儲(chǔ)著二進(jìn)制文件符號信息的文件

.dSYM/Contents/Resources/DWARF/xx(常用于分析APP的崩潰信息)

Mach-O目標(biāo)文件是源代碼編譯得到的文件,包含機(jī)器指令,數(shù)據(jù),符號表,調(diào)試信息,字符串等,然后按照不同的信息,放在不同的“段”(segment)中;比如指令一般放在代碼段里,變量一般放在數(shù)據(jù)段里.
官方描述
https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/MachOTopics/0-Introduction/introduction.html

一個(gè)Mach-O文件包含3個(gè)主要區(qū)域:
1、Header :保存文件的基本信息,如文件類型、CPU架構(gòu)信息、加載命令個(gè)數(shù)等。
2、Load commands:根據(jù)這里的數(shù)據(jù)確定內(nèi)存分布(本身不包含數(shù)據(jù),類似于一個(gè)指針)。
3、Raw segment data:存放具體的代碼和數(shù)據(jù),是Mach-O文件真正的內(nèi)容數(shù)據(jù)。


image.png

3,NSString *name = @"hahh",NSString *name1 = [NSString stringWithFormat:@"1"],NSString *name3 = [NSString stringWithFormat:@"荔枝集團(tuán)-哈哈"],

里面變量存放在哪里,
局部變量都是在全局區(qū)
[NSString stringWithFormat:@"1"],NSString *name3 = [NSString stringWithFormat:@"荔枝集團(tuán)-哈哈"],存放在哪里


image.png

4,KVO,在oberserforkey調(diào)用self.name=name,會(huì)發(fā)生什么情況,

死循環(huán)

5,NSTimer 跟viewConther,是怎么循環(huán)引用的,當(dāng)NSTimer只是作為viewConther一個(gè)局部變量,會(huì)發(fā)生內(nèi)存泄漏嗎?

會(huì)導(dǎo)致循環(huán)引用,不管是作為局部變量還是屬性,用block就不會(huì),
會(huì)導(dǎo)致泄露

6,當(dāng)在瀏覽器www.baidu.com,敲回車,是怎么流程?為什么后面能顯示百度頁面

DNS 解析:將域名解析成 IP 地址
TCP 連接:TCP 三次握手
發(fā)送 HTTP 請求
服務(wù)器處理請求并返回 HTTP 報(bào)文
瀏覽器解析渲染頁面
斷開連接:TCP 四次揮手

URL(Uniform Resource Locator),統(tǒng)一資源定位符,用于定位互聯(lián)網(wǎng)上資源,俗稱網(wǎng)址
scheme://host.domain:port/path/filename
各部分解釋如下:
scheme - 定義因特網(wǎng)服務(wù)的類型。常見的協(xié)議有 http、https、ftp、file,其中最常見的類型是 http,而 https 則是進(jìn)行加密的網(wǎng)絡(luò)傳輸。
host - 定義域主機(jī)(http 的默認(rèn)主機(jī)是 www)
domain - 定義因特網(wǎng)域名,比如 http://baidu.com
port - 定義主機(jī)上的端口號(http 的默認(rèn)端口號是 80)
path - 定義服務(wù)器上的路徑(如果省略,則文檔必須位于網(wǎng)站的根目錄中)。
filename - 定義文檔/資源的名稱

瀏覽器如何通過域名去查詢 URL 對應(yīng)的 IP 呢

瀏覽器緩存 – 瀏覽器會(huì)緩存DNS記錄一段時(shí)間。 (2分鐘到30分鐘不等)。

系統(tǒng)緩存 – 如果在瀏覽器緩存里沒有找到需要的記錄,瀏覽器會(huì)做一個(gè)系統(tǒng)調(diào)用(windows里是gethostbyname)。

路由器緩存 – 接著,前面的查詢請求發(fā)向路由器,它一般會(huì)有自己的DNS緩存。

ISP DNS 緩存 – ISP 有專門的 DNS 服務(wù)器應(yīng)對 DNS 查詢請求。

遞歸搜索 – 你的ISP的DNS服務(wù)器從根域名服務(wù)器開始進(jìn)行遞歸搜索,從.com頂級域名服務(wù)器到baidu的域名服務(wù)器。一般DNS服務(wù)器的緩存中會(huì)有.com域名服務(wù)器中的域名,所以到頂級服務(wù)器的匹配過程不是那么必要了。

瀏覽器通過向 DNS 服務(wù)器發(fā)送域名,DNS 服務(wù)器查詢到與域名相對應(yīng)的 IP 地址,然后返回給瀏覽器,瀏覽器再將 IP 地址打在協(xié)議上,同時(shí)請求參數(shù)也會(huì)在協(xié)議搭載,然后一并發(fā)送給對應(yīng)的服務(wù)器。接下來介紹向服務(wù)器發(fā)送 HTTP 請求階段,HTTP 請求分為三個(gè)部分:TCP 三次握手、http 請求響應(yīng)信息、關(guān)閉 TCP 連接。

7,dns是哪一層協(xié)議,dns是怎么工作流程的?

DNS協(xié)議位于OSI模型的應(yīng)用層

7,viewconther有個(gè)屬性NSTimer,在子線程里創(chuàng)建NSTimer,并間隔2s執(zhí)行,并加入當(dāng)前runloop,在主線程是對NSTimer能否釋放掉嗎

經(jīng)過測試,沒有釋放,釋放不掉

@interface SecondeViewController ()
@property(nonatomic,strong)NSTimer *timer;
@end

@implementation SecondeViewController
- (void)dealloc {
    NSLog(@"銷毀");
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.timer invalidate];
}
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
//    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread) object:nil];
//       [thread start];
   self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(dicClickEvent) userInfo:nil repeats:YES];
//    __weak typeof(self) weakSelf = self;
//       self.timer =  [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
//            __strong typeof(weakSelf) strongSelf = weakSelf;
//           //do something
//             [strongSelf dicClickEvent];
//        }];

    // Do any additional setup after loading the view.
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//寫在這里去銷毀timer是無效的
   //  [self.timer invalidate];
    [self dismissViewControllerAnimated:YES completion:nil];
}
- (void)newThread
 {
      @autoreleasepool
     {
      self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(addTime) userInfo:nil repeats:YES];
//
     [[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
     [[NSRunLoop currentRunLoop] run];
      }
  }
- (void)addTime {
    NSLog(@"定時(shí)器計(jì)時(shí)中");
}
- (void)dicClickEvent {
    NSLog(@"------");
}

@end

結(jié)論是可以銷毀的

9,講講runloop相關(guān)技術(shù)

鏈接

10,崩潰日志怎么做到實(shí)時(shí)上傳的,用nsurlcontent

1,NSURLConnection 同步等待 Crash 日志上傳
2,啟用后臺進(jìn)程上傳 Crash 日志
其實(shí)最理想的日志上傳,是將上傳的 request 放到另一個(gè)不同的進(jìn)程,那么即使 App 又發(fā)生閃退,也不會(huì)影響到另一個(gè)進(jìn)程代碼的執(zhí)行。

問題是,iOS app 都處于 sandbox 環(huán)境下,系統(tǒng)不允許代碼 fork 一個(gè)新進(jìn)程。

幸運(yùn)的是,從 iOS 8 開始,系統(tǒng)對 NSURLSession 新增了一個(gè) background session 特性。這個(gè)特性允許 NSURLSession 將網(wǎng)絡(luò)請求放入到一個(gè)單獨(dú)的進(jìn)程中執(zhí)行。我個(gè)人感覺,這個(gè)特性設(shè)計(jì),原本是為了增強(qiáng)某些 App 后臺下載音視頻等資源的體驗(yàn)。我實(shí)際測試下來,發(fā)現(xiàn)不管下載或者是上傳,我們都可以將網(wǎng)絡(luò)請求放入另一個(gè)進(jìn)程。代碼也很簡單,比如我寫一段如下的測試代碼:


NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.mrpeak.background.crashupload"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue new]];
NSURL *url = [NSURL URLWithString:@"https://images.unsplash.com/photo-1515816949419-7caf0a210607?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=f46b60857b4826e733da34993ec26a2f&auto=format&fit=crop&w=1534&q=80"];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
[task resume];

exit(0);

11,講講main之前做了什么操作?你做了哪些優(yōu)化點(diǎn)

Pre-mian 大概過程主要分為:Load dylibs、Rebase、Bind、Objc、Initializers 這幾個(gè)步驟。

當(dāng)我們點(diǎn)擊 App 圖標(biāo),內(nèi)核就開始做啟動(dòng)程序的初始化,然后交給 dyld(The Dynamic Link Editor,動(dòng)態(tài)鏈接器);dyld 首先會(huì)讀取鏡像文件,然后遞歸的查找動(dòng)態(tài)庫,利用 ImageLoader(鏡像加載器) 來將其加載到內(nèi)存中,但是由于 ASLR 的特性,這里需要 Rebase/Bind 修復(fù)鏡像中的資源指針,來指向正確的地址;然后 dyld 會(huì)通知 Runtime:ImageLoader 已經(jīng)將對應(yīng)的鏡像加載到內(nèi)存,這個(gè)時(shí)候 Runtime 會(huì)調(diào)用 map_image 去解析和處理該鏡像資源(譬如注冊 Objc 類、處理 category 等);接下來再調(diào)用 load_image,遍歷調(diào)用類的 load 方法、調(diào)用C++的構(gòu)造函數(shù)屬性函數(shù)、創(chuàng)建非基本類型的C++靜態(tài)全局變量等等。
上面的文字可能比較生澀難懂, 簡單講:

加載自動(dòng)鏈接的動(dòng)態(tài)庫,并先后執(zhí)行動(dòng)態(tài)庫中的2、3項(xiàng)。
執(zhí)行 +load 方法
執(zhí)行 C++ static initializers and C/C++ attribute(constructor) functions 。
通過上面一段簡單的敘述,我們大概了解知道m(xù)ian之前的過程, 也就有了優(yōu)化的方向.

1,優(yōu)化 Load Dylibs Image 過程
盡量減少動(dòng)態(tài)庫的依賴和合并一些動(dòng)態(tài)庫,減少 ImageLoading 加載鏡像的數(shù)量;不過這里一般不是 App 的瓶頸,這里只需要平時(shí)需要注意項(xiàng)目中不要依賴太多動(dòng)態(tài)庫就可以了。

2,優(yōu)化 Rebase/Bind 過程
這里主要由于 ASLR 特性,需要修復(fù)鏡像中的資源指針,來指向正確的地址;這里一般不太好優(yōu)化,只能說盡量將項(xiàng)目中不用的類給刪除,減少類數(shù)量和 selector 數(shù)量。

3,優(yōu)化 Objc 過程
這個(gè)過程主要是:注冊 Objc 類,處理 category,將 category 中的方法屬性協(xié)議等插入到本類中去,這塊一般也沒什么優(yōu)化的空間。
4,優(yōu)化 Initializers 過程
這個(gè)過程主要做初始化工作,相對其它過程會(huì)比較耗時(shí),這里我們需要注意以下操作的耗時(shí),去分析對應(yīng)操作有沒必要在 Pre-main 這個(gè)階段去處理,是否可以在程序啟動(dòng)完成之后再處理:
Load 函數(shù)中的操作
C++的構(gòu)造函數(shù)屬性函數(shù)
C++靜態(tài)全局變量
通過上面幾個(gè)步驟,我們主要能優(yōu)化的點(diǎn)如下:
減少動(dòng)態(tài)庫的依賴
減少 Objc 類和方法
減少 C++的構(gòu)造函數(shù)
減少 C++靜態(tài)全局變量
減少 +load 函數(shù)數(shù)量, 并避免做耗時(shí)操作

11,當(dāng)一個(gè)頁面內(nèi)存泄漏了,你是怎么處理的?

常用的內(nèi)存檢查工具

Instruments

Instruments 是 Xcode 自帶的工具集合,為開發(fā)者提供強(qiáng)大的程序性能分析和測試能力。

它打開方式為:Xcode → Open Developer Tool → Instruments。其中的 Allocations、Leaks 和 Zombies 功能可以協(xié)助我們進(jìn)行內(nèi)存泄漏檢查。

? Leaks:動(dòng)態(tài)檢查泄漏的內(nèi)存,如果檢查過程時(shí)出現(xiàn)了紅色叉叉,就說明存在內(nèi)存泄漏,可以定位到泄漏的位置,去解決問題。此外,Xcode 中還提供靜態(tài)監(jiān)測方法 Analyze,可以直接通過 Product → Analyze 打開,如果出現(xiàn)泄漏,會(huì)出現(xiàn)“藍(lán)色分支圖標(biāo)”提示。

? Allocations:用來檢查內(nèi)存使用/分配情況。比如出現(xiàn)“循環(huán)加載引起內(nèi)存峰值”的情況,就可以通過這個(gè)工具檢查出來。

? Zombies:檢查是否訪問了僵尸對象。

Instruments 的使用相對來說比較復(fù)雜,你也可以通過在工程中引入一些第三方框架進(jìn)行檢測。

13,講講http,https的區(qū)別,tcp,udp,為什么tcp要三次鏈接,網(wǎng)絡(luò)層里有哪些協(xié)議?網(wǎng)絡(luò)層是做了什么工作的

HTTPS(Hypertext Transfer Protocol Secure:超文本傳輸安全協(xié)議)是一種透過計(jì)算機(jī)網(wǎng)絡(luò)進(jìn)行安全通信的傳輸協(xié)議。HTTPS 經(jīng)由 HTTP 進(jìn)行通信,但利用 SSL/TLS 來加密數(shù)據(jù)包。HTTPS 開發(fā)的主要目的,是提供對網(wǎng)站服務(wù)器的身份認(rèn)證,保護(hù)交換數(shù)據(jù)的隱私與完整性。

HTTPS 默認(rèn)工作在 TCP 協(xié)議443端口,它的工作流程一般如以下方式:

1、TCP 三次同步握手
2、客戶端驗(yàn)證服務(wù)器數(shù)字證書
3、DH 算法協(xié)商對稱加密算法的密鑰、hash 算法的密鑰
4、SSL 安全加密隧道協(xié)商完成
5、網(wǎng)頁以加密的方式傳輸,用協(xié)商的對稱加密算法和密鑰加密,保證數(shù)據(jù)機(jī)密性;用協(xié)商的hash算法進(jìn)行數(shù)據(jù)完整性保護(hù),保證數(shù)據(jù)不被篡改。
HTTP 與 HTTPS 區(qū)別
HTTP 明文傳輸,數(shù)據(jù)都是未加密的,安全性較差,HTTPS(SSL+HTTP) 數(shù)據(jù)傳輸過程是加密的,安全性較好。
使用 HTTPS 協(xié)議需要到 CA(Certificate Authority,數(shù)字證書認(rèn)證機(jī)構(gòu)) 申請證書,一般免費(fèi)證書較少,因而需要一定費(fèi)用。證書頒發(fā)機(jī)構(gòu)如:Symantec、Comodo、GoDaddy 和 GlobalSign 等。
HTTP 頁面響應(yīng)速度比 HTTPS 快,主要是因?yàn)?HTTP 使用 TCP 三次握手建立連接,客戶端和服務(wù)器需要交換 3 個(gè)包,而 HTTPS除了 TCP 的三個(gè)包,還要加上 ssl 握手需要的 9 個(gè)包,所以一共是 12 個(gè)包。
http 和 https 使用的是完全不同的連接方式,用的端口也不一樣,前者是 80,后者是 443。
HTTPS 其實(shí)就是建構(gòu)在 SSL/TLS 之上的 HTTP 協(xié)議,所以,要比較 HTTPS 比 HTTP 要更耗費(fèi)服務(wù)器資源。


image.png

image.png

為什么 TCP 需要三次握手?

原因一:防止重復(fù)連接
三次握手的主要原因是為了防止舊的重復(fù)連接引起連接混亂問題
比如在網(wǎng)絡(luò)狀況比較復(fù)雜或者網(wǎng)絡(luò)狀況比較差的情況下,發(fā)送方可能會(huì)連續(xù)發(fā)送多次建立連接的請求
如果 TCP 握手的次數(shù)只有兩次,那么接收方只能選擇接受請求或者拒絕接受請求,但它并不清楚這次的請求是正常的請求,還是由于網(wǎng)絡(luò)環(huán)境問題而導(dǎo)致的過期請求,如果是過期請求的話就會(huì)造成錯(cuò)誤的連接
所以如果 TCP 是三次握手的話,那么客戶端在接收到服務(wù)器端 SEQ+1 的消息之后,就可以判斷當(dāng)前的連接是否為歷史連接,如果判斷為歷史連接的話就會(huì)發(fā)送終止報(bào)文(RST)給服務(wù)器端終止連接;如果判斷當(dāng)前連接不是歷史連接的話就會(huì)發(fā)送指令給服務(wù)器端來建立連接
原因二:同步初始化序列化
TCP 為了保證在不穩(wěn)定的網(wǎng)絡(luò)環(huán)境中構(gòu)建一個(gè)穩(wěn)定的數(shù)據(jù)連接,它就需要一個(gè)“序列號”字段來保證自己的穩(wěn)定性
而這個(gè)序列號的作用就是防止數(shù)據(jù)包重復(fù)發(fā)送,以及有效的解決數(shù)據(jù)包接收時(shí)順序顛倒的問題
那么在建立 TCP 連接時(shí)就需要同步初始化一個(gè)序列號來保證 TCP 的穩(wěn)定性,因此它需要執(zhí)行以下過程:
首先客戶端發(fā)送一個(gè)攜帶了初始序列號的 SYN 報(bào)文給服務(wù)器端
服務(wù)端接收到消息之后會(huì)回復(fù)一個(gè) ACK 的應(yīng)答報(bào)文,表示客戶端的 SYN 報(bào)文已被服務(wù)端成功接收了
而客戶端收到消息之后也會(huì)發(fā)送一個(gè) ACK 給服務(wù)端,服務(wù)器端拿到這個(gè)消息之后,我們就可以得到一個(gè)可靠的初始化序列號了
而如果是兩次握手的話,就無法進(jìn)行序列號的確認(rèn)工作了,因此也就無法得到一個(gè)可靠的序列號了,所以 TCP 連接至少需要三次握手

1.網(wǎng)際協(xié)議(IP)
IP是因特網(wǎng)使用的一種最為廣泛的網(wǎng)絡(luò)層協(xié)議,它的主要功能是將數(shù)據(jù)包從源地址傳輸?shù)侥康牡刂?,同時(shí)負(fù)責(zé)數(shù)據(jù)包的路由選擇、分段和重組等功能。
2.互聯(lián)網(wǎng)控制報(bào)文協(xié)議(ICMP)
3.地址解析協(xié)議(ARP)
4.網(wǎng)際組管理協(xié)議(IGMP)
5.網(wǎng)絡(luò)地址翻譯(NAT)
網(wǎng)絡(luò)層的主要任務(wù)是實(shí)現(xiàn)網(wǎng)絡(luò)互連,進(jìn)而實(shí)現(xiàn)數(shù)據(jù)包在各網(wǎng)絡(luò)之間的傳輸。
要實(shí)現(xiàn)網(wǎng)絡(luò)層任務(wù),需要解決以下主要問題:
網(wǎng)絡(luò)層向運(yùn)輸層提供怎樣的服務(wù)(“可靠傳輸”還是“不可靠傳輸”)
網(wǎng)絡(luò)層尋址問題
路由選擇問題
因特網(wǎng)是目前全世界用戶數(shù)量最多的互聯(lián)網(wǎng),它使用TCP/IP協(xié)議棧。
由于TCP/IP協(xié)議棧的網(wǎng)絡(luò)層使用網(wǎng)際協(xié)議IP,它是整個(gè)協(xié)議棧的核心協(xié)議,因此在TCP/IP協(xié)議棧中網(wǎng)絡(luò)層常稱為網(wǎng)際層。


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

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