iOS面试库iOS基础

iOS最新面试题解答最全-2023-05

2023-06-20  本文已影响0人  MoShengLive

1,内存分布在哪几个区,哪些区地址是怎么分布的

iOS内存的五大区域 :栈区(stack):存放函数参数值、局部变量的值, 0X7开头;堆区(heap):以0x6开头;全局区(又称静态区)(static):存放全局变量和静态变量,以0x1开头;文字常量区:存放常量:整型、字符型、浮点、字符串等;程序代码区:存放函数的二进制代码。


image.png

2,有了解mach-o文件吗?里面是什么结构

Mach-O:是Mach object的缩写,是Mac\iOS上用于存储程序、库的标准格式。有很多种类型,

常见类型有:
1、MH_OBJECT:
1)、目标文件(.o)
2)、静态库文件(.a),静态库其实就是N个.o合并在一起的
2、MH_EXECUTE:可执行文件

.app/xx
3、MH_DYLIB:动态库文件

.dylib
.framework/xx
4、MH_DYLINKER:动态链接编辑器

/usr/lib/dyld
5、MH_DSYM:存储着二进制文件符号信息的文件

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

Mach-O目标文件是源代码编译得到的文件,包含机器指令,数据,符号表,调试信息,字符串等,然后按照不同的信息,放在不同的“段”(segment)中;比如指令一般放在代码段里,变量一般放在数据段里.
官方描述
https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/MachOTopics/0-Introduction/introduction.html

一个Mach-O文件包含3个主要区域:
1、Header :保存文件的基本信息,如文件类型、CPU架构信息、加载命令个数等。
2、Load commands:根据这里的数据确定内存分布(本身不包含数据,类似于一个指针)。
3、Raw segment data:存放具体的代码和数据,是Mach-O文件真正的内容数据。


image.png

3,NSString *name = @"hahh",NSString *name1 = [NSString stringWithFormat:@"1"],NSString *name3 = [NSString stringWithFormat:@"荔枝集团-哈哈"],

里面变量存放在哪里,
局部变量都是在全局区
[NSString stringWithFormat:@"1"],NSString *name3 = [NSString stringWithFormat:@"荔枝集团-哈哈"],存放在哪里


image.png

4,KVO,在oberserforkey调用self.name=name,会发生什么情况,

死循环

5,NSTimer 跟viewConther,是怎么循环引用的,当NSTimer只是作为viewConther一个局部变量,会发生内存泄漏吗?

会导致循环引用,不管是作为局部变量还是属性,用block就不会,
会导致泄露

6,当在浏览器www.baidu.com,敲回车,是怎么流程?为什么后面能显示百度页面

DNS 解析:将域名解析成 IP 地址
TCP 连接:TCP 三次握手
发送 HTTP 请求
服务器处理请求并返回 HTTP 报文
浏览器解析渲染页面
断开连接:TCP 四次挥手

URL(Uniform Resource Locator),统一资源定位符,用于定位互联网上资源,俗称网址
scheme://host.domain:port/path/filename
各部分解释如下:
scheme - 定义因特网服务的类型。常见的协议有 http、https、ftp、file,其中最常见的类型是 http,而 https 则是进行加密的网络传输。
host - 定义域主机(http 的默认主机是 www)
domain - 定义因特网域名,比如 http://baidu.com
port - 定义主机上的端口号(http 的默认端口号是 80)
path - 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。
filename - 定义文档/资源的名称

浏览器如何通过域名去查询 URL 对应的 IP 呢

浏览器缓存 – 浏览器会缓存DNS记录一段时间。 (2分钟到30分钟不等)。

系统缓存 – 如果在浏览器缓存里没有找到需要的记录,浏览器会做一个系统调用(windows里是gethostbyname)。

路由器缓存 – 接着,前面的查询请求发向路由器,它一般会有自己的DNS缓存。

ISP DNS 缓存 – ISP 有专门的 DNS 服务器应对 DNS 查询请求。

递归搜索 – 你的ISP的DNS服务器从根域名服务器开始进行递归搜索,从.com顶级域名服务器到baidu的域名服务器。一般DNS服务器的缓存中会有.com域名服务器中的域名,所以到顶级服务器的匹配过程不是那么必要了。

