设为首页收藏本站

安徽论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 16181|回复: 0

iOS知识汇总

[复制链接]

1

主题

0

回帖

3

积分

新手上路

Rank: 1

积分
3
发表于 2021-11-17 20:02:25 | 显示全部楼层 |阅读模式
网站内容均来自网络,本站只提供信息平台,如有侵权请联系删除,谢谢!
1.网络

1.网络七层协议有哪些?

物理层:
主要功能:传输比特流;
典型设备:集线器、中继器;
典型协议标准和应用:V.35、EIA/TIA-232
数据链路层:
主要功能:保证无差错的疏忽链路的
典型设备:交换机、网桥、网卡
典型协议标准和应用:802.2、802.3ATM、HDLC、FRAME RELAY
网络层:
主要功能:路由、寻址
典型设备:路由器
典型协议标准和应用:IP、IPX、APPLETALK、ICMP
传输层:
主要功能:端到端控制
典型设备:网关
典型协议标准和应用:TCP、UDP、SPX
会话层:
主要功能:会话的建立和结束
典型设备:网关
典型协议标准和应用:RPC、SQL、NFS、X WINDOWS、ASP
表示层:
表示层相当于一个东西的表示,表示的一些协议,比如图片声音视频MPEG等
主要功能:数据表示、压缩和加密
典型设备:网关
典型协议标准和应用:ASCLL、PICT、TIFF、JPEG|MPEG
应用层:
主要功能:应用接口、应用程序
典型设备:网关
典型协议标准和应用:TELNET、FTP、HTTP
2.Http 和 Https 的区别?Https为什么更加安全?

区别:

  • HTTP是明文传输, https是基于SSL进行的加密传输、有身份验证环节,更加安全
  • HTTP默认端口号是80,HTTPS默认端口号是443
  • HTTPS需要CA证书,极少免费。
安全的原因:HTTPS是基于SSL(安全套接字)和TLS(传输层安全),对网络进行加密处理,保障数据的完整性,更加安全。
3.HTTPS的连接建立流程

HTTPS为了兼顾安全与效率,同时使用了对称加密和非对称加密。在传输中涉及到3个密钥:服务端到公钥和私钥用于非对称加密,客户端生成的随机密钥用来进行对称加密
如图HTTPS连接过程大致分为8步

  • 客户端访问HTTPS连接:客户端把安全协议版本号、客户端支持的加密算法列表、随机数C发给服务端。
  • 服务端发送证书给客户端:服务端接受密钥算法配件后,会和自己支持的加密算法列表进行对比,如果不符合则断开连接。否则会在该算法列表中选择一种对称算法(如AES)、一种公钥算法(如具有特定密钥长度的RSA)和一种MAC算法发给客户端。服务端有一个密钥对(公钥和私钥)用来进行非对称加密使用,服务端保存着私钥,公钥可以发送给任何人。在发送加密算法的同时还会把数字证书和随机数S发送给客户端
  • 客户端验证server证书:客户端会对server公钥进行检查,验证其合法性,如果公钥有问题,那么HTTPS传输就无法继续。
  • 客户端组装会话密钥:如果公钥合格,那么客户端就会用服务端公钥来生成一个前主密钥(Pre-Master Secret,PMS),并通过该前主密钥和随机数C、S来组装成会话密钥
  • 客户端将前主密钥发送给服务端:通过服务端端公钥对前主密钥进行非对称加密,发送给服务端
  • 服务端通过私钥解密得到前主密钥:服务端接受到加密信息后,用私钥解密得到前主密钥。
  • 服务端组装会话密钥:服务端通过前主密钥和随机数C、S来组装会话密钥。至此,服务端和客户端都已经知道了用于此次会话都都主密钥。
  • 数据传输:客户端收到服务器发送来的秘文,用客户端密钥对其进行对称解密,得到服务器发送的数据。同理,服务端收到客户端发送的秘文,用服务端密钥进行对称解密得到客户端发送的数据。
