-
网络分几层,每层都是干什么的。
[应用层]
支持网络应用,应用协议仅仅是网络引用的一个组成部分,运行在不同主机上的进程则使用应用层协议进行通信。主要的协议有:http,ftp,telnet,smtp,pop4[传输层]
负责为信源和信宿提供应用程序进程的数据传输服务,这一层上主要定义了两个传输协议,传输控制协议TCP,和用户数据报协议UDP【格式化信息流+提供可靠传输】[网络层]
负责将数据包独立地从信源发送到信宿,主要解决路由选择,拥塞控制和网络互连等问题[链路层]
负责将IP数据报封装成合适在物理网络上传输的帧格式并传输,或将物理网络接收到的帧解封,取出IP数据报交给网络层【将数据流发给网络层】[物理层]
负责将比特流在节点间传输,即负责物理传输。该层的协议即与链路层有关也与传输介质有关【其实就是通信设备相关】
-
一个请求从客户端发送到服务器,都经过什么过程
- 域名解析
- 发起TCP的3次握手
- 建立TCP连接后发起http请求
- 服务器响应http请求,客户端得到响应数据
- 客户端对数据进行解析
-
HTTP请求方法都有哪些
- GET,HEAR,POST,PUT,DELETE,OPTIONS,TRACE
-
事件响应链相关
- hit-test responder
- touch如何传递到view和gesture recognizer
- 通过hit-test判断哪个view被触摸,这一层会考虑到(userInteractionEnable,hidden,alpha)
- 当touch状态发生改变的时候,应用调用自己的sendEvent,进而调用window的sendEvent:,windown通过掉用下面的方法来掉用合适的touch方法
- 当touch第一次出现时,会考虑mutipletouchEnable和exclusiveTouch,如果满足条件,则
- touch被传递给对应的view的gesture recognizer
- 该touch被传递给对应的view
- 如果一个gesture被检测出来,对于和这个gesture recognizer有关的touch
- touchesCacelled:forEvent: 会被掉用,touch不再传递给对应的view
- 如果这个touch还跟其他gesture recognizer有管理,其他的都直接设置为fail
- 如果一个gesture recognizer失败了,那么touch不会再传递给它,但是它们还会传递给对应的view
- 如果一个touch将被传递给一个view,但是这个view没有合适的处理touch的方法,responder会顺着responder chain 找到一个合适的并传递到那里
- 当touch第一次出现时,会考虑mutipletouchEnable和exclusiveTouch,如果满足条件,则
-
UI相关
- 转场动画 1.
-
数据结构相关:链表,线性表,二叉树结构
[链表]
:是一种线性表,但不是按线性的顺序存储数据,而是在每个节点里存了下一个节点的指针。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另外一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表的时间复杂度分别是O(logn)和O(1)[线性表]
:由N个数据元素组成的优先序列[二叉树]
:就是每个节点最多有两个子树的树结构【二叉树常被用于实现二叉查找树和二元堆积】
-
常用三方库的实现 1.
-
runloop,gcd,block,runtime
-
[runloop]
- runloop 其实就是个事件循环,能够让线程能够随时处理事件而不退出
- 每个线程都会有一个runloop,但是runloop。但是如果我们不去主动获取runloop,那它就一直不会有(获取runloop:CFRunloopGetMain,CFRunloopGetCurrent)
- runloop的创建是发生在第一次获取时,销毁发生在线程结束时
- 我们开发中主要用到的是Runloop的Mode
- 对外暴露的Mode有:RunloopDefaultMode,RunloopCommonMode
- RunloopDefaultMode:app平时所处的状态
- TrackingRunloopMode:ScrollView滑动时候的状态的Model
- UIInitializationRunLoopMode:刚启动APP时进入的第一个Mode,启动完成后将不再使用
- GSEventReceiveRunLoopMode:接受系统时间的内部Mode,通常用不到
- CommonMode:组合,所有RunloopMode的组合,加入这个Mode,则会向一个给每个Mode都加
- 常见问题就是:我们给time加入了defaultMode,所以,tableView滑动的时候,它不计时
- 可用于:监控runloop的状态,然后在他处于defaultMode的时候,做些异步的事情
- Runloop的内部逻辑
-
[gcd]
- GCD主要是和Block配合使用,进行多线程编程【GCD使用一套C接口,调用的系统底层的方法实现多线程的】
- 常用方法:
- dispatch_async,dispatch_sync,dispatch_group_async,dispatch_group_notify,dispatch_barrier_async,dispatch_apply,dispatch_after,dispatch_once,dispatch_wait[以及请求依赖]
- 需要注意的dispatch_sync【这个方法,是同步进行,所以,会等待当前线程的方法运行完毕后,再执行。如果我们在当前线程+执行sync方法,则会阻塞线程】
- 串行+并行 同步+异步
- 全局队列,不同的优先级别:background,low,default,high
- dispatch_barrier_async:可用于读写分离,在写的时候,执行dispatch_barrier_async,可保证之前的都读完了,才执行写的操作。
-
[block]
- 使用的时候需要注意:循环引用
- __block 关键词:使用block后,它会将修饰的变量的指针地址,也放入block结构中,然后当在block中对其进行修改的时候,就可以正确响应到相关对象
- 三种block:全局block,堆block,栈block
- 全局block:没有引用任何局部变量的,其实就是全局block
- 因为ARC的开启,现在基本都是堆block。因为我们有默认的__strong修饰符。
- 栈block,其实就是引用了栈上的变量。。
-
[runtime]
- 需要理解objc_msgSend(id,sel)【可参考:方法调用流程】
- Objective-C Runtime 运行时之三:方法与消息
-
-
常用sql语句
-
常用设计模式KVO,MVC,MVVM
-
socket[传输层上面封装的套接字接口,方便应用层的使用】
-
tpc,udp的区别
- TCP(传输控制协议) 面向连接,UDP(用户数据报协议)面向非连接
- TCP是可靠的,UDP不可靠
- TCP传输大量的数据,UDP少量数据
- TPC速度慢,UDP速度快
- 为什么说TCP可靠,UDP不可靠
- TCP,TCP必须要经过三次会话才能建立连接,并且会要求计算机成功接受到数据的时候,发送一个确认(ACK),如果未在某个时限内收到相应的ACK,则会重新发送数据包。【如果网络阻塞,这种重新发送会导致数据包重复,但是,接收计算机可使用数据包的序号来确定它是否为重复数据包,并在必要时丢弃它】
- UDP,UDP不必与对方先建立连接,不管对方是什么状态,就直接发送【类似于手机短信】
-
调用方法的过程
- 将代码转化为objc_msgSend
- msgSend干了什么事
-
首先绑定对象+SEL
-
会从对象所属的类找到相应的方法实现
- 如何找到方法的实现
- 在对象所属的这个类方法分发表中找到方法的selector,如果没有找到selector,则根据指向父类的指针找到其父类,并在父类的分发表中找到方法的selector,直到找到NSObject类【如果是类方法,则根据isa,从元类中找】
- 找到selector,函数就会找到具体的实现入口IMP,然后传入相应的参数,来执行方法的具体实现
- 如果没有找到selector,则会走消息转发流程
- 如何找到方法的实现
-
调用方法实现,并将接受者对象及方法的所有参数传给它
-
最后,它将实现返回的值作为它的自己的返回值
-
-
三次握手
- 客户端向服务器发起SYN包(同步序列编号),客户端进入SYN_SEND状态,等待服务器确认
- 服务器接收到客户端的SYN包,对其进行确认ACK,并向客户端发送SYN包,即:SYN+ACK,此时服务器进入SYN_RECV状态
- 客户端收到服务器的SYN+ACK包,并向服务器发送确认包ACK,此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手
-
什么是isa
- isa指向的是元类,元类其实就是类对象的objc_class结构体,里面存储了相关的类方法
- 元类的isa,最终指向的是自己,形成闭环
-
IMP,Selector,Method
- IMP:方法的实现地址【指针】
- Selector:方法选择器
- Method:保存了Selector+IMP
-
Load方法
- 调用顺序:父类的load——子类的load——分类的load 【注意,我们不需要使用[super load],系统自己会调用】
-
initialize方法
- 只有我们显示的调用了[super initialize],父类的方法才会调用
- 每个类的initialize只会调用一次,分类中如果也有实现,是不会被再次调用的
-
Copy
- 要支持copy操作,需要实现NSCoping协议的copyWithZone方法
- copy是不可变的拷贝操作,mutableCopy是可变操作
-
NSCoding[归档操作]
- 需要实现NSCoding协议,initWithCoder encodeWithCoder
-
讲讲你对Hybrid App的理解,他与Native App之间的优缺点。
[Hybrid App]
- 使用PhoneGap这类的中间件,以webView为用户界面,用javascript作为基本逻辑,再通过中间件访问底层API,进行app开发,比较依赖于webView的性能
- 使用Xamarin这种非官方语言工具,然后转换打包成原生应用
- 在原生应用的基础上,嵌入WebView,但整体框架还是原生应用提供
- 特性:跨平台(热修复),对于熟悉web的人员来说,相对开发成本低
[Native App]
- 原生语言开发
- 特性:性能,交互较好,但不支持跨平台,不方便进行热修复
[React Native]
- 使用JSX来生成HTML或者React标签
- UI生成:OC加载JS,然后进行解析映射,最后生成UI
- 事件:然后通过javascriptcore与OC进行交互调用
-
iOS 代码混淆
[方法名混淆]
- 外部创建一个sqliteDB,里面放入一些我们需要混淆的名字+要混淆成什么样子【或者是,我们随机生成混淆,然后DB中放入我们混淆后的方法名,方便我们对比查找】
- Xcode设置,build的时候,运行 .sh 脚本
- sh脚本:1.查询DB文件,找出需要混淆的内容
- 将这些内容使用#define的形式写入一个.h文件【实现文本替换】
- 在.pch文件中引用这个.h文件。
- 这样之后有人反编译我们的app,看到的就是我们混淆后的代码了
-
KVC实现原理
- [user setValue:@"zhangsan" forKey:@"name"]
- 上面代码被转为
SEL sel = sel_get_uid ("setValue:forKey:"); IMP method = objc_msg_lookup (site->isa,sel); method(site, sel, @"sitename", @"name");
- 就是先先找到setValue:forKey的sel,然后结合isa,找到具体的类+方法实现的接口,然后进行调用
-
KVO的实现原理
- 这块实现原理有部分类似于KVC,当我们
[addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil]
的时候,应该是先获取到实例的isa,然后在获取到要设置的属性,然后在执行下面的重新指向子类的操作 - 当我们将实例的某个属性注册到观察者中的时候
- 系统会生成一个当前实例所属类的子类
- 在子类中重写set方法,在其中加入一些KVO用到的方法
- 将当前实例指向新创建的子类
- 然后,当我们调用set方法的时候,就会触发KVO
- 这块实现原理有部分类似于KVC,当我们
-
OC中main.m方法解释
int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil,NSStringFromClass([AppDelegate class])); } }
[@autoreleasepool]
:将整个app放入一个autoreleasepool中,当app关掉后,释放所有内存[UIApplicationMain(argc, argv, nil,NSStringFromClass([AppDelegate class]))]
:第三个参数会初始化一个UIApplication对象,用来接收事件(默认nil,会使用默认的UIApplication)
-
我们可以指定自己的UIApplication,例如下面[当接收到系统事件的时候,就会打印相应的Log]:
class MyApplication: UIApplication {
-(void)sendEvent(event: UIEvent!) {
[super sendEvent:event];
Log("Event sent: %@",event);
}
}
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv,NSStringFromClass([MyApplication class]),NSStringFromClass([AppDelegate class]));
}
}
-
[UIApplicationMain(argc, argv, nil,NSStringFromClass([AppDelegate class]))]
:第四个参数是指定由哪个类实现应用的委托AppDelegate【其实就是这些方法: didFinishLaunching 或者 didEnterBackground】 -
编译流程
- 确定标准库+头文件的位置
- 确定依赖关系(确定编译顺序,例如A依赖B,那么,就需要先编译B)
- 头文件的预编译【但不会编译#define】,保证只编译一次,而不是每次都重新编译
- 预处理【替换源码中的宏文件】
- 编译【将源码转为汇编,再有汇编转为机器码】
- 链接【将外部函数添加到可执行文件,例如静态库】
- 安装【将可执行文件保存到用户指定的目录】
- 操作系统连接【要求让操作系统记录程序的元数据】
- 生成安装包【将之前的可执行文件,打包为可执行的安装包】
- 动态链接【在运行期间,加载需要的链接,例如dylib,dll】
-
UIView与CALayer
- 所有的Viw,都是有一个底层的layer来驱动的,由Layer提供绘制+现实
- VIew的尺寸样式也是Layer提供的。
- View跟Layer都有树状层级结构,有subLayers,subView。但layer比View多了个AnchorPoint属性(旋转的时候会用到)
- View是Layer的CALayerDelegate,View的现实内容有内部的CALayer的display
- CALayer,修改属性,支持隐式动画(属性有标记animatable的),再给UIView的layer做动画的时候,View作为layer的代理,View通过调用actionForLayer:forKey: 方法,让Layer做相应的动画action(动画行为)
- CALayer内部维护了3个tree
- presentlayer tree(动画树):做动画的时候,其实是presentlayer的属性值[所以,做完动画后,View又会回到原位]
- modeLayer tree(模型树):最终显示在界面上的,其实就是这个
- Render tree (渲染树)
- View可以处理事件,Layer不可以
- 修改View的属性,是不会有隐式动画的,但是Layer有,因为View默认禁止了layer的动画,在animation block中又将其启用
-
scrollView 与全屏返回的手势有冲突怎么办?
- 需要给scrollView加个分类,然后实现UIGestureRecognizerDelegate
- 实现这个方法:- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
- 这个方法指明:如果有多个手势同时触发,是否同时识别另外一个手势
- 如果返回YES,则会同时识别两个手势
- 如果返回NO,则只识别当前手势
-
swift
- 相关内容:https://nicolastinkl.gitbooks.io/maker/content/swift_tips.html
- swift3 柯里化被移除了,不再支持
[柯里化:把接受多个参数的方法变换成接受 第一个参数的方法,并且返回接受余下的参数并且返回结果的新方法.]
- swift中并没有main.m文件了,而是在APPDelegate文件中,有这么一句:
[@UIApplicationMain]
- 这其实就是将被标注的类作为委托,去创建一个 UIApplication 并启动整个程序。在编译的时候,编译器将寻找这个标记的类,并自动 插入像 main 函数这样的模板代码
- 如果你不想要这个标签,也可以自己新建个main.swift文件,来做OC中main文件所做的事情
- swift为了追求性能,一般情况下,是不会做些运行时的事情。swift的类型,成员变量,方法是在编译的时候就确定的,不需要再经过一次查找就可以直接使用
[@objc]
关键词- 如果我们要使用objc的方法或特性,来调用纯swift的类型的时候,就会提示找不到所需要的运行时信息。
- 这个时候,就需要我们手动加上@objc关键字
- 或者将swift的类,继承自NSObject,这样,就会自动将不是private的成员,添加@objc关键字
-
相关文章