总结:iOS部分学习之路

写在前面:

已经好久没有碰代码和程序了。如今重新拿起来,再学习一些曾经不懂的东西。文中的内容基本都是已经有很多人讲过了,如果有错误的地方请留言指正。感谢。

不出意外的情况是不间断更新的。(本文中大多是借鉴他人的博客,所以如果可以的话请点击原文,支持一下原作者。)



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;

}

原文:iOS单例模式(面试必考) - 推酷

最后,单例作为一个被普遍使用的设计模式而深受大家喜爱,但单例也有其弊端。在此贴出一篇blog共勉

慎用单例模式! - FerventDesert - 博客园


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

多线程下NSOperation、NSBlockOperation、NSInvocationOperation、NSOperationQueue的使用 - crycheng的专栏 - 博客频道 - 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文件下?)*/

推荐阅读更多精彩内容