标签:最大 工厂 依赖关系 graph 解决 修改表 网络请求 coretext 国外
1. 首先搞清楚什么是线程、什么是多线程
2. Mach是第一个以多线程方式处理任务的系统,因此多线程的底层实现机制是基于Mach的线程
3. 开发中很少用Mach级的线程,因为Mach级的线程没有提供多线程的基本特征,线程之间是独立的
4. 开发中实现多线程的方案
C语言的POSIX接口:#include <pthread.h>
OC的NSThread
C语言的GCD接口(性能最好,代码更精简)
OC的NSOperation和NSOperationQueue(基于GCD)
1. performSelector:onThread:withObject:waitUntilDone:
2. NSMachPort
利用字典(图片地址为key,下载操作为value),具体可以查看SD缓存机制
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSOperation *A = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"SuperLog------ NSOperationA");
}];
NSOperation *B = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"SuperLog------ NSOperationB");
}];
NSOperation *C = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"SuperLog------ NSOperationC");
}];
[C addDependency:A];
[C addDependency:B];
[queue addOperation:A];
[queue addOperation:B];
[queue addOperation:C];
1. 只在主线程刷新访问UI
2. 如果要防止资源抢夺,得用synchronized进行加锁保护
3. 如果异步操作要保证线程安全等问题, 尽量使用GCD(有些函数默认就是安全的)
1. iOS和OS X的核心是XNU内核,GCD是基于XNU内核实现的
2. GCD的API全部在libdispatch库中
3. GCD的底层实现主要有Dispatch Queue和Dispatch Source
Dispatch Queue :管理block(操作)
Dispatch Source :处理事件
1. GCD是纯C语言的API,NSOperationQueue是基于GCD的OC版本封装
2. GCD只支持FIFO的队列,NSOperationQueue可以很方便地调整执行顺序、设置最大并发数量
3. NSOperationQueue可以在轻松在Operation间设置依赖关系,而GCD需要写很多的代码才能实现
4. NSOperationQueue支持KVO,可以监测operation是否正在执行(isExecuted)、是否结束(isFinished),是否取消(isCanceld)
5. GCD的执行速度比NSOperationQueue快
任务之间不太互相依赖:GCD
任务之间有依赖\或者要监听任务的执行情况:NSOperationQueue
Block的使用注意:
1. block的内存管理
2. 防止循环retian
非ARC(MRC):__block
ARC:__weak\__unsafe_unretained
1. 重新下载图片
2. 下载完毕, 利用RunLoop的输入源回到主线程刷新UIImageView
1. 使用Analyze进行代码的静态分析
2. 尽量使用ARC
创建单例设计模式的基本步骤:
1. 声明一个单件对象的静态实例,并初始化为nil
2. 创建一个类的类工厂方法,当且仅当这个类的实例为nil时生成一个该类的实例
3. 实现NScopying协议, 覆盖allocWithZone:方法,确保用户在直接分配和初始化对象时,不会产生另一个对象
4. 覆盖release、autorelease、retain、retainCount方法, 以此确保单例的状态。
5. 在多线程的环境中,注意使用@synchronized关键字或GCD,确保静态实例被正确的创建和初始化。
1. 系统自带的绝大数类方法返回的对象,都是经过autorelease的
1. 对于没有引用外部变量的Block,无论在ARC还是非ARC下,类型都是__NSGlobalBlock__,这种类型的block可以理解成一种全局的block,不需要考虑作用域问题。同时,对他进行Copy或者Retain操作也是无效的
2. 应注意避免循环引用
1. 当程序在申请内存后,无法释放已申请的内存空间(例如一个对象或者变量使用完成后没有释放,这个对象一直占用着内存),一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。内存泄露会最终会导致内存溢出!
2. 当程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个int,但给它存了long才能存下的数,那就是内存溢出。
[NSArray arrayWithobject:(id)obj]
这个方法添加对象后,需要对这个数组做释放操作吗?不需要这个对象被放到自动释放池中
自动释放池以栈的形式实现:当你创建一个新的自动释放池时,它将被添加到栈顶。当一个对象收到发送autorelease消息时,它被添加到当前线程的处于栈顶的自动释放池中,当自动释放池被回收时,它们从栈中被删除, 并且会给池子里面所有的对象都会做一次release操作.
1. KVO是基于runtime机制实现的
2. 当某个类的对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法。
3. 派生类在被重写的 setter 方法实现真正的通知机制(NSKVONotifying_Class)
如果在异步线程发的通知,那么可以执行比较耗时的操作
如果在主线程发的通知,那么就不可以执行比较耗时的操作
1. Foundation对象是OC的,Core Foundation对象是C对象
2. 数据类型之间的转换
ARC:__bridge_retained、__bridge_transfer
非ARC: __bridge
A = A + B
B = A - B
A = A - B
A = A^B;
B = A^B;
A = A^B;
节省内存资源,一个应用就一个对象。
运行时机制,runtime库里面包含了跟类、成员变量、方法相关的API,比如获取类里面的所有成员变量,为类动态添加成员变量,动态改变类的方法实现,为类动态添加新的方法等 需要导入<objc/message.h> <objc/runtime.h>
1. runtime,运行时机制,它是一套C语言库
2. 实际上我们编写的所有OC代码,最终都是转成了runtime库的东西,比如类转成了runtime库里面的结构体等数据类型,方法转成了runtime库里面的C语言函数,平时调方法都是转成了objc_msgSend函数(所以说OC有个消息发送机制)。因此,可以说runtime是OC的底层实现,是OC的幕后执行者
3. 有了runtime库,能做什么事情呢?runtime库里面包含了跟类、成员变量、方法相关的API,比如获取类里面的所有成员变量,为类动态添加成员变量,动态改变类的方法实现,为类动态添加新的方法等。因此,有了runtime,想怎么改就怎么改
CoreText
1. 随意修改文本的样式
2. 图文混排(纯C语言)
3. 国外:Niumb
Core Image(滤镜处理)
- 能调节图片的各种属性(对比度, 色温, 色差等)
通知比较灵活(1个通知能被多个对象接收, 1个对象能接收多个通知)
代理比较规范,但是代码多(默认是1对1)
KVO性能不好(底层会动态产生新的类),只能监听某个对象属性的改变, 不推荐使用(1个对象的属性能被多个对象监听,1个对象能监听多个对象的其他属性)
更详细参考:
Objective-C是对C语言的扩展,block的实现是基于指针和函数指针
算法题,百度自己学习。
思路
1. 计算 differ = sum(a) - sum(b)
2. 寻找 a b 数组中差值最接近differ/2 的元素
3. 交换元素
编写SQL语句来操作原来表中的字段
1. 增加表字段
ALTER TABLE 表名 ADD COLUMN 字段名 字段类型;
2. 删除表字段
ALTER TABLE 表名 DROP COLUMN 字段名;
3. 修改表字段
ALTER TABLE 表名 RENAME COLUMN 旧字段名 TO 新字段名;
1. 添加SQLite动态库
2. 导入主头文件:#import <sqlite3.h>
3. 利用C语言函数创建/打开数据库,编写SQL语句
1. 缓存可以分为:内存数据缓存、数据库缓存、文件缓存
2. 每次想获取数据的时候
2.1 先检测内存中有无缓存
2.2 再检测本地有无缓存(数据库\文件)
2.3 最终发送网络请求
2.4 将服务器返回的网络数据进行缓存(内存、数据库、文件),以便下次读取
1. CoreData是对SQLite数据库的封装
2. CoreData中的NSManagedObjectContext在多线程中不安全
3. 如果想要多线程访问CoreData的话,最好的方法是一个线程一个NSManagedObjectContext
4. 每个NSManagedObjectContext对象实例都可以使用同一个NSPersistentStoreCoordinator实例,这是因为NSManagedObjectContext会在便用NSPersistentStoreCoordinator前上锁
ios中不存在缓存池满的情况,因为通常我们ios中开发,对象都是在需要的时候才会创建,有种常用的说话叫做懒加载,还有在UITableView中一般只会创建刚开始出现在屏幕中的cell,之后都是从缓存池里取,不会在创建新对象。缓存池里最多也就一两个对象,缓存池满的这种情况一般在开发java中比较常见,java中一般把最近最少使用的对象先释放。
Core Animation Programming Guide
如何找到最合适的视图
1. 自己是否能接收触摸事件
2. 触摸点是否在自己身上
3. 从后往前遍历子控件,重复前面的两个步骤
4. 如果没有符合条件的子控件,那么自己最适合处理
1. 首先判断控制器是否有视图,如果没有就调用loadView方法创建(storyboard/代码)
2. 随后调用viewDidLoad,可以进行下一步的初始化操作(只会被调用一次)
3. 在视图显示之前调用viewWillAppear(该函数可以多次调用)
4. viewDidAppear
3. 在视图显示之前调用viewWillDisappear;该函数可以多次调用(如需要)
5. 在布局变化前后,调用viewWill/DidLayoutSubviews处理相关信息
NSRunLoop是iOS消息机制的处理模式
1. NSRunLoop的主要作用:控制NSRunLoop里面线程的执行和休眠,在有事情做的时候使当前NSRunLoop控制的线程工作,没有事情做让当前NSRunLoop的控制的线程休眠。
2. NSRunLoop 就是一直在循环检测,从线程start到线程end,检测inputsource(如点击,双击等操作)异步事件,检测timesource同步事件,检测到输入源会执行处理函数,首先会产生通知,corefunction向线程添加runloop observers来监听事件,意在监听事件发生时来做处理。
3. runloopmode是一个集合,包括监听:事件源,定时器,以及需通知的runloop observers
多线程中如何使用?
1. 只有在为你的程序创建次线程的时候,才需要运行run loop。对于程序的主线程而言,run loop是关键部分。Cocoa提供了运行主线程run loop的代码同时也会自动运行run loop。iOS程序UIApplication中的run方法在程序正常启动的时候就会启动run loop。如果你使用xcode提供的模板创建的程序,那你永远不需要自己去启动run loop
2. 在多线程中,你需要判断是否需要run loop。如果需要run loop,那么你要负责配置run loop并启动。你不需要在任何情况下都去启动run loop。比如,你使用线程去处理一个预先定义好的耗时极长的任务时,你就可以毋需启动run loop。Run loop只在你要和线程有交互时才需要
一般的应用在进入后台的时候可以获取一定时间来运行相关任务,也就是说可以在后台运行一小段时间(10S左右)。
1. 后台播放音乐
2. 后台GPS跟踪
3. 后台voip支持
程序启动分为两类:
1. 有storyboard
2. 没有storyboard
情况一:
1.main函数
2.UIApplicationMain
* 创建UIApplication对象
* 创建UIApplication的delegate对象
3.根据Info.plist获得最主要storyboard的文件名,加载最主要的storyboard(有storyboard)
* 创建UIWindow
* 创建和设置UIWindow的rootViewController
* 显示窗口
情况二:
1.main函数
2.UIApplicationMain
* 创建UIApplication对象
* 创建UIApplication的delegate对象
3.delegate对象开始处理(监听)系统事件(没有storyboard)
* 程序启动完毕的时候, 就会调用代理的application:didFinishLaunchingWithOptions:方法
* 在application:didFinishLaunchingWithOptions:中创建UIWindow
* 创建和设置UIWindow的rootViewController
* 显示窗口
1. 关掉后不执行任何代码,不能处理事件
2. 应用程序进入后台状态不久后转入挂起状态。在这种状态下,应用程序不执行任何代码,并有可能在任意时候从内存中删除。只有当用户再次运行此应用,应用才会从挂起状态唤醒,代码得以继续执行
3. 或者进入后台时开启多任务状态,保留在内存中,这样就可以执行系统允许的动作
4. 远程推送是由远程服务器上的程序发送到APNS,再由APNS把消息推送至设备上的程序,当应用程序收到推送的消息会自动调用特定的方法执行事先写好的代码
5. 本地通知和远程推送通知对基本概念和用法?
* 本地通知和远程推送通知都可以向不在前台运行的应用发送消息,这种消息既可能是即将发生的事件,也可能是服务器的新数据.不管是本地通知还是远程通知,他们在程序界面的显示效果相同,都可能显示为一段警告信息或应用程序图标上的微章.
* 本地通知和远程推送通知的基本目的都是让应用程序能够通知用户某些事情,而且不需要应用程序在前台运行.二者的区别在于本地通知由本应用负责调用,只能从当前设备上的iOS发出, 而远程通知由远程服务器上的程序发送到APNS,再由APNS把消息推送至设备上的程序
1. SIP(Session Initiation Protocol),会话发起协议
2. SIP是建立VOIP连接的 IETF 标准,IETF是全球互联网最具权威的技术标准化组织
3. 所谓VOIP,就是网络电话,直接用互联网打电话,不用耗手机话费
1. 图片下载放在异步线程
2. 图片下载过程中使用占位图片
3. 如果图片较大,可以考虑多线程断点下载
1. 提供给外界的接口功能是否实用、够用
2. 能不能根据类名、方法名就猜出接口的具体作用
3. 提供的参数是否够用、调用起来是否简单
4. 要不要再导入依赖其他的框架
1. 设置请求超时
2. 给用户提示请求超时
3. 根据用户操作再次请求数据
1. 如果通知是在主线程发出,那么接收通知的方法中的耗时操作要放到异步线程中
2. 如果通知实在异步线程中发出,那么接收通知后调用的方法会默认在异步线程中执行
1. 利用NSOperationQueue和NSOperation下载图片, 还使用了GCD的一些函数(解码GIF图片)
2. 利用URL作为key,NSOperation作为value
3. 利用URL作为key,UIImage作为value
待完善...
1. AFN基于NSURL,ASI基于底层的CFNetwork框架,因此ASI的性能优于AFN
2. AFN采取block的方式处理请求,ASI最初采取delegate的方式处理请求,后面也增加了block的方式
3. AFN只封装了一些常用功能,满足基本需求,直接忽略了很多扩展功能,比如没有封装同步请求;ASI提供的功能较多,预留了各种接口和工具供开发者自行扩展
4. AFN直接解析服务器返回的JSON、XML等数据,而ASI比较原始,返回的是NSData二进制数据
1. 你创建的程序不需要显示的创建run loop;每个线程,包括程序的主线程(main thread)都有与之相应的run loop对象, 主线程会自行创建并运行run loop
2. Runloop处理的输入事件有两种不同的来源:输入源(input source)和定时源(timer source)
3. 输入源传递异步消息,通常来自于其他线程或者程序。定时源则传递同步消息,在特定时间或者一定的时间间隔发生
1. 检查网络请求操作是否被放在主线程了
2. 看看异步请求的数量是否太多了(子线程数量)
3. 数据量是否太大?如果太大,先清除一些不必要的对象(看不见的数据、图片)
4. 手机CPU使用率和内存问题
1. 设置数据库锁定的处理函数
int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
2. 设定锁定时的等待时间
int sqlite3_busy_timeout(sqlite3*, 60);
标签:最大 工厂 依赖关系 graph 解决 修改表 网络请求 coretext 国外
原文地址:https://www.cnblogs.com/chao8888/p/11328860.html