4.解释一下 三次握手 和 四次挥手




    • 三次握手:

      • 客户端向服务端发送SYN同步报文
      • 服务端收到SYN同步报文后,会返回给客户端SYN同步报文和ACK确认报文
      • 客户端向服务端发送ACK确认报文,此时客户端和服务端的连接正式建立

    • 建立连接:

      • 这个时候客户端就可以通过HTTP请求报文向服务端发送数据
      • 服务端收到客户端的请求之后,向客户端回复HTTP响应报文

    • 四次挥手:当客户端和服务端的连接想要断开的时候,要经历四次挥手的过程,客户端和服务端双方都要知道结束了。

      • 先由客户端向服务端发送FIN结束报文
      • 服务端会返回给客户端ACK确认报文。此时,由客户端发起的断开连接已经完成。
      • 服务端会发送给客户端FIN结束报文和ACK确认报文。
      • 客户端会返回ACK确认报文到服务端,至此,由服务端方向的断开连接已经完成。


5.TCP 和 UDP的区别

TCP:面向连接、传输可靠(保证数据正确性、保证数据顺序),用于传输大量数据(流模式),速度慢、建立连接需要开销较多(时间、系统资源)
UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快
6.Cookie和Session

Cookie:cookie主要用来记录用户状态,区分用户,状态保存在客户端。cookie功能需要浏览器支持。如果浏览器不支持cookie(如大部分手机中的浏览器)或者把cookie禁用了,cookie功能就会失效。

  • cookie的使用:首次访问某网站时,客户端会发送一个HTTP请求到服务器,服务器发送一个HTTP响应到客户端,其中包含set-cookie头部;客户端再发送HTTP请求时,包含cookie头部,服务端返回HTTP响应到客户端;隔断时间再访问时,客户端会直接发包含cookie头部的http请求,服务端响应客户端
  • cookie的修改和删除:在修改cookie的时候,只需要新cookie覆盖旧cookie即可,在覆盖的时候,由于cookie具有不可跨域名性,主要name、path、domain需与原cookie一致。删除cookie也一样,设置cookie的过期时间为过去的一个时间点或者maxage=0即可。
  • cookie的安全:cookie的使用存在争议,因为它被认为是对用户隐私的侵害,并且cookie并不安全。http协议不仅是无状态的,而且是不安全的,使用http协议的数据使用明文在网络传播有被截获的可能。如果不希望cookie在http非安全协议中传输可以设置cookie的Secure属性为true,浏览器只会在https和ssl等安全协议中传输此类cookie。Secure属性并不能对cookie内容加密,因而不能保证却对安全。如果需要提高安全性,需要在程序中对cookie进行加解密。除了Secure属性,也可设置cookie为httponly,如果设置此属性,那么通过js脚本将无法读取到cookie信息,能有效防止XSS攻击(跨站脚本攻击)
Session:是服务端使用的 一种记录客户端状态的机制。使用上比cookie简单,响应的增加了服务器的存储压力。不同于cookie保存在客户端浏览器中,session保存在服务器上,客户端访问浏览器时,服务端把客户端信息以某种形式记录在服务器上,这就是session。客户端浏览器再次访问时只需要从该session 中查找该客户的状态就可以了。
当程序需要为某个客户端的请求创建session时,会先检索客户端的请求里是否包含session表示(称为sessionid)如果包含则说明之前已经为此客户端创建过会话,服务器就按标识把这个session检索出来使用,检索不到会新建一个。如果客户端请求不包含会话标识,服务端会创建一个session并生成关联的会话id,这个sessionid将在本次响应中返回给客户端保存。

  • cookie和session的区别

    • cookie存储在客户端浏览器上,session数据存在服务器上
    • cookie相比session不是很安全
    • session会在一定时间内保存在服务器上,当访问增多会占用服务器性能,考虑减轻服务器性能可以使用cookie
    • 单个cookie保存数据不能超过4k,很多浏览器都限制一个站点最多保存20个。而session没有限制
    • 所以可以将登陆等重要信息存放session,其他如果需要保留可以放在cookie中

