参考:
Apple Developer
Apple OpenSource
1. 基础知识点:
Cocoa Touch
是apple基于手机触摸的一套基础框架,包括音频视频,数据管理,网络,用户应用等框架;
查看官方文档说明
>> runtime运行时原理
runtime是一套比较底层的纯C语言API,我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码;
利用runtime机制让我们可以在程序运行时动态修改类、对象中的所有属性、方法;
用处:
- 动态创建一个类;
- 动态为某个类添加属性\方法,修改属性值\方法;
- 遍历一个类的所有成员变量(属性)\所有方法 例如:我们需要对一个类的属性进行归档解档的时候属性特别的多,这时候,我们就会写很多对应的代码,但是如果使用了runtime就可以动态设置;
相关函数: - objc_msgSend : 给对象发送消息
- class_addMethod: 添加方法
- class_copyMethodList : 遍历某个类所有的方法
- class_copyIvarList : 遍历某个类所有的成员变量
IOS的函数调用是在运行时通过objc_msgSend决定的;
GCD (Grand Central Dispatch)
GCD的工作原理是:让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节;
常用函数:
dispatch_async dispatch_group_async dispatch_barrier_async dispatch_apply
APNS (Apple Push Notification service)
APNS的消息注册跟消息吹都在AppDelegate中处理,使用:
didRegisterForRemoteNotificationsWithDeviceToken
didReceiveRemoteNotification
相关application函数;
工作原理:
- 应用注册,由iOS系统向APNS请求返回设备令牌;
(void)application:(UIApplication )application didRegisterForRemoteNotificationsWithDeviceToken:(NSData)deviceToken; - 应用程序接收到设备令牌并发送给服务器;
- 服务器把要提送的内容和设备发送给APNS;
- APNS根据设备令牌找到设备,再由iOS根据APPID把推送内容展示;
NSZone
可以想象成一个内存池,alloc与dealloc这些操作,都是在这个内存池中操作的,cocoa总是会配置一个默认的NSZone,任何默认的内存操作都是在这个zone上操作的;
默认的NSZone是全局的,时间一长,必然会导致内存碎片化,如果大量的alloc一些object,那么性能就会收到影响;所以cocoa提供方法,你可以自己生成一个NSZone,并将alloc,copy全部限制在这个zone之内;
>> 数据存储
>> 沙盒
http://www.cnblogs.com/luckhao/p/5437896.html
沙盒目录结构
文件存储
- plist 存储
存放一些基本数据类型的数据,一般在Document目录下,plist路径获取代码示例:
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSString *fileName = [path stringByAppendingPathComponent:@"123.plist"];
- 偏好设置存储
偏好设置是专门用来保存应用程序的配置信息的,一般不要保存其他安全性数据;
如果要立即同步数据到文件,使用synchronize;
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults synchronize];
偏好设置会将所有数据保存到同一个文件中。即preference目录下的一个以此应用包名来命名的plist文件;
- 归档操作 NSKeyedArchiver
归档在iOS中是另一种形式的序列化,只要遵循了NSCoding协议的对象都可以通过它实现序列化;
保存文件的扩展名可以任意指定;
数据库存储:
- SQLite 轻型嵌入式关系数据库,包含在一个相对小的c库中,基于C的API操作;
- CoreData:对象关系映射(ORM),它将数据库的创建,表的创建,对象与表的转换操作等封装起来,简化了我么的操作;开发者只要把模型搭建起来,具体数据库如何创建不用管,在IOS项目中添加“Data Model”文件;
- 第三方架构FMDB: 相比于SQLite3来说Core Data存在着诸多优势,它面向对象,开发人员不必过多的关心更多数据库操作知识,同时它基于ObjC操作,书写更加优雅等。
多线程访问数据同步?
NSLock
常用函数 lock,unlock;NSCondition
A condition object acts as both a lock and a checkpoint in a given thread. 即它表示一个锁+一个线程检查器,线程检查器主要是根据条件决定是否继续运行线程,即线程是否被阻塞;
常用函数:
lock,unlock
wait:等待其他线程发出信号,此时其他线程可访问lock区域内的内容,wait相当于在调用时候unlock了,然后触发后再次lock,所以wait时候其他线程可以访问lock的内容;
signal: 处理完数据通知其他线程互斥锁 synchronized
使用 @synchronized(锁对象) {} 锁住一块代码操作;
能有效处理多线程数据安全问题,但是消耗大量CPU资源;DSP中的信号量 dispatch_semaphore_t
使用函数:
dispatch_semaphore_create(num) //创建信号量的初始值
dispatch_semaphore_wait 信号量-1,如果等于0则阻塞,大于0往下执行;
dispatch_semaphore_signal 信号量+1CoreData的多线程访问同步?
OC与Swift混编
- Swift访问OC
使用 Bridging Header,加入oc文件时系统询问自动创建,或者自己手动创建,在项目中加入一个新的头文件命名为"项目工程名-Bridging-Header",然后再设置Build Setting->Swift Compiler ->Object-C Bridging Header的路径,必须只想文件本身;
在这个头文件中添加swift需要访问的OC类的头文件; - OC访问Swift
需要配置 Build Setting下的 Packaging:
设置Defines Module为YES,设置Product Module Name,在调用swift
的模块中加入该名称的"***-Swift.h"头文件(这个文件是系统自己创建的),就能够直接使用OC语法调用swift模块;
后台多任务管理机制
http://www.zhihu.com/question/21192280
响应链
系统会根据hittest来处理将定位消息属于具体哪个窗口;
能响应对象的都是UIResponse的子对象;
app接受的响应会逐级传递寻找响应, 形成一个响应链,例如一个事件响应链:
AppDelegate --> UIApplication --> UIWindow --> UIViewController --> UIView --> UIButton
使用nextResponder函数可以循环获取父级响应对象;
用户的一个点击事件信息包括:UITouch和UIEvent;
keychain(Security.framework)
它是一个在所有app之外的sqlite数据库;
Keychain的信息是存在于每个应用(app)的沙盒之外的,所以keychain里保存的信息不会因App被删除而丢失,在用户重新安装App后依然有效,数据还在;
NSUserDefaults存储是不安全的,简单的信息存储使用NSUserDefaults即可,但是对于安全性要求比较高的信息,比如账户密码等;
基本函数:SecItemAdd/SecItemUpdate/SecItemCopyMatching/SecItemDelete
100个知识点汇总
http://www.csdn.net/article/2015-01-19/2823604-ios-interview-questions
类的load与initialize静态函数作用
这两个静态方法是可选的,且只有在实现了他们时才会被调用;
- load的作å用
当类对象被引用项目中,runtime会向每一个类对象发送load消息,这个消息只会被调用一次,要想修改原来类方法及其他,可以在分类的load中进行实现; - initialize作用
在整个runtime中也只调用一次,但是它是该类的第一个方法调用之前调用的,用于确保实例初始化前某些条件必须满足;
2. 内存与多线程知识点
多线程
内存管理
http://www.jianshu.com/p/dba7e8010cd3
自动释放池块与线程
使用局部自动释放池块降低最大内存占用率
-
为什么更新UI都在主线程中进行?
因为UIKit不是线程安全的,无法保证多个线程对同一UI的更新操作;
在子线程中是不能进行UI 更新的,我们看到的UI更新其实是子线程代码执行完毕了,又自动进入到了主线程,执行了子线程中的UI更新的函数栈,这中间的时间非常的短,就让大家误以为分线程可以更新UI。如果子线程一直在运行,则子线程中的UI更新的函数栈 主线程无法获知,即无法更新。
3. UI知识点:
Core Animation / Core Graphics
- Core Animation iOS 系统基本渲染框的OC语言框架
基于CoreGraphics的OC语言封装动画处理架构;
动画执行过程都是在后台操作的,不会阻塞主线程;
动画使用:
CALayer *layer = [CALayer layer];
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"transform.scale";
animation.toValue = @0;
[layer addAnimation:animation forKey:nil];
CA动画基础参考:http://www.jianshu.com/p/8c1c1697c0ce
- Core Graphics 是底层绘制的C语言框架
实际用到的CG开头的函数与变量是指这绘制库;
可在drawRect函数中重绘视图,也可对图形图片进行切角,旋转等转换处理;
CGContextRef context = UIGraphicsGetCurrentContext();
NSString *str1 = @"画线";
[self drawText:str1 atPoint:CGPointMake(20.0, 20.0) FontSize:15];
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSaveGState(context);
CGContextRestoreGState();
每一个 UIView 都有一个 graphics context (绘图上下文),在设备硬件显示前,绘制的所有视图都会被渲染到这个上下文中;
iOS 在任何时候需要更新视图都是通过调用 drawRect 方法;
参考学习:http://www.tuicool.com/articles/jaM7zmN
UIView本身更像是一个一个CALayer的管理器
把UIView看做图片的话,layer就像是一个图层,一个图片是由很多个大小不同的有层次的图层构成的 uiview也是
UITableView 复用机制
UITableview通常只会显示当前页面最大可显示cell个数加1,cell离开屏幕后会从队列中删除;
- 复用队列
只有cell被滑出当前页面的时候,此cell才会被加到复用队列中,使用dequeueReusableCellWithIdentifier,如果找不到才会调用UITableviewCell的initWithStyle:reuseIdentifier接口创建cell
imageNamed
使用imageNamed方法创建UIImage对象时,图片会自动加载到系统缓存中不再释放,会使内存增大
UIImageView圆角
如何提高调价圆角的性能?
- 一般使用clipsToBounds与layer.corneRadius, 但是这个方法会强制Core Animation提前渲染屏幕的离屏绘制,为性能带来负面影响;
- 使用贝塞尔曲线切割图片
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
[[UIBezierPath bezierPathWithRoundedRect:RECT cornerRadius:RADIUS] addClip];
[image drawInRect:RECT];
UIImage* imageNew = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
key window是?
可接收键盘输入等事件的UIWindow,官方文档如是说:
The key window is the one that is designated to receive keyboard and other non-touch related events. Only one window at a time may be the key window.
使用 makeKeyAndVisible让一个 UIWindow 变成 key window;
程序主窗口是:[[[UIApplication sharedApplication] delegate] window];
pushViewController 与 presentViewcontroller
- pushViewController提供的是一个栈控制器数组;
- presentViewcontroller提供的是模态视图控制器;
模态是指一个控制器present另一个控制器,prensenting 与 presented,两者通过delegate实现交互;所以在没有navigationController的情况下,使用presentModalViewController能进行controller间的转换;