本文可能涉及很多零碎的知识点,其中包括iOS应用开发的相关基础知识。以后会针对每个条目在进行深入研究,这里只是先做一个相关知识的概述总结。
大多数iOS程序其功能总结为:提供一套界面,帮助用户管理特定数据。在这个过程中,不同对象各司其职:模型对象负责保存数据,视图对象负责显示数据,控制器对象负责在模型对象与视图对象之间同步数据。
由iOS SDK提供的一种保存和读取对象的机制。固化某个对象的时候,会将其所有属性存入指定的文件中。解固某个对象时,会从指定的文件读取相应的数据,然后根据数据还原对象。
为了固化和解固某个对象,必须要遵守NSCoding协议,并且实现两个必需方法:encodeWithCoder方法:和initWithCoder:方法。
-(void)encodeWithCoder:(NSCode *)aCoder{
[aCoder encodeObject:self.itemName forKey:@"itemName"];
}
-(instancetype) initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if(self){
_itermName = [aDecoderdecodeObjectForKey:@"itemName"];
}
}
iOS应用可以在运行时载入应用程序包中的文件。要获得应用程序包中的某个文件的全路径,需要首先得到代表应用程序包的NSBundle对象,然后通过该对象得到某个文件的全路径,代码如下:
NSBundle *applicationBundle = [NSBundle mainBundle];
NSString *path = [applicationBundle pathForResource:@"myImage" ofType:@"png"];
如果应用程序需要保存程序参数、选项相关的少量数据,则可以使用NSUserDefaults进行保存;如果应用程序只有少量数据需要保存,那么使用属性列表就可以了;如果应用程序有大量数据进行存储、访问,就需要借助于数据库了。iOS内置SQLite数据库是一个真正轻量级的数据库,他没有后台程序,整个数据库对应一个文件。并有两套API:基于c语言风格的libsqlite3.dylib和面向对象的Core Data。
1. Document:除了基于NSUserDefaults的首选项设置之外,应用程序的数据、文件都保存在该目录下
2. Library:基于NSUserDefaults的首选项参数保存在Library/Preference目录下。
3. Library/Caches:存放运行时生成的保留数据。iTunes或者iClound不会同步该数据。
4. Library/Preferences: 存放所有偏好数据。可以使用NSUserDefaults类
5. tmp:该目录提供应用程序存储的历史文件,当iOS执行同步的时候,iTunes不会备份tmp目录下的文件。
因此当应用程序不在需要某个临时文件时,应该负责删除tmp目录下的临时文件,避免占用系统空间。运行时的临时文件。
前面介绍了固化的存放路径,下面要讲的是:1.如何保存、读取数据;2.何时保存、读取数据
通过 NSKeyedArchiver类保存对象发送archiveRootObject:toFile:消息
-(BOOL)saveChagne
{
NSString *path = [self itemArchivePath];
return [NSKeyedArchiver archiveRootObject:self.privateItems toFile :path];
}
上面的工作原理是:
1. archiveRootObject:toFile:会先创建一个NSKeyedArchiver对象。
2. 然后,archiveRootObject:toFile:会向privateItems发送encodeWithCoder:消息,并传入NSKeyedArchiver对象作为第一个参数。
3. privateItems的encodewithCoder:方法会向其包含的多个对象一次发送encodeWithCoder消息,
并传入NSKeyedArchiver对象。这项BNRItem对象都会将其属性编码至同一个NSKeyedArchiver对象。
4. 当所有的对象都完成编码后,NSKeyedArchiver对象就会将数据写入指定的文件中。
一般情况是在用户按下设备的主屏幕按钮后,AppDelegate对象会收到applicationDidEnterBackground:消息之后,发送saveChange消息;
主要使用NSKeyedUnarchiver类。
-(instancetype)initPrivate
{
self = [super init];
NSString *psth = [self itemArchivePath];
_privateItems = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
if(!_privateItems){
_privateItems = [[NSMutableArray alloc] init];
}
return self;
}
iOS大致提供了如下三种多线程编程技术。
1. NSThread实现多线程。
2. NSOperation与NSOperationQueue实现多线程。
3. 使用GCD(Grand Central Dispatch)实现多线程。
创建一个新线程对象。
- initWithTarget:selector:object:
创建并启动新线程。
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)arg;
上面两种方法的本质都是将target对象的selector方法转化为线程执行体,其中selector方法最多可以接受一个参数,而arg就代表创个selector方法的参数。
*currentThread 属性返回当前正在执行的线程对象。
除此之外,可以通过setName:方法为线程设置名字,也可以通过name方法返回指定线程的名字。
备注:启动线程使用start方法,线程启动之后并不是立即进入运行状态,线程内启动后处于就绪状态,当系统调度线程后, 线程才会进入运行状态。
如果程序希望子线程的start后立刻执行,程序可以使用NSThread sleepForTimeInterval:0.001让当前运行的线程睡眠1毫秒。
1. 线程正常结束。
2. 线程执行过程中出现错误。
3. 直接调用NSThread的exit方法,来终止当前正在执行的线程。
在iOS规定中,只能在UI线程中修改UI控件的属性。所以当子线程执行“任务”完成后,如果需要通过UI控件来显示子线程中的数据,则通常会调用performSelectorOnMainThread:withObject:waitUntilDone:方法完成。
1.@synchronize实现同步。被@synchronize修饰的代码块可简称同步代码块。格式如下:
@synchronize(obj)
{
...
//同步代码块。obj就是同步监视器。通过是可能被并发访问的共享资源充当同步监视器。
}
Foundation框架中很多类都有可变和不可变两种版本,比如NSString, NSArray都是不可变,他们永远是线程安全的。但是NSMutableString,NSMutaleArray就是可变得,线程不安全的。
1. 块执行结束;
2. return、goto等语句结束代码块。
3. 出现错误、异常等。但是sleep不会释放监视器。
先获得NSLock对象实例,然后
[lock lock]
......
[lock unlock];
虽然线程在系统内运行时,线程的调度具有一定的透明性,程序通常无法准确的控制线程轮换执行,但我们可以通过一些机制来保证线程协调运行,也就是处理线程之间的通信。
Foundation提供了一个NSCondition类来处理线程通信,NSCondition实现了NSLocking协议,因此也可以调用lock、unlock来实现线程同步。NSCondition可以让那些已经锁定NSCondition对象却无法继续执行的线程释放NSCondition对象,NSCondition对象也可以唤醒其他处于等待状态的线程。
主要是三个函数:
-wait:导致当前一直等待,直到其他线程调用该NSCondition的signal或者broadcaset方法来唤醒该线程。
-signal:唤醒再次NSCondition对象等待的单个线程。如果线程都在该NSCondition对象等待,则会选择性唤醒其中一个线程。
-broadcast:唤醒在此NSCondition对象等待的所有线程。
1.队列:队列负责管理开发者提交的任务
2.任务:任务就是用户提交给队列的工作单位,这些任务提交给队列底层维护的线程池执行,因此这些任务会以多线程的方式执行。
1.创建队列。
2.将任务提交给队列。
dispatch_queue_t dispatch_get_current_queue(void);
dispatch_queue_t dispatch_get_global_queue(long identifier, <#unsigned long flags#>)
…..其他具体的参考开发文档
NSOperationQueue:代表一个FIFO的队列,它负责管理系统提交的多个NSOperation,NSOperationQueue底层维护一个线程池,会按照顺序启动线程来执行提交给该队列的NSOperation任务。
NSOperation:代表一个多线程任务。NSOperation有两个子类:1.NSInvocationOperation、NSBlockOperation。开发者会自己实现子类,也可以直接使用该子类。
1.创建NSOperationQueue队列,病设置相关属性。
2.创建NSOperation子类对象,并将该对象提交给NSOperationQueue队列,该队列将会按照一次启动每个NSOperation任务。