7.DNS是什么?

域名系统:domain name system, 用于 主机名到ip地址到转换。
因特网上的主机可以用多种方式标识,比如主机名或ip地址。主机名比如www.baidu.com 这种方式便于人们记忆和接受,但这种长度不一没有规律的字符串不方便路由器处理。路由器比较热衷于 定长的有清晰层次结构的ip地址。为了这种这两种方式,我们需要一种能进行主机名到ip地址转换到服务,这就是域名系统DNS。
DNS是一个由分层的DNS服务器实现的分布式数据库。一个使得主机能够查询分布式数据库的应用层协议: DNS服务器通常是运行BIND软件的UNIX机器,DNS协议运行在UDP上使用53号端口。DNS通常是由其他应用层协议所使用的,包括HTTP、SMTP等。其作用是将用户提供的主机名解析为ip地址。DNS的一种简单设计就是在因特网上只使用一个DNS服务器,该服务器包含所有的映射。很明显这种设计有很大问题:单点故障:如果该DNS服务器崩溃全世界网络随之瘫痪;通信容量:单个DNS服务器必须处理所有的DNS查询;远距离的集中式数据库:单个DNS服务器必须面对所有用户,距离过远会有严重时延。维护:该数据库过于庞大,还需要对新添加的主机频繁更新。所以DNS被设计成了一个分布式、层次数据库。
8.DNS解析过程

www.163.com为例:

  • 客户端打开浏览器,输入一个域名。比如输入www.163.com,这时,客户端会发出一个DNS请求到本地DNS服务器。本地DNS服务器一般都是你的网络接入服务器商提供,比如中国电信,中国移动。
  • 查询www.163.com的DNS请求到达本地DNS服务器之后,本地DNS服务器会首先查询它的缓存记录,如果缓存中有此条记录,就可以直接返回结果。如果没有,本地DNS服务器还要向DNS根服务器进行查询。
  • 根DNS服务器没有记录具体的域名和IP地址的对应关系,而是告诉本地DNS服务器,你可以到域服务器上去继续查询,并给出域服务器的地址。
  • 本地DNS服务器继续向域服务器发出请求,在这个例子中,请求的对象是.com域服务器。.com域服务器收到请求之后,也不会直接返回域名和IP地址的对应关系,而是告诉本地DNS服务器,你的域名的解析服务器的地址。
  • 最后,本地DNS服务器向域名的解析服务器发出请求,这时就能收到一个域名和IP地址对应关系,本地DNS服务器不仅要把IP地址返回给用户电脑,还要把这个对应关系保存在缓存中,以备下次别的用户查询时,可以直接返回结果,加快网络访问。
2.多线程

1.进程与线程分别是什么意思?