浏览器通过向 DNS 服务器发送域名,DNS 服务器查询到与域名相对应的 IP 地址,然后返回给浏览器,浏览器再将 IP 地址打在协议上,同时请求参数也会在协议搭载,然后一并发送给对应的服务器。接下来介绍向服务器发送 HTTP 请求阶段,HTTP 请求分为三个部分:TCP 三次握手、http 请求响应信息、关闭 TCP 连接。

7,dns是哪一层协议,dns是怎么工作流程的?

DNS协议位于OSI模型的应用层

7,viewconther有个属性NSTimer,在子线程里创建NSTimer,并间隔2s执行,并加入当前runloop,在主线程是对NSTimer能否释放掉吗

经过测试,没有释放,释放不掉

@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(@"定时器计时中");
}
- (void)dicClickEvent {
    NSLog(@"------");
}

@end

结论是可以销毁的

9,讲讲runloop相关技术

链接

10,崩溃日志怎么做到实时上传的,用nsurlcontent

1,NSURLConnection 同步等待 Crash 日志上传
2,启用后台进程上传 Crash 日志
其实最理想的日志上传,是将上传的 request 放到另一个不同的进程,那么即使 App 又发生闪退,也不会影响到另一个进程代码的执行。

问题是,iOS app 都处于 sandbox 环境下,系统不允许代码 fork 一个新进程。

幸运的是,从 iOS 8 开始,系统对 NSURLSession 新增了一个 background session 特性。这个特性允许 NSURLSession 将网络请求放入到一个单独的进程中执行。我个人感觉,这个特性设计,原本是为了增强某些 App 后台下载音视频等资源的体验。我实际测试下来,发现不管下载或者是上传,我们都可以将网络请求放入另一个进程。代码也很简单,比如我写一段如下的测试代码:


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之前做了什么操作?你做了哪些优化点

Pre-mian 大概过程主要分为:Load dylibs、Rebase、Bind、Objc、Initializers 这几个步骤。

当我们点击 App 图标,内核就开始做启动程序的初始化,然后交给 dyld(The Dynamic Link Editor,动态链接器);dyld 首先会读取镜像文件,然后递归的查找动态库,利用 ImageLoader(镜像加载器) 来将其加载到内存中,但是由于 ASLR 的特性,这里需要 Rebase/Bind 修复镜像中的资源指针,来指向正确的地址;然后 dyld 会通知 Runtime:ImageLoader 已经将对应的镜像加载到内存,这个时候 Runtime 会调用 map_image 去解析和处理该镜像资源(譬如注册 Objc 类、处理 category 等);接下来再调用 load_image,遍历调用类的 load 方法、调用C++的构造函数属性函数、创建非基本类型的C++静态全局变量等等。
上面的文字可能比较生涩难懂, 简单讲:

加载自动链接的动态库,并先后执行动态库中的2、3项。
执行 +load 方法
执行 C++ static initializers and C/C++ attribute(constructor) functions 。
通过上面一段简单的叙述,我们大概了解知道mian之前的过程, 也就有了优化的方向.

1,优化 Load Dylibs Image 过程
尽量减少动态库的依赖和合并一些动态库,减少 ImageLoading 加载镜像的数量;不过这里一般不是 App 的瓶颈,这里只需要平时需要注意项目中不要依赖太多动态库就可以了。

2,优化 Rebase/Bind 过程
这里主要由于 ASLR 特性,需要修复镜像中的资源指针,来指向正确的地址;这里一般不太好优化,只能说尽量将项目中不用的类给删除,减少类数量和 selector 数量。

3,优化 Objc 过程
这个过程主要是:注册 Objc 类,处理 category,将 category 中的方法属性协议等插入到本类中去,这块一般也没什么优化的空间。
4,优化 Initializers 过程
这个过程主要做初始化工作,相对其它过程会比较耗时,这里我们需要注意以下操作的耗时,去分析对应操作有没必要在 Pre-main 这个阶段去处理,是否可以在程序启动完成之后再处理:
Load 函数中的操作
C++的构造函数属性函数
C++静态全局变量
通过上面几个步骤,我们主要能优化的点如下:
减少动态库的依赖
减少 Objc 类和方法
减少 C++的构造函数
减少 C++静态全局变量
减少 +load 函数数量, 并避免做耗时操作

11,当一个页面内存泄漏了,你是怎么处理的?

常用的内存检查工具

Instruments

Instruments 是 Xcode 自带的工具集合,为开发者提供强大的程序性能分析和测试能力。

它打开方式为:Xcode → Open Developer Tool → Instruments。其中的 Allocations、Leaks 和 Zombies 功能可以协助我们进行内存泄漏检查。

