==========================================================================================
Const 内存分配、类型检查
#define 内容替换、不会类型检查、不内存分配
栈:
向低地址扩展的数据结构、内存连续、
静态分配和动态分配
堆:
向高地址扩展、内存不连续
动态分配
数组:
栈区和数据区
数组所占内存大小
指针:
指向任意类型内存块
4个字节
引用:
内存别名
代码区:
存放函数二进制代码
数据区:
全局变量、静态变量、常量
selector:
方法的名字
method(选择器):
方法的名字和实现
core foundation内存管理:
create、copy、retain 创建对象。要release
new:
c++操作符
分配内存
调用构造函数、delete调用析构函数
malloc:
C中函数
分配内存
OC反射机制:
类名字符串—>对象
类名变—>字符串
方法字符串—>方法
方法—>字符串
SEL:
方法的包装、方法地址、调用方法
调用方法:
直接调用、用sel数据调用
ns: cocoa fundation
cf: core fundation
cg: core graphics
ca: core animation
ui: uikit
readwrite:可读可写、set/get方法
readonnly: 只读、生成get方法 不会生成set方法
Assign:赋值特性、set方法将参数赋值给实例变量,用于简单数据类型
Retain:持有特性、参数先保留、再赋值
Copy:赋值特性,set方法将传入对象复制一份
non-atomic: 非线程安全、不枷锁、不生成set/get方法
Atomic:多线程安全、枷锁、消化性能、
Kvo:观察属性变化.一对多, 基于runtime机制实现,原理:创建继承当前类的子类,并重写属性的set方法,随后通知观察属性的改变状况。
缺点:观察的属性必须使用string来定义,编译器不会警告、检查
Kvc:键值编码,通过Key名直接访问对象的属性。1、key的set方法 2、key的成员变量、3 _key成员变量 4、valueForUndefineKey
delegate:一对一,
notification:多对多
懒加载好处:1、避免内存过高 2、避免线程阻塞
内省:
程序运行时,检查对象类型的能力
多继承:子类可以有多个父类, 继承多个父类特性
Oc多继承:分类类别、协议实现多继承
Oc方法:类方法(静态方法) + 实例方法
私有方法:把方法的声明和定义在.m文件
私有变量:@private修饰或把声明放在.m文件
#Import:链入该头文件全部信息、编译效率会慢点(import同个文件)。会出现循环依赖关系、两次导入不会报错,解决重导的问题。
#include:使用两次include会报错,include相当于拷贝头文件的声明内容,会报重复定义的错误。
@class:只声明、不会出现编译报错
@protected : 类和子类访问 默认
@private:只能在本类访问
@public:任何地方访问
@package:本包内、跨包不行
目标-动作
目标:动作消息的接收者
动作:控件发送给目标的消息
oc缺点:
不支持命名空间、不支持运算符重载、不支持多继承
C语言函数调用:编译前决定调用哪些函数,编译后顺序执行。
Oc消息机制:编译不决定调用哪个函数, 运行时才去决定调用哪个方法、函数。
.m: c、oc
.mm: c 、c++
.cpp:c、c++
Id:万能指针、指向任何oc对象
instancetype:返回当前类的类型
Nil: 对象的指针、引用为空
Null:c语言变量的指针为空
NSNull:oc的类,空的占位对象
修改类的私有属性:
1、kvc
2、runtime
定义对外只读 对内可读可写:
头文件将属性定义为readonly,实现文件为readwrite
meta-class:
是class对象的类,存储类方法
Selecor转化c语言函数调用:
Selector imp类似c语言函数指针 指向方法实现,oc不能直接应用函数指针,只能做一个selector来取。
// 考虑是点语法还是下划线、考虑是深复制还是浅复制
nsstring使用copy和strong的区别:
//记: 如果是下划线_copyedStr不会调用set方法进行copy
NSString *string = [NSString stringWithFormat:@"abc"];
self.strongStr = string;
self.copyedStr = string;
//改变string的值 此时字符串nsstring为不可变
string = @"123";
结论:当string为nsstring不可变字符串时
当string为不可变字符串时,不管是strong还是copy属性的对象,其指向的地址都是同一个,即为string指向的对象地址。
当string的值发生改变时,两个对象的值也保持原来的值。 strongStr和copyStr还是abc
结论:当string为NSMutableString可变字符串时
1、此时copy属性字符串已不再指向string字符串对象,而是深拷贝了string字符串,并让_copyedStr对象指向这个字符串
2、_strongStr与string是指向同一对象,所以_strongString的值也会跟随着改变(需要注意的是,此时_strongStr的类型实际上是NSMutableString,而不是NSString);而_copyedStr是指向另一个对象的,所以并不会改变,还是abc
选择:一般我们将对象声明为NSString时,都不希望它改变,所以大多数情况下,我们建议用copy,以免因可变字符串的修改导致的一些非预期问题。
Nsarray:不能进行往数组增、删、改元素。
nsmutablearray:插入、删除效率低
nsobject:
类方法 alloc、class、description
对象方法 init、dealloc
构造方法:初始化参数并实例出对象
创建对象步骤:1、内存分配 2、初始化参数 3、返回内存地址
get作用:得到内部的成员变量
Set作用:为外界提供设置成员变量值的方法
结构体定义oc对象?
不能 不能分配空间
点语法:方法的调用,没有set方法和set方法,则不能用点语法
下划线命名开头的好处:1、与get方法名区分开; 2、与其他局部变量区分开
@:oc中的指令符
ARC原理:代码编译为你自动在合适的位置插入retain、release和autorelease, 没有强指针指向, 对象会被释放。
weak和assign区别
// 修饰代理时 考虑是否能将变量置为nil
weak: 用于oc对象,解决循环引用;
Assign:非o c对象 ,数据类型的赋值, 赋值特性、set方法将参数赋值给实例变量。
oc对象的内存布局:
最前面有个isa指针,父类的实例变量在子类成员变量之前。
autorelease实现方式:
以队列数组的形式实现(push、pop)
Objc内存管理机制:
通过引用计数器机制决定对象是否释放。是否有强指针指向。
内存管理的范围:
管理继承自nsobject的对象, 对基本数据类型基本无效
野指针:指向不可用的内存(对象被release了)的指针
僵尸对象:堆中已经被释放的对象
对象销毁判断:
重写dealloc方法,对象销毁会调用。
成员变量对象释放地方:
在dealloc中被释放
重写set方法步骤:
1、判断是否同一对象
2、release旧对象
3、retain新对象
自动释放池作用:延迟release对象的销毁时间
将对象添加到池中条件:调用对象的autorelease方法
自动释放池销毁时间:通过observe监听run loop的状态, 监听到app进入到睡眠等待状态,就释放。
内存泄漏的点:
1、block强引用
2、定时器释放不当
3、第三方代码的内存泄漏
4、core foundation申请的内存 忘记释放。(copy、create、retain)
5、代理申明为retain或strong
内存泄漏检查方式:
1、静态分析analyze
2、动态分析leak
默认关键词:
基本数据类型:atomic、readwrite、assign
Oc对象:atomic、readwrite、strong
代理delegate修饰符:assign或weak,非拥有关系
block内存管理:
Block在哪个区 取决于是否调用外部变量
如果访问外部变量,block在堆里;用copy或strong修饰, block是一个对象。
block循环引用:
在block中使用外部强指针会发生错误,如果延迟操作取不到弱指针,需要在block内部将弱指针强化
Block返回值的使用:
Masonry框架:链式编程(点语法串起来)
系统block api循环引用问题:
不需要考虑的:uiview动画
需要考虑的:gcd
block实现原理:
基于指针和函数指针
block使用好处:
代码紧凑、代码简洁
swift优势:
1、Swift容易阅读(去掉分号,方法的调用,if-else表达式)
2、swift容易维护(去掉.h,.m文件)
3、swift更安全(可选值的加入)
4、swift运行速度快(Swift将很多在运行时才可以确定的信息,在编译期就决定了)
swift 内存管理:
自动引用计数
封装view:
1、添加子控件
2、接收数据模型,根据数据模型设置子控件数据和位置
frame和bounds区别:
frame:该view在父view坐标系统的位置、大小
Bounds:该view在本身系统的位置、大小
控制器的声明周期:
loadView:视图初始化,这个方法不应该被直接调用,而是由系统自动调用。它会加载或创建一个 view 并把它赋值给 UIViewController 的 view 属性。
viewDidLoad:视图加载完成,但还没在屏幕上显示出来。 当view对象被加载到内存就会调用。
viewWillAppear:在视图即将显示在屏幕上时调用
viewDidAppear:在视图显示在屏幕上时调用时调用
viewWillDisappear:视图即将消失、被覆盖或是隐藏时调用
viewDidDisappear:视图已经消失、被覆盖或是隐藏时调用
didReceiveMemoryWarning:当接收到内存警告时会执行这个方法
事件传递机制:
initial view —> 父view —>view controller —>uiwindow —> uiapplication
awakefromnib:
当nib文件被加载的时候调用
Uiwindow:提供一个区域来显示, 将事件分发给view
uiview:calayer的管理器,用户交互
calayer:增强view的展现能力
+(void)load:
当类对象被引入项目时调用。
1、首先执行的是父类Person load方法,再执行的是子类Student load方法,说明父类的load方法执行顺序要优先于子类
3、最后执行的是Person 3个Category的load方法,并且没有顺序,说明类别(Category)中的load方法要晚于类,多个类别(Category)都实现了load方法,这几个load方法都会执行,但执行顺序不确定
4、同时我们也可以看到这几个Category load 执行顺序与其在Compile Sources中出现的顺序一致
5、当然多个不同的类 其load执行顺序,也与其在Compile Sources出现的顺序一致
// key word: 覆盖
+(void)initialize:
第一次使用这个类时调用
1.父类的initialize方法会比子类先执行、
2.当子类未实现initialize方法时,会调用父类initialize方法,子类实现initialize方法时,会覆盖父类initialize方法. 当子类未实现initialize方法,会调用父类initialize方法,initialize方法竟然调用了两次. Focus on
3.当有多个Category都实现了initialize方法,会覆盖类中的方法,只执行一个(会执行Compile Sources 列表中最后一个Category 的initialize方法)
view和view传值方式:
block、代理、属性、target-action、通知
手机架构:
自定义UI控件代码封装内部的业务逻辑
封装网络请求工具类
封装数据存储工具类
调试bug方式:
1、查看异常报告
2、配置相关环境,重现bug
3、代码检查
Cocoapods:
第三库的管理工具
cocoapods修改版本:
修改podfile文件中第三库的版本
集成第三方框架的方法:
1、cocoapod
2、framework
3、直接拖源码
SDWebImage加载流程:
1、先从内存图片缓存查找是否有图片
2、开始从硬盘磁盘查找图片是否已经缓存,读取到了,将图片添加到内存缓存,没有则重新下载。
SDWebImage缓存机制:
1、将图片转化成字典保存在内存缓存中。
2、再次进入程序,将图片保存本地沙盒缓存文件。并将本地沙盒缓存文件保存内存缓存中(从内存中去读取,节约时间)
cadisplaylink:
屏幕刷新率触发的时钟机制 每秒60次,与视图刷新率同步。 Nstime 无法确保触发的准确时间。
客户端缓存机制:
1、获取数据
2、先检测内存有无缓存
3、再检测本地有无缓存
4、最终发送网络请求
序列化:把对象转化字节序列
反序列:把字节序列转成对象
意义:把对象写到文件或数据
Oc实现复杂对象的存储:
遵守nscoding协议,实现复杂对象的存储
数据存储的方式:
plist、nsuserdefault、keychain、sqlite、fmdb、core data
app bundle 里面包含什么:
1、info.plist
2、可执行文件
3、资源文件
4、其他
Md5:不可逆的摘要算法,验证文件是否损坏
Base64:加密算法, 可逆的。
run loop:
概念:运行循环、内部do-while循环、一个线程对应一个run loop。
作用:最核心的事情就是保证线程在没有消息的时候休眠,在有消息时唤醒,以提高程序性能。 靠系统内核完成。
run loop与线程:
主线程run loop自动创建好,子线程的run loop需要自己主动创建
Run loop第一次获取时创建,线程结束销毁。
run loop:
1、开启一个常驻线程
为当前创建run loop
向当前 p 中添加一个 Port/Source
启动该run loop
2、子线程开启定时器
服务器卡住 咋整:
1、设置请求超时
2、给用户提示请求超时
3、根据用户再次操作请求数据
get和post区别:
Get:从服务器获取数据,最大1024字节大小, url能看到提交的数据
Post:向服务器传输数据,无限制大小,数据隐藏在请求体。
TCP: 安全送达、三次握手连接、无限制大小、可靠、慢、流媒体
UDP:只管发送、无需连接、每个数据64k、不可靠、快、qq
三次握手:
1、同步序列编号 (client)
2、同步序列编号+确认标示 (sever)
3、确认标志 (client)
四次挥手:
1、结束标记的报文(client)
2、确认序号(sever)
3、结束标记的报文(sever)
4、确认序号(client)
Json底层原理:
遍历字符串,根据{},[],:,区分
Xml底层原理:
Dom解析和Sax解析
Socket:即使性强、数据量大
Osi七层:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
Ios-h5 优缺点:
Weak:比原生慢点
Strong:不用更新版本,随时更改
Gcd:fifo,接近底层速度快
Nsoperation:支持kvo,观察执行状态; 调整执行顺序,设置最大并发数
线程&进程:
概念:线程是进程的基本单元
目的:实现系统对应用的并发
其他:进程有自己的独立地址空间。多进程比多线程健壮;进程切换,浪费资源大、效率差
进程和线程:
线程是进程的基本执行单元,进程的所有任务都在线程中。
线程是cpu分配资源和调度的最小单位
一个程序可以对应多个进程。一个进程可有多个线程,至少有一条。
同一个进程内的线程共享进程资源
多线程的底层实现:
底层实现机制:基于Mach线程
多线程安全问题:
使用锁:nslock、synchronized
回调主线程作用:子线程数据处理,主线程刷新UI
Atomic并非绝对安全:
绝对安全需要加锁, nsmutablearray
多线程好处:
耗时长的任务放到后台
多线程坏处:
更多线程 需要更多内存
更多线程 会影响性能。因为系统需要让线程切换。
GCD作用:利用更多CPU核数,会自动管理线程的生命周期。
gcd:XNU
GCD和NSThread区别:
Nsthread:通过selector指定方法, 必须实例化多个线程对象
Gcd:通过block指定方法,不需要管理线程创建、销毁、复用
缺点:
delegate:
定义很多代码
notification:
编译不会检查通知是否正确处理
调试过程很难追踪
KVO:
属性需要strings定义,编译器不会出现警告以及检查
设计模式:
为特定场景下的问题定制解决方案
类工厂方法: 分配和初始化在一个步骤并返回创建对象
单例模式:确保一个类只有一个实例。向系统提供这个实例。
Mvvm:业务逻辑、网络请求、数据存储分离到viewmodel,使viewcontroller精简
view controller瘦下来途径:
业务逻辑移到model
网络请求移到model
View代码移到view
苹果的安全机制:
没有用户同意, 不能获取用户信息
程序都在沙盒进行
防止代码反编译
网络请求登录
签名机制:
App内容 摘要算法 私钥 加密成密文。 公钥+私钥+密文发布
验证:
公钥是否是私钥方的。 公钥对密文解密 摘要。对比两个摘要
Md5特点:
输入两个不同的明文,不会得到相同的输出值
根据输出值 不能得到原始的明文,过程不可逆
runtime:
概念:运行时机制,c语言api库。类转结构体,方法转c函数
用处:获取类的所有的成员变量、为类添加变量、改变类的方法实现 、添加新的方法
分类支持属性:
使用runtime实现
runtime如何通过selector找到对应的imp地址?
selector和imp是一一对应的关系
性能优化:
ARC管理
不阻塞主线程
懒加载
加速启动时间
图片缓存
本地推送通知:
不需要联网。是开发人员在app内设定特定时间提醒用户。
远程推送通知:
需要联网。远程服务器的程序发送apns, 再由apns把消息推送到设备上。
App启动流程:
1、系统内核创建一个进程
2、加载可执行文件
3、加载苹果的动态链接器
3.5、动态链接器含有 :分析应用依赖的dylib、runtime运行时初始化(类的注册、category注册、+load方法加载、静态全局变量)
编译器前端Clang:
语法分析,语义分析,生成中间代码
编译器后端LLVM:
代码优化,生成机器语言。
通过IR(中间码)生成特定CPU架构的汇编代码。将汇编代码转化成机器码。将机器码链接成可执行程序或动态码
静态库:
链接时完整 多个目标文件拷贝到可执行文件,多次使用,就有多次拷贝。
动态库:
链接不复制,运行时动态加载到内存,系统只加载一次,节省内存
静态链接:
多个目标文件合链接成一个可执行的文件
delegate代理对象使用weak和assign哪个:
声明一个delegate,如果delegate指向的对象销毁了,delegate中依然会保存之前对象的地址
即,delegate成为了一个野指针。而使用weak,则不会有上述问题,当delegate指向的对象销毁后,delegate = nil