进程是系统中正在运行的程序,就是一段程序的执行过程,我们可以理解为手机上一个正在运行的app。进程是操作系统分配资源的基本单元。每个进程之间相互独立,每个进程均运行在其专用且受保护的内存空间内,拥有独立运行所需的全部资源。
线程是程序执行的最小单元,是进程中的一个实体。一个进程想要执行任务必须至少有一条线程。应用程序启动时,系统会默认开启一条线程,也就是主线程。
进程和线程的关系:线程是进程的执行单元,进程中的所有任务都是在线程中执行的;线程是CPU分配资源和调度的最小单元;一个程序可以对应多个进程,一个进程至少有一条线程;同一个进程内的线程共享进程资源。
2.什么是多线程?
一个进程至少有一个线程,如果有多个线程在执行就是多线程。多线程的实现原理,如果是单核CPU,则是CPU在多个线程之间快速切换,造成多个线程同时执行的假象。如果是多核CPU,就真的可以实现多个线程同时执行。多线程的目的是为了同步完成多项任务,通过提高系统资源的利用率来提高工作效率。
3.多线程的优点和缺点有哪些?
优点:能适当的提高程序的执行效率;能适当提高资源的利用率(CPU、内存利用率)
缺点:每个线程都有一定的开销,从而影响性能。不仅有创建时的时间开销,还有消耗内存。每个线程大约消耗1kb的内核内存空间,用于存储与线程有关的数据结构和属性,这块儿内存是联动内存,无法被分页。此外还占用一定的栈空间,默认主线程占1M,子线程占512k,注意完整的栈不会被立即创建,实际消耗的栈空间随着使用而增加,如果开启大量线程,会占用大量内存空间降低程序性能;线程越多CPU调度线程的开销就越大。程序设计更加复杂比如线程之间的通信多线程的数据共享等。
4.多线程的 并行 和 并发 有什么区别?
并行:充分利用计算机的多核,在多个线程上同步进行
并发:CPU快速切换线程,让人感觉在同步进行
5.iOS中实现多线程的几种方案,各自有什么特点?
NSThread 面向对象,需手动创建线程,但不需要手动销毁。自线程间通信很难;
GCD C语言,充分利用了设备的多核,自动管理线程生命周期。比NSOperation高效;
NSOPeration 基于GCD封装,更加面向对象。比GCD多了一些功能,比如设置最大并发数,可以监控任务状态,轻松设置任务依赖等。
6.多个网络请求完成后如何执行?
<blockquote>

  • 使用GCD的任务组
创建一个任务组 dispatch_group_t,每次网络请求前先进入组 dispatch_group_enter,请求回调后再离开组 dispatch_group_leave。进入和离开必须成对使用,否则组会一直存在。当所有enter都leave之后,会执行组通知dispatch_group_notify的block。

  • 使用GCD的信号量
信号量是基于计数器的一种多线程同步机制。如果信号计数大于1,计数-1返回,程序继续执行。如果计数为0则等待。
增加信号量 dispatch_semaphore_signal(semaphore)为计数+1操作。dispatch_semaphore_wait(sema,DISPATCH_TIME_FOREVER)为设置等待的时间,这里设置的是一直等待。
创建信号量为0,等待。等10个网络请求都完成了,信号量dispatch_semaphore_signal计数为1,然后计数-1返回。
ProtoBuf),如果可能建议使用 ProtoBuf。
如果请求的返回数据相同,可以使用 NSCache 进行缓存
使用断点续传,避免因网络失败后要重新下载。</p>网络不可用的时候,不尝试进行网络请求
长时间的网络请求,要提供可以取消的操作
采取批量传输。下载视频流的时候,尽量一大块一大块的进行下载,广告可以一次下载多个

  • 定位层面的优化
如果只是需要快速确定用户位置,最好用 CLLocationManager 的 requestLocation 方法。定位完成后,会自动让定位硬件断电
如果不是导航应用,尽量不要实时更新位置,定位完毕就关掉定位服务
尽量降低定位精度,比如尽量不要使用精度最高的 kCLLocationAccuracyBest
需要后台定位时,尽量设置 pausesLocationUpdatesAutomatically 为 YES,如果用户不太可能移动的时候系统会自动暂停位置更新
尽量不要使用 startMonitoringSignificantLocationChanges,优先考虑 startMonitoringForRegion:

  • 硬件检测优化
用户移动、摇晃、倾斜设备时,会产生动作(motion)事件,这些事件由加速度计、陀螺仪、磁力计等硬件检测。在不需要检测的场合,应该及时关闭这些硬件
5.Runloop

