1.p、*p、&p以及指针常量和常量指针的区别
p是一个指针变量的名字,表示此指针变量指向的内存地址
*p表示此指针指向的内存地址中存放的内容,一般是一个和指针类型一致的变量或者常量
&p就表示编译器为指针变量p分配的内存地址
//这俩谁在前面先读谁
const(常量) int *(指针)p;常量指针
int *(指针)const(常量) p;指针常量
常量指针代表*p是不可变的,结合上面的解释,也就是指针指向的内存地址中存放的内容是不可变的,例如*p =d; // 不可以(d是已经声明过的整型)但指针本身的值是可变的:
p=&d; // 可以
指针常量代表p是不可变的,结合上面的解释,也就是指针变量指向的内存地址是不可变的,例如p=&d; // 不可以,*p =d; // 可以
2.block
block,它类似一个方法。而每一个方法都是在被调用的时候从硬盘到内存,然后去执行,执行完就消失,所以,方法的内存不需要我们管理,也就是说,方法是在内存的栈区。所以,block不像OC中的类对象(在堆区),它也是在栈区的。
1.使用block作为一个对象的属性,应使用关键字copy修饰,因为它在栈区,我们没办法控制他的消亡,当我们用copy修饰的时候,系统会把该 block的实现拷贝一份到堆区,这样我们对应的属性,就拥有的该block的所有权。就可以保证block代码块不会提前消亡。
2.在传递的时候,对于基本数据类型的外部变量来说,系统默认传递的仅仅是值,也就是说这个局部变量是不能修改的。如果想修改值,会使用__block来修饰这个变量。这样一来,系统在传递的时候,传的就是外部变量的地址,这样我们就可以修改值了。
3.对于对象类型,传递的是地址,同时默认对该对象进行了一次强引用。系统进行了强引用,而他又对该对象的内存管理袖手旁观,也就是说,他只做了强引用,但是没有做释放操作。这个时候就会造成内存泄漏。所以,我们在使用对象的时候,在MRC下,都会使用__block修饰,在ARC下,使用__weak修饰,这样一来,系统在传递的时候就不会对该对象进行强引用,避免了内存泄漏。还有一种情况,在代码块内部要用__storng来修饰对象,这样防止使用dispatch_after时,对象已经释放了
3.CPU、GPU、界面的逻辑处理关系以及界面卡顿的原因
iOS 的显示系统是由 VSync 信号驱动的,VSync 信号由硬件时钟生成,每秒钟发出 60 次
iOS 图形服务接收到 VSync 信号后,会通过 IPC 通知到 App 内,App 的 Runloop 在启动后会注册对应的 CFRunLoopSource 通过 mach_port 接收传过来的时钟信号通知,随后 Source 的回调会驱动整个 App 的动画与显示
App 主线程开始在 CPU 中计算显示内容,比如视图的创建、布局计算、图片解码、文本绘制等。随后 CPU 会将计算好的内容提交到 GPU 去,由 GPU 进行变换、合成、渲染。随后 GPU 会把渲染结果提交到帧缓冲区去,等待下一次 VSync 信号到来时显示到屏幕上
由于垂直同步的机制,如果在一个 VSync 时间内,CPU 或者 GPU 没有完成内容提交,则那一帧就会被丢弃,等待下一次机会再显示,而这时显示屏会保留之前的内容不变,也就是界面卡顿
4.copy assgin strong weak的区别
几者的区别有两点:1、是否会开辟新的内存 2、是否对原地址的引用计数有增加
总结:
只有copy会开辟新的内存;
只有strong会增加原地址引用计数(retain已经不再使用了,作用应与strong相同);
具体来讲,可变类型应使用strong,因为可变对象copy后会变成不可变对象,一旦进行增删等操作,可能会出现crash
不可变类型应使用copy,因为如果对不可变对象使用strong,使用一个可变对象对其赋值,当可变对象的数据产生变化时,不可变对象的数据同样会产生变化
浅拷贝 -- 指针拷贝,引用计数+1
深拷贝 -- 内容(空间)拷贝,引用计数不变
对于不可变对象,调用copy为浅拷贝,调用mutableCopy为深拷贝
对于可变对象,调用copy或者mutableCopy都是深拷贝,区别在于,copy为创建一个新的不可变对象,mutableCopy为创建一个新的可变对象(注意:容器内部的元素对象都是指针拷贝(如NSArray等))
5.AutoreleasePool 释放/原理
释放:自己创建的在[pool release]时释放;ARC下系统自己的在runloop(消息循环机制)结束时释放;
原理:NSAutoreleasePool实际上是个对象引用计数自动处理器,可以同时有多个,它的组织是个栈,由 AutoreleasePoolPage 以双向链表的方式实现的,对于每一个Autorelease,系统只是把该对象放入了当前的AutoreleasePoolPage栈中,当该pool被释放时,该pool中的所有对象会被调用AutoreleasePoolPage::pop方法会向栈中的对象发送 release 消息
6.iOS为什么必须在主线程中操作UI
因为UIKit不是线程安全的,所以如果不是在主线程中执行的话,有可能造成两个线程同时操作一个UI,造成崩溃
7.object 对象和类的内部布局
对象:对象是一个含有isa指针的结构体
类:类是一个指向objc_class结构体的指针(还有元类和根类)
NSNumber:Number是一个抽象的父类,它实现的方法主要是操作它的子类,这就是类簇,实际上是Foundation framework框架下的一种设计模式,它管理了一组隐藏在公共接口下的私有类
8.weak 自动设置为 nil 怎么实现的
对象销毁时(release),指针自动置为nil。nil是把一个对象的指针置为空 release是释放对象占据的内存
9.NSstring *str = @“abc”;这句涉及到几块存储区域
涉及到文字常量区(abc)和栈区(str指针指向abc,存储在栈区)
10.内存分配
栈区:编译器自动分配并释放,存放函数的参数值,对象的指针等,静态(编译器)和动态分配(alloca)
堆区:程序员分配和释放,对象都是在堆中,动态分配
全局静态区:全局变量和静态变量和常量分为初始化区和未初始化区
文字常量区:常量字符串,程序结束后由系统释放
程序代码区:存放函数的二进制代码
11.静态变量、静态常量、全局变量
静态变量:static修饰的变量,是一个私有的全局变量,static修饰的变量必须放在@implementation外面或方法中,它只在程序启动初始化一次
静态常量:static const修饰的变量是不可变的,如果需要定义一个时间间隔的静态常量,就可以使用const修饰,写在*之前,为指针不可变,写在*之后,为内容不可变
全局变量:extern修饰的变量,是一个全局变量。
12.UIView截图生成image
- (UIImage *)viewShot{
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
13.属性和成员变量
1、@property (属性)的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的
@property(属性) = ivar(成员变量) + getter + setter(存取方法)
LLVM(编译器)自动给生成了成员变量和getter、setter方法
2.@synthesize的作用?
@synthesize的作用就是让编译器为你自动生成setter与getter方法,另外可以指定与属性对应的实例变量,例如@synthesize myString= xxxx;
那么self.myString其实是操作的实例变量xxxx,而不是_myString了。
3.分类只能增加方法,不能增加成员变量?
分类中用@property定义变量,只会生成变量的getter,setter方法的声明,不能生成方法实现和带下划线的成员变量。有没有解决方案呢?有,通过运行时建立关联引用。
14.线程的几种状态
创建(alloc—线程对象加入内存)、开启(start—线程对象加入可调度线程池)、运行、阻塞(sleep/block—移出可调度线程池)、死亡(dead—移出内存)
15.OC语言的特性
OC作为面向对象的语言,具有三大特性:封装(隐藏对象的属性和方法实现,仅对外公开接口,控制程序中属性的读取修改权限)、继承(子类具有父类的各种属性和方法)、多态(子类重写父类的方法,产生不同的响应)。他具有静态语言的特性(如C++),又有动态语言的效率(动态绑定、动态加载)。
OC的动态特性:之所以叫做动态,是因为必须到运行时(run time)才会做一些事情。(动态特性的三个方面:动态类型、动态绑定、动态加载)
1.动态类型 (id类型)在编译器编译的时候不能被识别出,在运行时(run time),程序运行的时候才会根据语境来识别。静态类型,与动态类型相对。在编译的时候就能识别出来,明确的基本类型都属于静态类型。(int、NSString等)
2.动态绑定(关键词@selector)跳过编译,在运行时动态添加函数调用,运行时才决定调用什么方法,传递什么参数。
3.动态加载 根据需求动态地加载资源。
OC的优点:类别;在不创建继承类的情况下,给已经存在的类添加方法
16.socket套接字的格式 socket半包 粘包 怎么修改
格式:socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。socket的格式是 ip + port ,ip是用来标识互联网中的一台主机的位置,而port是用来标识这台机器上的一个应用程序,ip地址是配置到网卡上的,而port是应用程序开启的,ip与port的绑定就标识了互联网中独一无二的一个应用程序
粘包:1.须知:只有TCP有粘包现象,UDP永远不会粘包。指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾 2.原因:它既可能由发送方造成,也可能由接收方造成。发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象(在长连接中会出现) 3.解决:为字节流加上自定义固定长度报头,报头中包含字节流长度,然后一次send到对端,对端在接收时,先从缓存中取出定长的报头,然后再取真实数据
半包:1.原因:指接受方没有接受到一个完整的包,只接受了部分,这种情况主要是由于TCP为提高传输效率,将一个包分配的足够大,导致接受方并不能一次接受完。(在长连接和短连接中都会出现)2.解决:通过包头+包长+包体的协议形式,当服务器端获取到指定的包长时才说明获取完整 或者指定包的结束标识,这样当我们获取到指定的标识时,说明包获取完整
17.加载超高分辨率的大图
内存飙升:SDWebImage等加载大图时,都是在解压缩那一步才会造成内存飙升,因此解决办法有:1.当加载大图时禁止调用解压缩方法 2.是否缓存到内存以及内存缓存最高限制等,来保证内存安全
加载:对图片进行压缩展示,点击放大时,裁剪当前屏幕中展示对应原图中的位置
18.离屏渲染
离屏渲染,指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。当使用 shouldRasterize(光栅化)、masks(遮罩)、shadows(阴影)、edge antialiasing(抗锯齿)、group opacity(不透明)、复杂形状设置圆角、渐变 的时候,图层属性的混合体被指定为在未预合成之前不能直接在屏幕中绘制,所以就需要屏幕外渲染
19.消息传递流程和消息转发机制流程
消息转发流程:1.动态方法解析 2.备援接受者 3.完整的消息转发
消息传递流程:objc_msgSend()函数会依据接受者(调用方法的对象)的类型和选择子(方法名)来调用适当的方法。接收者会根据isa指针找到接收者自己所属的类,然后在所属类的”方法列表“(method list)中从上向下遍历。如果能找到与选择子名称相符的方法,就根据IMP指针跳转到方法的实现代码,调用这个方法的实现。如果找不到与选择子名称相符的方法,接收者会根据所属类的superClass指针,沿着类的继承体系继续向父类查找,如果 能找到与名称相符的方法,就根据IMP指针跳转到方法的实现代码,调用这个方法的实现。如果在继承体系中还是找不到与选择子相符的方法,此时就会执行”消息转发(message forwarding)“操作。
20.网络状态码
http状态吗 :500以上是服务器错误;400以上是客户端错误;300以上是请求重定向;200以上是正确;100以上是请求接受成功
200:请求成功,请求所希望的响应头或数据体将随此响应返回
304:一个带条件的GET请求且该请求已被允许,而文档的内容并没有改变
400:由于包含语法错误,当前请求无法被服务器理解
401:服务器拒绝,需要进行用户验证
403:服务器已经理解请求,但是拒绝执行它,并且身份验证也并不能提供任何帮助
404:请求失败,请求的资源未在服务器上发现,并且没有任何理由
500:服务器出错,无法处理请求
503:由于临时的服务器维护或者过载,服务器当前无法处理请求
21.函数式编程
函数式编程是一种编程范式,如PHP语言的面向过程,JAVA语言的面向对象;函数式编程主要思想是把运算过程尽量携程一系列嵌套的函数调用
22.RunLoop
RunLoop是一个接收处理异步消息事件的循环,是在main函数中的UIApplicationMain中启动的
作用主要有三点:
保持程序的持续运行
等待事件发生,然后将这个事件送到能处理它的地方(比如触摸事件、定时器事件(NSTimer)、selector事件(performSelector)
节省CPU资源,提高程序性能,有事情就做事情,没事情就睡眠
RunLoop与线程的关系:
一个RunLoop对应着一个线程,如果你想开启一条常驻线程(不死线程),可以在子线程中开启一个对应的RunLoop就可以实现了.
RunLoop的创建:主线程Runloop系统已经创建好了,子线程的runloop需要手动创建
RunLoop的声明周期:在第一次获取RunLoop的时候创建,在线程结束的时候销毁
23.Category(分类)和Extension(扩展)区别
1.形式上看:extension 是匿名的category
2.extension中声明的方法需要在implementation中实现,而category不做强制要求
3.extension可以添加属性、成员变量,而category一般不可以
24.五种数据持久化的方案
1.plist文件(属性列表)
2.preference(偏好设置)
3.NSKeyedArchiver(归档)
4.SQLite 3
5.CoreData
沙盒的目录结构:{
1.应用程序包:这里面存放的是应用程序的源文件,包括资源文件和可执行文件
2.Documents:最常用的目录,iTunes同步该应用时会同步此文件夹中的内容,适合存储重要数据
3.Library/Caches:iTunes不会同步此文件夹,适合存储体积大,不需要备份的非重要数据
4.Library/Preferences:iTunes同步该应用时会同步此文件夹中的内容,通常保存应用的设置信息
5.tmp:iTunes不会同步此文件夹,系统可能在应用没运行时就删除该目录下的文件,适合保存一些临时文件
}
1.plist文件
plist文件是将某些特定的类,通过XML文件的方式保存在目录中
注意:只支持NSArray NSDictionary NSData NSString NSNumber NSDate这几种数据类型以及它们可能存在的可变类型
2.preference
NSUserDefaults,会将所有数据保存到同一个文件中。即preference目录下的一个以此应用包名来命名的plist文件
注意:如果没有调用synchronize方法,系统会根据I/O情况不定时刻地保存到文件中。所以如果需要立即写入文件的就必须调用synchronize方法
3.NSKeyedArchiver
归档在iOS中是另一种形式的序列化,只要遵循了NSCoding协议的对象都可以通过它实现序列化
4.SQLite3
在一般开发过程中,使用的都是第三方开源库 FMDB,FMDB是iOS平台的SQLite数据库框架,它是以OC的方式封装了SQLite的C语言API,它相对于cocoa自带的C语言框架有如下的优点:
1.使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码
2.对比苹果自带的Core Data框架,更加轻量级和灵活
3.提供了多线程安全的数据库操作方法,有效地防止数据混乱(FMDatabaseQueue)
4.mac上用来查看数据库的应用Datum free
5.CoreData
本质上是对SQLite的一个封装,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象,通过CoreData管理应用程序的数据模型,可以极大程度减少需要编写的代码数量
25.KVC KVO NSNotification
1.KVC的基本概念
key-value-coding,即键值编码,它是一种可以直接通过字符串类型的属性名(key)来访问某个类属性的机制,而不是通过调用Setter、Getter方法访问
所有NSObject对象都可以使用KVC
KVC既支持带有对象值的属性,也支持基本数据类型和结构,基本数据类型会被自动封装和解装,主要用途:①对私有变量进行赋值(setValue forKey以及setValue forKeyPath)②字典转模型
2.KVO的基本概念和使用
KVO: Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者。属于一种非正式的 Protocol
可以观察任意属性,包括基本数据类型,对一或对多关系。对多关系的观察者将会被告知发生变化的类型,也即使任意发生变化的对象
使用方法:注册观察者,指定被观察者的属性;实现回调方法,接收变更通知;移除观察者身份
3.NSNotification
概述:与KVO不同的是,KVO在属性上通过 K-V 发生改变时,自动调用方法,而 NSNotification 在需要的时候自行发送通知才调用,且方法自定义
使用方法:NSNotificationCenter注册观察者并指定方法;在某个时机激活观察者;收到通知时,执行观察者指定的方法
注意:编译器根据这个事件的名字找到之前注册过这个名字的观察者,所以这个名字一般设置成静态属性,保证两次使用是同一个字符串
26.WebImage框架实现原理
以最常用的UIImageView加载图片为例:
1.先显示placeholderImage ,同时由SDWebImageManager 根据 URL 来在本地查找图片
2.SDImageCache,用来从缓存根据CacheKey查找图片是否已经在缓存中
3.如果内存中已经有图片缓存,会回调显示图片
4.如果内存中没有图片缓存,那么生成 NSInvocationOperation 添加到队列,从硬盘查找图片是否已被下载缓存
5.根据URLKey在硬盘缓存目录下尝试读取图片文件,如果从硬盘读取到了图片,将图片添加到内存缓存中,如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片
6.共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片
7.图片下载由 NSSession 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败
8.数据下载完成后交给 SDWebImageDecoder 做图片解码处理
9.通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片
10.将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存
27.Mac OS X上搭建本地SVN服务器
Mac自带了svn服务器端和客户端功能,我们只需要简单配置一下即可使用,svn上的文件不是以原来的格式存储的,而是以FSFS(the Fast Secure File System)格式存储的
1.创建svn路径path 2. 创建svn repository 3.配置svn的用户权限 4.配置svn账号密码 5.配置svn用户组和权限 6.启动svn服务器 7.连接svn
28.Instruments
Instruments的价值在于,它使我们深刻理解我们代码的内部运作。
1.Time Profiler:分析代码的执行时间,找出导致程序变慢的原因
用来检测app中每个方法所用的时间,并且可以排序,并查找出哪些函数占用了大量时间
1.一定要使用真机调试 2.应用程序一定要使用发布配置
2.Zombies:检查是否访问了僵尸对象,但是这个工具只能从上往下检查,不智能
检测过度释放的“僵尸”对象,还提供了数据对象分配的类以及所有活动分配内存地址的历史
过度释放:是对同一个对象释放了过多的次数,其实当引用计数降到0时,对象占用的内存已经被释放掉,此时指向原对象的指针就成了悬垂指针,如若再对其进行任何方法的调用,原则上都会直接crash
野指针:指向僵尸对象的指针,给野指针发消息会报EXC_BAD_ACCECC错误
空指针:没有指向储存空间的指针(里面存的是nil,也就是0),在oc中使用空指针调中方法不会报错 NSString *Str = nil;
3.Allocations:用来检查内存分配
根据内存泄漏的情况对内存分配进行分析,内存泄漏分两种:
1.为对象A申请了内存空间,之后再也没用到A,也没有释放A导致内存泄漏。这种是Leaked Memory内存泄漏
2.类似于递归,不断的申请内存导致的内存泄漏,这种情况就是Abandoned Memory被遗弃的内存
4.Leaks:检查内存,看是否有内存泄露
内存溢出:out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出
内存泄露:memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光
29.断点续传
要实现断点续传的功能,通常都需要客户端记录下当前的下载进度,并在需要续传的时候通知服务端本次需要下载的内容片段
在HTTP1.1协议(RFC2616)中定义了断点续传相关的HTTP头的Range和Content-Range字段,一个最简单的断点续传实现大概如下:
客户端下载一个1024K的文件,已经下载了其中512K
网络中断,客户端请求续传,因此需要在HTTP头中申明本次需要续传的片段:
Range:bytes=512000 这个头通知服务端从文件的512K位置开始传输文件
服务端收到断点续传请求,从文件的512K位置开始传输,并且在HTTP头中增加:
Content-Range:bytes 512000-/1024000
并且此时服务端返回的HTTP状态码应该是206,而不是200
30.响应者链:
事件可以分为三大类型:触摸事件;加速计事件;远程控制事件;
iOS中只有继承了UIResponder(实现了四个touches对象方法)的对象才能接受并处理事件,即响应者对象(UIApplication UIViewController UIView)
事件的产生:
发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中,UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow),主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的第一步,找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理
事件的传递:
1.首先判断主窗口(keyWindow)自己是否能接受触摸事件
2.判断触摸点是否在自己身上
3.子控件数组中从后往前遍历子控件,重复前面的两个步骤
4.view,比如叫做fitView,那么会把这个事件交给这个fitView,再遍历这个fitView的子控件,直至没有更合适的view为止
5.如果没有符合条件的子控件,那么就认为自己最合适处理这个事件,也就是自己是最合适的view
事件的传递顺序是这样的:
产生触摸事件->UIApplication事件队列->[UIWindow hitTest:withEvent:]->返回更合适的view->[子控件 hitTest:withEvent:]->返回最合适的view
拦截事件的处理:
正因为hitTest:withEvent:方法可以返回最合适的view,不管点击哪里,最合适的view都是hitTest:withEvent:方法中返回的那个view,因此通过重写hitTest:withEvent:,就可以拦截事件的传递过程,想让谁处理事件谁就处理事件
事件的传递和响应的区别:
事件的传递是从上到下(父控件到子控件)hitTest:withEvent:,事件的响应是从下到上(顺着响应者链条向上传递:子控件到父控件)touchs
31.CoreAnimation
CAMediaTiming 协议中定义了时间,速度,重复次数等
CAAnimation 核心动画基础类,不能直接使用,除了CAMediaTiming协议中的方法,增加了CAAnimationDelegate的代理属性等
CAPropertyAnimation 属性动画,针对对象的可动画属性进行效果的设置,不可直接使用
CABasicAnimation 基础动画,通过keyPath对应属性进行控制,需要设置fromValue以及toValue
CASpringAnimation 带有初始速度以及阻尼指数等物理参数的属性动画
CAKeyframeAnimation 关键帧动画,同样通过keyPath对应属性进行控制
CATransition 转场动画,系统提供了很多酷炫效果
CAAnimationGroup 动画组,方便对于多动画的统一控制管理
32.OSI模型
OSI 模型是一个由国际标准化组织提出概念模型,试图提供一个使各种不同的计算机和网络在世界范围内实现互联的标准框架,它将计算机网络体系结构划分为七层,每层都可以提供抽象良好的接口,了解 OSI 模型有助于理解实际上互联网络的工业标准——TCP/IP 协议
接收消息:从上到下依次是
物理层:RJ45等将数据转化成0和1
数据链路层:规定了0和1的分包形式,确定了网络数据包的形式(SLIP,PPP等)
网络层:确定计算机的位置,怎么确定?IPv4,IPv6(IP,ICMP等)
传输层:端到端的网络数据流服务,每一个应用程序都会在网卡注册一个端口号,该层就是端口与端口的通信!(TCP,UDP)
会话层:建立一个连接,自动的手机信息、自动的网络寻址(SDTP,DNS)
表示层:解决不同系统之间的通信,eg:Linux下的QQ和Windows下的QQ可以通信(Telnet,SNMP等)
应用层:规定数据的传输协议(FTP,HTTP,HTTPS等)
33.版本号比较
NSString *old = @"1.1.0";
NSString *new = @"1.1.1";
NSComparisonResult s = [new compare:old options:NSNumericSearch];
if (s == NSOrderedDescending) {
NSLog(@"更新");
} else {
NSLog(@"不更新");
}
34.HTTPS
HTTPS要使客户端与服务器端的通信过程得到安全保证,必须使用的对称加密算法,但是协商对称加密算法的过程,需要使用非对称加密算法来保证安全,然而直接使用非对称加密的过程本身也不安全,会有中间人篡改公钥的可能性,所以客户端与服务器不直接使用公钥,而是使用数字证书签发机构颁发的证书来保证非对称加密过程本身的安全。这样通过这些机制协商出一个对称加密算法,就此双方使用该算法进行加密解密。从而解决了客户端与服务器端之间的通信安全问题。
35.检查IDFA
1、打开终端cd到要检查的文件的根目录。
2、执行下列语句:grep -r advertisingIdentifier . (别少了最后那个点号)
36.base64编码过程
示例:
a
01100001
00011000
00010000
24 16
Y Q
YQ==
将要编码的字符对照ASCII码获取十进制数字,然后将十进制转二进制,得到的二进制不足8位的,在前面补0,得到8位数,然后每6位一截取,最后不足6位的,在后面补0,得到多组6位的数,然后再前面分别补0,补足8位,然后二进制转10进制,得到的数对照base64编码表,得到对应的字符,拼接后最后添加一到两位的等于(=)号,编码完成