写在前面:
已经好久没有碰代码和程序了。如今重新拿起来,再学习一些曾经不懂的东西。文中的内容基本都是已经有很多人讲过了,如果有错误的地方请留言指正。感谢。
不出意外的情况是不间断更新的。(本文中大多是借鉴他人的博客,所以如果可以的话请点击原文,支持一下原作者。)
1.单例模式
单例是在iOS乃至所有程序开发中广泛使用的一种设计模式。
优点:在程序运行过程中只实例化一个对象,并且该对象易于被外界访问,节约系统消耗。
在使用单例的过程中应该注意的问题是:线程安全。
创建方式大概两种:
1)GCD
static id _instance;//保留一个全局的实例。
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
//在这里创建唯一的实例(注意线程安全)
dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
+ (instancetype)sharedInstance{
//提供的外部接口
dispatch_once_t oneceToken;
dispatch_once(&oneceToken, ^{
_instance = [[self alloc]init];
});
return _instance;
}
- (id)copyWithZone:(NSZone *)zone{
return _instance;
}
注:[[self alloc] init]; 调用时,会默认调用+ (id)allocWithZone:(NSZone *)zone方法的。。sharedInstance 最终是在allocWithZone:(NSZone *)zone方法中完成了初始化操作。
2)常规方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
@synchronized(self) {
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
}
return _instance;
}
+ (instancetype)sharedInstance{
@synchronized(self) {//一定要添加互斥锁,不然会出现线程安全问题
if (_instance == nil) {
_instance = [[self alloc]init];
}
}
return _instance;
}
最后,单例作为一个被普遍使用的设计模式而深受大家喜爱,但单例也有其弊端。在此贴出一篇blog共勉
2.cocoapods的安装和使用
关于cocoapods的介绍:类库管理工具。本人也是在网上搜到的安装方法,原理暂不清楚。
// Todo:搞清楚它。
基本的安装步骤:
gem sources --remove https://rubygems.org/
gem sources -a https://ruby.taobao.org/
(注:原来是http://ruby.taobao.org/ 后来淘宝改用了https。所以。。。)
sudo gem install cocoapods
(这里的下载和安装会根据网络环境不同有差异,请大家在安装时不要那么着急)
安装完成。(这里我都没有放图,如果输入正确的话,应该能看出来的。)
使用:
在终端中cd到当前项目下 在需要引入类库的之前先调用一下
pod search ***(库名。比如AFNetworking)
查看当前版本以及pod的语句。
然后创建podfile
vim podfile
然后手动输入:
platform :ios, '7.0'
pod "AFNetworking", "~> 2.0"
(这里可以根据你查看的Pod语句进行输入,支持command + c / v)
然后按esc 输入:wq 保存退出
输入 pod install (被墙了) pod install --verbose --no-repo-update 就可以进行下载了
再次打开项目的时候,打开xcworkspace文件了。 就可以啦。
如果想删除某个类库,只需要删除Podfile文件中对应的pod语句 然后重新进行 pod install 就可以了。
原文:CocoaPods安装和使用教程 - 精灵的专栏 - 博客频道 - CSDN.NET
3.iOS中的多线程
iOS中应用的多线程分为三种:NSThread,NSOperationQueue,GCD。
NSThread应用较少所以暂时不写啦。~~~
NSOperationQueue
NSOperationQueue:运行队列,是Apple对于GCD的封装。
需要在队列中添加对应的NSOperation的子类对象。可以指定线程的优先级(这个优先级是相对的,是相对在排队的。不包括正在执行的)
NSOpration是一个抽象类,所以不能进行封装操作。
注:抽象类是不完整的,它只能用作基类。在面向对象方法中,抽象类主要用来进行类型隐藏和充当全局变量的角色。(CR:百度百科)
系统给出的NSOperation子类为:NSInvocationOperation,NSBlockOperation。可以自定义。
自定义的非并发的NSOperation子类只需要重载- (void)main方法就可以了。
@protocol DownLoadWebImageOperationDelegate <NSObject>
- (void)downlineshWithImage:(UIImage *)image;
@end
@interface DownLoadWebImageOperation :NSOperation
@property (nonatomic, assign) id<DownLoadWebImageOperationDelegate> aDelegate;
@property (nonatomic, copy) NSString *imageURL;
- (id)initWithDelegate:(id<DownLoadWebImageOperationDelegate>)delegate andImageURL:(NSString *)url;
@end
@implementation DownLoadWebImageOperation
- (id)initWithDelegate:(id<DownLoadWebImageOperationDelegate>)delegate andImageURL:(NSString *)url{
if (self = [[super alloc]init]){
self.aDelegate = delegate;
self.imageURL = url;
}
return self;
}
- (void)main{
// 新建一个自动释放池,如果是异步执行操作,那么将无法访问到主线程的自动释放池
@autoreleasepool {
if (self.isCancelled) return;
// 获取图片数据
NSURL *url = [NSURL URLWithString:self.imageUrl];
NSData *imageData = [NSData dataWithContentsOfURL:url];
if (self.isCancelled) {
url = nil;
imageData = nil;
return;
}
// 初始化图片
UIImage *image = [UIImage imageWithData:imageData];
if (self.isCancelled) {
image = nil;
return;
}
if ([self.delegate respondsToSelector:@selector(downloadFinishWithImage:)]) {
// 把图片数据传回到主线程
[(NSObject *)self.delegate performSelectorOnMainThread:@selector(downloadFinishWithImage:) withObject:image waitUntilDone:NO];
}
}
}
@end
这样就基本实现了一个图片下载的自定义NSOperation子类。
NSInvocationOperation
这个方法比较简单,只需创建一个对象
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector( ) object:nil];
调用Start方法即可。
NSBlockOperation
创建对象:
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"执行了一个新的操作,线程:%@", [NSThread currentThread]);
}];// 开始执行任务(这里还是同步执行)
NSBlockOperation可以通过调用addExecutionBlock方法添加Block操作
[operation addExecutionBlock:^() {
NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]);
}];//添加的block是并发执行的,也就是在不同线程中执行的。
调用Start方法
NSOperationQueue
创建对象
NSOperationQueue *qu = [[NSOperationQueue alloc] init];
向队列中添加线程:addOperation:
控制Queue的最大并发操作数量:setMaxConcurrentOperationCount:
取消所有线程队列内的线程:cancelAllOperations:
只要加入队列之后,我们就不用去操作,直到Callback或者完成。
注1:operation的子类可以调用setCompletionBlock:这是线程执行结束的回调方法。
调用setQueuePriority:设定线程的优先级。NSOperationQueuePriority是一个枚举类型,包含最低,低,普通,高,最高五个等级。
注2:operation开始执行之后,会一直执行任务直到完成,或者显式地取消操作。取消可能发生在任何时候,甚至在operation执行之前。尽管NSOperation提供了一个方法,让应用取消一个操作,但是识别出取消事件则是我们自己的事情。如果operation直接终止, 可能无法回收所有已分配的内存或资源。因此operation对象需要检测取消事件,并优雅地退出执行
NSOperation对象需要定期地调用isCancelled方法检测操作是否已经被取消,如果返回YES(表示已取消),则立即退出执行。不管是自定义NSOperation子类,还是使用系统提供的两个具体子类,都需要支持取消。isCancelled方法本身非常轻量,可以频繁地调用而不产生大的性能损失
以下地方可能需要调用isCancelled:
* 在执行任何实际的工作之前
* 在循环的每次迭代过程中,如果每个迭代相对较长可能需要调用多次
* 代码中相对比较容易中止操作的任何地方
本章引用的博客:
多线程编程2 - NSOperation - M了个J - 博客频道 - CSDN.NET
谈iOS多线程(NSThread、NSOperation、GCD)编程 - 推酷
GCD
依然学习中。。。
串行并发,同步异步。。我想shi。。。
//其中第一个参数是标识符。第二个参数传DISPATCH_QUEUE_SERIAL 或 NULL 表示创建串行队列,传入 DISPATCH_QUEUE_CONCURRENT 表示创建并发队列。
dispatch_queue_t myQueue = dispatch_queue_create(参数一, 参数二);
串行:以先进先出的方式,顺序的调度队列中的任务,无论队列中的任务是同步还是异步,都会等待前一个任务完成后再执行。
并发:以先进先出的方式,并发的调度队列中的任务,如果任务是同步的,则会等待任务完成之后再调度后续的任务;如果任务是异步的,会开启新线程调度后续任务。
dispatch_sync(dispatch_queue_t queue, ^(void)block)同步任务
dispatch_async(dispatch_queue_t queue, ^(void)block)异步任务
注:比较常用的是串行队列异步任务,和并发队列异步任务。(猜测因为同步任务会阻塞线程,有待查清)。
全局队列:没有名字,不需要考虑释放问题。在日常开发中建议使用。
待更。。。·
/*4.sqlite和CoreData的使用
在iOS开发中用到的数据库大多是sqlite(PS:本人还是小菜,目前所写的程序中用到数据库的只有两个。)而CoreData则是Apple对于sqlite的封装。
sqlite使用基本都在使用FMDB的第三方库,sqlite的api还没有怎么研究过,见谅见谅。
fmdb 的github地址:GitHub - ccgus/fmdb: A Cocoa / Objective-C wrapper around SQLite
在印象中使用数据库基本都作为MVC中的Model使用。创建一个对应的数据库模型,然后对内容进行增删改查。
在使用FMDB之前先介绍一下iOS应用的沙盒目录结构:
详细的沙盒目录介绍:iOS沙盒目录介绍
一般情况下我们会将数据库存放在Document目录下。(我想的:缓存文件是否可以放在tmp文件下?)*/