1.Runloop 和线程的关系?
一个线程对应一个runloop,主线程的runloop时默认开启的,子线程的runloop以懒加载的形式创建。runloop存储在一个全局的可变字典中,线程是key,runloop是value。
2.RunLoop的运行模式
runloop的运行模式一共有5种,runloop只会运行在一个模式下,要切换模式,就要暂停当前的模式,重新启动一个运行模式
- kCFRunLoopDefaultMode, App的默认运行模式,通常主线程是在这个运行模式下运行
- UITrackingRunLoopMode, 跟踪用户交互事件(用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他Mode影响)
- kCFRunLoopCommonModes, 伪模式,不是一种真正的运行模式
- UIInitializationRunLoopMode:在刚启动App时第进入的第一个Mode,启动完成后就不再使用
-GSEventReceiveRunLoopMode:接受系统内部事件,通常用不到
3.runloop内部逻辑?
实际上 RunLoop 就是这样一个函数,其内部是一个 do-while 循环。当你调用 CFRunLoopRun() 时,线程就会一直停留在这个循环里;直到超时或被手动停止,该函数才会返回。
内部逻辑:



    • 如果是 Timer 事件,处理 Timer 并重新启动循环,跳到第 2 步
    • 如果输入源被触发,处理该事件(文档上是 deliver the event)
    • 如果 RunLoop 被手动唤醒但尚未超时,重新启动循环,跳到第 2 步
    • 事件到达基于端口的输入源(port-based input sources)(也就是 Source0)
    • Timer 到时间执行
    • 外部手动唤醒
    • 为 RunLoop 设定的时间超时


    • 通知 Observer 已经进入了 RunLoop
    • 通知 Observer 即将处理 Timer
    • 通知 Observer 即将处理非基于端口的输入源(即将处理 Source0)
    • 处理那些准备好的非基于端口的输入源(处理 Source0)
    • 如果基于端口的输入源准备就绪并等待处理,请立刻处理该事件。转到第 9 步(处理 Source1)
    • 通知 Observer 线程即将休眠
    • 将线程置于休眠状态,直到发生以下事件之一
    • 通知 Observer 线程刚被唤醒(还没处理事件)
    • 处理待处理事件

  • Source1 :基于mach_Port的,来自系统内核或者其他进程或线程的事件,可以主动唤醒休眠中的RunLoop(iOS里进程间通信开发过程中我们一般不主动使用)。mach_port大家就理解成进程间相互发送消息的一种机制就好, 比如屏幕点击, 网络数据的传输都会触发sourse1。
    • Source0 :非基于Port的 处理事件,什么叫非基于Port的呢?就是说你这个消息不是其他进程或者内核直接发送给你的。一般是APP内部的事件, 比如hitTest:withEvent的处理, performSelectors的事件.
  • 简单举个例子:一个APP在前台静止着,此时,用户用手指点击了一下APP界面,那么过程就是下面这样的:
  • 我们触摸屏幕,先摸到硬件(屏幕),屏幕表面的事件会被IOKit先包装成Event,通过mach_Port传给正在活跃的APP , Event先告诉source1(mach_port),source1唤醒RunLoop, 然后将事件Event分发给source0,然后由source0来处理。
4.autoreleasePool 在何时被释放?

  • app启动后,苹果在主线程的runloop中注册了两个observer,其回调都是_wrapRunLoopWithAutoreleasePoolHandler()。
  • 第一个observer监听的事件是Entry即将进入loop,其回调内会调用_objc_autoreleasePoolPush()创建自动释放池,其order是-2147483647,优先级最高,保证创建释放池发生在其他所有回调之前。
  • 第二个observer监听了两个事件:beforewaiting准备进入休眠时调用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 释放旧的释放池病创建新池;Exit即将退出Loop时调用_objc_autoreleasePoolPop() 来释放自动释放池。这个 Observer 的 order 是 2147483647,优先级最低,保证其释放池子发生在其他所有回调之后。
  • 在主线程执行的代码,通常是写在诸如事件回调、Timer回调内的。这些回调会被 RunLoop 创建好的 AutoreleasePool 环绕着,所以不会出现内存泄漏,开发者也不必显示创建 Pool 了。

  • GCD 在Runloop中的使用?


  • GCD由 子线程 返回到 主线程,只有在这种情况下才会触发 RunLoop。会触发 RunLoop 的 Source 1 事件。