• Leaks:动态检查泄漏的内存,如果检查过程时出现了红色叉叉,就说明存在内存泄漏,可以定位到泄漏的位置,去解决问题。此外,Xcode 中还提供静态监测方法 Analyze,可以直接通过 Product → Analyze 打开,如果出现泄漏,会出现“蓝色分支图标”提示。

• Allocations:用来检查内存使用/分配情况。比如出现“循环加载引起内存峰值”的情况,就可以通过这个工具检查出来。

• Zombies:检查是否访问了僵尸对象。

Instruments 的使用相对来说比较复杂,你也可以通过在工程中引入一些第三方框架进行检测。

13,讲讲http,https的区别,tcp,udp,为什么tcp要三次链接,网络层里有哪些协议?网络层是做了什么工作的

HTTPS(Hypertext Transfer Protocol Secure:超文本传输安全协议)是一种透过计算机网络进行安全通信的传输协议。HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。

HTTPS 默认工作在 TCP 协议443端口,它的工作流程一般如以下方式:

1、TCP 三次同步握手
2、客户端验证服务器数字证书
3、DH 算法协商对称加密算法的密钥、hash 算法的密钥
4、SSL 安全加密隧道协商完成
5、网页以加密的方式传输,用协商的对称加密算法和密钥加密,保证数据机密性;用协商的hash算法进行数据完整性保护,保证数据不被篡改。
HTTP 与 HTTPS 区别
HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好。
使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy 和 GlobalSign 等。
HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。
http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
HTTPS 其实就是建构在 SSL/TLS 之上的 HTTP 协议,所以,要比较 HTTPS 比 HTTP 要更耗费服务器资源。


image.png
image.png

为什么 TCP 需要三次握手?

原因一:防止重复连接
三次握手的主要原因是为了防止旧的重复连接引起连接混乱问题
比如在网络状况比较复杂或者网络状况比较差的情况下,发送方可能会连续发送多次建立连接的请求
如果 TCP 握手的次数只有两次,那么接收方只能选择接受请求或者拒绝接受请求,但它并不清楚这次的请求是正常的请求,还是由于网络环境问题而导致的过期请求,如果是过期请求的话就会造成错误的连接
所以如果 TCP 是三次握手的话,那么客户端在接收到服务器端 SEQ+1 的消息之后,就可以判断当前的连接是否为历史连接,如果判断为历史连接的话就会发送终止报文(RST)给服务器端终止连接;如果判断当前连接不是历史连接的话就会发送指令给服务器端来建立连接
原因二:同步初始化序列化
TCP 为了保证在不稳定的网络环境中构建一个稳定的数据连接,它就需要一个“序列号”字段来保证自己的稳定性
而这个序列号的作用就是防止数据包重复发送,以及有效的解决数据包接收时顺序颠倒的问题
那么在建立 TCP 连接时就需要同步初始化一个序列号来保证 TCP 的稳定性,因此它需要执行以下过程:
首先客户端发送一个携带了初始序列号的 SYN 报文给服务器端
服务端接收到消息之后会回复一个 ACK 的应答报文,表示客户端的 SYN 报文已被服务端成功接收了
而客户端收到消息之后也会发送一个 ACK 给服务端,服务器端拿到这个消息之后,我们就可以得到一个可靠的初始化序列号了
而如果是两次握手的话,就无法进行序列号的确认工作了,因此也就无法得到一个可靠的序列号了,所以 TCP 连接至少需要三次握手

1.网际协议(IP)
IP是因特网使用的一种最为广泛的网络层协议,它的主要功能是将数据包从源地址传输到目的地址,同时负责数据包的路由选择、分段和重组等功能。
2.互联网控制报文协议(ICMP)
3.地址解析协议(ARP)
4.网际组管理协议(IGMP)
5.网络地址翻译(NAT)
网络层的主要任务是实现网络互连,进而实现数据包在各网络之间的传输。
要实现网络层任务,需要解决以下主要问题:
网络层向运输层提供怎样的服务(“可靠传输”还是“不可靠传输”)
网络层寻址问题
路由选择问题
因特网是目前全世界用户数量最多的互联网,它使用TCP/IP协议栈。
由于TCP/IP协议栈的网络层使用网际协议IP,它是整个协议栈的核心协议,因此在TCP/IP协议栈中网络层常称为网际层。


image.png
上一篇下一篇

猜你喜欢

热点阅读