6.AFNetworking 中如何运用 Runloop?
AFURLConnectionOperation 这个类是基于 NSURLConnection 构建的,其希望能在后台线程接收 Delegate 回调。
为此 AFNetworking 单独创建了一个线程,并在这个线程中启动了一个 RunLoop:
right);  int diff = left - right;  if (diff > 1 || diff < -1) return flase;  return IsBalanced(pRoot->left) && IsBalanced(pRoot->right);}方法2:
left,left) && IsBalanced_1(pRoot->right,right)){    diff=left-right;    if(diff < 1 || diff >= -1){      depth = left > right ? left + 1 : right + 1;      return true;    }  }  return false;}bool IsBalancedTree(TreeNode* pRoot){  int depth = 0;  return IsBalanced_1(pRoot,depth);}</ul>8.字符匹配 & 字符去重的方法
给你一个仅包含小写字母的字符串,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小(要求不能打乱其他字符的相对位置)
1.什么叫字典序:26个英文字母的顺序
2.什么叫字符的相对位置,就是你只能删除重复的但是不能左右移动元素
我们来模拟下从第一个元素到最后一个元素的过程算法就出来了:
step1:c
step2:cb
step3:cba
step4:bac
step5:bacd
step6:acdb
按照我们的思维来写算法:定义一个结果集,依次遍历每个元素,结果集不存在就加入,如果存在就判断两个元素之间的元素有没有比当前元素小的,有的话就删掉之前的,比如bacdb,两个b之间有a比b小,所以要删掉之前的b,改成acdb
这里用另一个方法栈+标志来实现
说明:栈中存的元素满足两个条件之一就可以:1.元素都是递增的,2,当前元素在后续不在出现(过了这个村就没这个店了)
i) {                    memory2.put(stack.peek(), false);                    stack.pop();                } else {                    break;                }            }            //当循环完了后,当前节点肯定大于栈顶元素,入栈,记录该节点已经入栈了            stack.push(strArr);            memory2.put(strArr, true);        }    }    StringBuilder stringBuilder = new StringBuilder();    while (!stack.empty()) {        stringBuilder.insert(0, stack.pop());    }    return stringBuilder.toString();} public static void main(String[] args) {    String result = removeDuplicateLetters("bacacca");    System.out.println(result);}9.算法

1.时间复杂度 / 空间复杂度
<ul>时间复杂度
<ul>时间频度:一个算法执行所消耗的时间,从理论上是不能算出来的,必须上机运行测试才能知道,但我们不可能也没有必要对每个算法都上机测试。只需要知道哪个算法花费时间最多哪个算法花费时间最少就可以了。并且一个算法花费时间与算法中语句的执行次数成正比。哪个算法中语句执行次数多,它花费时间就多。一个算法中语句执行次数称为语句频度或时间频度,记为T(n)
时间复杂度:一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于0的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)) 称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。在各种不同算法中,若算法中语句执行次数为一个常数,则时间复杂度为O(1),另外,在时间频度不相同时,时间复杂度有可能相同,如T(n)=n2+3n+4与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n2).
按数量级递增排列,常见的时间复杂度有:
O(1)称为常量级,算法的时间复杂度是一个常数。
O(n)称为线性级,时间复杂度是数据量n的线性函数。
O(n²)称为平方级,与数据量n的二次多项式函数属于同一数量级。
O(n³)称为立方级,是n的三次多项式函数。
O(logn)称为对数级,是n的对数函数。
O(nlogn)称为介于线性级和平方级之间的一种数量级
O(2ⁿ)称为指数级,与数据量n的指数函数是一个数量级。
O(n!)称为阶乘级,与数据量n的阶乘是一个数量级。

它们之间的关系是:O(1)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
免责声明
1. 本论坛所提供的信息均来自网络,本网站只提供平台服务,所有账号发表的言论与本网站无关。
2. 其他单位或个人在使用、转载或引用本文时,必须事先获得该帖子作者和本人的同意。
3. 本帖部分内容转载自其他媒体,但并不代表本人赞同其观点和对其真实性负责。
4. 如有侵权,请立即联系,本网站将及时删除相关内容。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表