寫(xiě)在前面:
已經(jīng)好久沒(méi)有碰代碼和程序了。如今重新拿起來(lái)锦针,再學(xué)習(xí)一些曾經(jīng)不懂的東西它浅。文中的內(nèi)容基本都是已經(jīng)有很多人講過(guò)了译柏,如果有錯(cuò)誤的地方請(qǐng)留言指正。感謝姐霍。
不出意外的情況是不間斷更新的鄙麦。(本文中大多是借鑒他人的博客,所以如果可以的話(huà)請(qǐng)點(diǎn)擊原文邮弹,支持一下原作者黔衡。)
1.單例模式
單例是在iOS乃至所有程序開(kāi)發(fā)中廣泛使用的一種設(shè)計(jì)模式。
優(yōu)點(diǎn):在程序運(yùn)行過(guò)程中只實(shí)例化一個(gè)對(duì)象腌乡,并且該對(duì)象易于被外界訪問(wèn),節(jié)約系統(tǒng)消耗夜牡。
在使用單例的過(guò)程中應(yīng)該注意的問(wèn)題是:線程安全与纽。
創(chuàng)建方式大概兩種:
1)GCD
static id _instance;//保留一個(gè)全局的實(shí)例。
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
//在這里創(chuàng)建唯一的實(shí)例(注意線程安全)
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]; 調(diào)用時(shí)塘装,會(huì)默認(rèn)調(diào)用+ (id)allocWithZone:(NSZone *)zone方法的急迂。。sharedInstance 最終是在allocWithZone:(NSZone *)zone方法中完成了初始化操作蹦肴。
2)常規(guī)方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
@synchronized(self) {
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
}
return _instance;
}
+ (instancetype)sharedInstance{
@synchronized(self) {//一定要添加互斥鎖僚碎,不然會(huì)出現(xiàn)線程安全問(wèn)題
if (_instance == nil) {
_instance = [[self alloc]init];
}
}
return _instance;
}
最后,單例作為一個(gè)被普遍使用的設(shè)計(jì)模式而深受大家喜愛(ài)阴幌,但單例也有其弊端勺阐。在此貼出一篇blog共勉
慎用單例模式卷中! - FerventDesert - 博客園
2.cocoapods的安裝和使用
關(guān)于cocoapods的介紹:類(lèi)庫(kù)管理工具。本人也是在網(wǎng)上搜到的安裝方法渊抽,原理暫不清楚蟆豫。
// Todo:搞清楚它。
基本的安裝步驟:
gem sources ?--remove https://rubygems.org/
gem sources -a https://ruby.taobao.org/?
(注:原來(lái)是http://ruby.taobao.org/ ?后來(lái)淘寶改用了https懒闷。所以十减。。愤估。)
sudo ?gem install cocoapods?
(這里的下載和安裝會(huì)根據(jù)網(wǎng)絡(luò)環(huán)境不同有差異帮辟,請(qǐng)大家在安裝時(shí)不要那么著急)
安裝完成。(這里我都沒(méi)有放圖玩焰,如果輸入正確的話(huà)织阅,應(yīng)該能看出來(lái)的。)
使用:
在終端中cd到當(dāng)前項(xiàng)目下 在需要引入類(lèi)庫(kù)的之前先調(diào)用一下?
pod search ***(庫(kù)名震捣。比如AFNetworking)
查看當(dāng)前版本以及pod的語(yǔ)句荔棉。
然后創(chuàng)建podfile?
vim podfile?
然后手動(dòng)輸入:
platform :ios, '7.0'
pod "AFNetworking", "~> 2.0"
(這里可以根據(jù)你查看的Pod語(yǔ)句進(jìn)行輸入,支持command + c / v)
然后按esc ?輸入:wq 保存退出?
輸入 pod install (被墻了) pod install --verbose --no-repo-update 就可以進(jìn)行下載了
再次打開(kāi)項(xiàng)目的時(shí)候蒿赢,打開(kāi)xcworkspace文件了润樱。 就可以啦。
如果想刪除某個(gè)類(lèi)庫(kù)羡棵,只需要?jiǎng)h除Podfile文件中對(duì)應(yīng)的pod語(yǔ)句 然后重新進(jìn)行 pod install 就可以了壹若。?
原文:CocoaPods安裝和使用教程 - 精靈的專(zhuān)欄 - 博客頻道 - CSDN.NET
3.iOS中的多線程
iOS中應(yīng)用的多線程分為三種:NSThread,NSOperationQueue皂冰,GCD店展。
NSThread應(yīng)用較少所以暫時(shí)不寫(xiě)啦。~~~
NSOperationQueue
NSOperationQueue:運(yùn)行隊(duì)列秃流,是Apple對(duì)于GCD的封裝赂蕴。
需要在隊(duì)列中添加對(duì)應(yīng)的NSOperation的子類(lèi)對(duì)象〔罢停可以指定線程的優(yōu)先級(jí)(這個(gè)優(yōu)先級(jí)是相對(duì)的概说,是相對(duì)在排隊(duì)的。不包括正在執(zhí)行的)
NSOpration是一個(gè)抽象類(lèi)嚣伐,所以不能進(jìn)行封裝操作糖赔。
注:抽象類(lèi)是不完整的,它只能用作基類(lèi)轩端。在面向?qū)ο蠓椒ㄖ蟹诺洌橄箢?lèi)主要用來(lái)進(jìn)行類(lèi)型隱藏和充當(dāng)全局變量的角色。(CR:百度百科)
系統(tǒng)給出的NSOperation子類(lèi)為:NSInvocationOperation,NSBlockOperation奋构】怯埃可以自定義。
自定義的非并發(fā)的NSOperation子類(lèi)只需要重載- (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{
// 新建一個(gè)自動(dòng)釋放池态贤,如果是異步執(zhí)行操作,那么將無(wú)法訪問(wèn)到主線程的自動(dòng)釋放池
@autoreleasepool {
if (self.isCancelled) return;
// 獲取圖片數(shù)據(jù)
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:)]) {
// 把圖片數(shù)據(jù)傳回到主線程
[(NSObject *)self.delegate performSelectorOnMainThread:@selector(downloadFinishWithImage:) withObject:image waitUntilDone:NO];
}
}
}
@end
這樣就基本實(shí)現(xiàn)了一個(gè)圖片下載的自定義NSOperation子類(lèi)醋火。
NSInvocationOperation?
這個(gè)方法比較簡(jiǎn)單悠汽,只需創(chuàng)建一個(gè)對(duì)象
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector( ) object:nil];
調(diào)用Start方法即可。
NSBlockOperation
創(chuàng)建對(duì)象:
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
NSLog(@"執(zhí)行了一個(gè)新的操作芥驳,線程:%@", [NSThread currentThread]);
}];// 開(kāi)始執(zhí)行任務(wù)(這里還是同步執(zhí)行)
NSBlockOperation可以通過(guò)調(diào)用addExecutionBlock方法添加Block操作
[operation addExecutionBlock:^() {
NSLog(@"又執(zhí)行了1個(gè)新的操作柿冲,線程:%@", [NSThread currentThread]);
}];//添加的block是并發(fā)執(zhí)行的,也就是在不同線程中執(zhí)行的兆旬。
調(diào)用Start方法
NSOperationQueue
創(chuàng)建對(duì)象
NSOperationQueue *qu = [[NSOperationQueue alloc] init];
向隊(duì)列中添加線程:addOperation:
控制Queue的最大并發(fā)操作數(shù)量:setMaxConcurrentOperationCount:
取消所有線程隊(duì)列內(nèi)的線程:cancelAllOperations:
只要加入隊(duì)列之后假抄,我們就不用去操作,直到Callback或者完成丽猬。
注1:operation的子類(lèi)可以調(diào)用setCompletionBlock:這是線程執(zhí)行結(jié)束的回調(diào)方法宿饱。
調(diào)用setQueuePriority:設(shè)定線程的優(yōu)先級(jí)。NSOperationQueuePriority是一個(gè)枚舉類(lèi)型脚祟,包含最低谬以,低,普通由桌,高为黎,最高五個(gè)等級(jí)。
注2:operation開(kāi)始執(zhí)行之后,會(huì)一直執(zhí)行任務(wù)直到完成,或者顯式地取消操作行您。取消可能發(fā)生在任何時(shí)候,甚至在operation執(zhí)行之前铭乾。盡管NSOperation提供了一個(gè)方法,讓?xiě)?yīng)用取消一個(gè)操作,但是識(shí)別出取消事件則是我們自己的事情。如果operation直接終止, 可能無(wú)法回收所有已分配的內(nèi)存或資源娃循。因此operation對(duì)象需要檢測(cè)取消事件,并優(yōu)雅地退出執(zhí)行
NSOperation對(duì)象需要定期地調(diào)用isCancelled方法檢測(cè)操作是否已經(jīng)被取消,如果返回YES(表示已取消),則立即退出執(zhí)行炕檩。不管是自定義NSOperation子類(lèi),還是使用系統(tǒng)提供的兩個(gè)具體子類(lèi),都需要支持取消。isCancelled方法本身非常輕量,可以頻繁地調(diào)用而不產(chǎn)生大的性能損失
以下地方可能需要調(diào)用isCancelled:
* 在執(zhí)行任何實(shí)際的工作之前
* 在循環(huán)的每次迭代過(guò)程中,如果每個(gè)迭代相對(duì)較長(zhǎng)可能需要調(diào)用多次
* 代碼中相對(duì)比較容易中止操作的任何地方
本章引用的博客:
多線程編程2 - NSOperation - M了個(gè)J - 博客頻道 - CSDN.NET
談iOS多線程(NSThread骤星、NSOperation、GCD)編程 - 推酷
GCD?
依然學(xué)習(xí)中爆哑。洞难。。
串行并發(fā)揭朝,同步異步队贱。色冀。我想shi。柱嫌。锋恬。
//其中第一個(gè)參數(shù)是標(biāo)識(shí)符。第二個(gè)參數(shù)傳DISPATCH_QUEUE_SERIAL 或 NULL 表示創(chuàng)建串行隊(duì)列编丘,傳入 DISPATCH_QUEUE_CONCURRENT 表示創(chuàng)建并發(fā)隊(duì)列与学。
dispatch_queue_t myQueue = dispatch_queue_create(參數(shù)一, 參數(shù)二);
串行:以先進(jìn)先出的方式嘉抓,順序的調(diào)度隊(duì)列中的任務(wù)索守,無(wú)論隊(duì)列中的任務(wù)是同步還是異步,都會(huì)等待前一個(gè)任務(wù)完成后再執(zhí)行抑片。
并發(fā):以先進(jìn)先出的方式卵佛,并發(fā)的調(diào)度隊(duì)列中的任務(wù),如果任務(wù)是同步的敞斋,則會(huì)等待任務(wù)完成之后再調(diào)度后續(xù)的任務(wù)截汪;如果任務(wù)是異步的,會(huì)開(kāi)啟新線程調(diào)度后續(xù)任務(wù)植捎。
dispatch_sync(dispatch_queue_t queue, ^(void)block)同步任務(wù)
dispatch_async(dispatch_queue_t queue, ^(void)block)異步任務(wù)
注:比較常用的是串行隊(duì)列異步任務(wù)衙解,和并發(fā)隊(duì)列異步任務(wù)。(猜測(cè)因?yàn)橥饺蝿?wù)會(huì)阻塞線程鸥跟,有待查清)丢郊。
全局隊(duì)列:沒(méi)有名字,不需要考慮釋放問(wèn)題医咨。在日常開(kāi)發(fā)中建議使用枫匾。
待更。拟淮。干茉。·
/*4.sqlite和CoreData的使用
在iOS開(kāi)發(fā)中用到的數(shù)據(jù)庫(kù)大多是sqlite(PS:本人還是小菜很泊,目前所寫(xiě)的程序中用到數(shù)據(jù)庫(kù)的只有兩個(gè)角虫。)而CoreData則是Apple對(duì)于sqlite的封裝。
sqlite使用基本都在使用FMDB的第三方庫(kù)委造,sqlite的api還沒(méi)有怎么研究過(guò)戳鹅,見(jiàn)諒見(jiàn)諒。
fmdb 的github地址:GitHub - ccgus/fmdb: A Cocoa / Objective-C wrapper around SQLite
在印象中使用數(shù)據(jù)庫(kù)基本都作為MVC中的Model使用昏兆。創(chuàng)建一個(gè)對(duì)應(yīng)的數(shù)據(jù)庫(kù)模型枫虏,然后對(duì)內(nèi)容進(jìn)行增刪改查。
在使用FMDB之前先介紹一下iOS應(yīng)用的沙盒目錄結(jié)構(gòu):
詳細(xì)的沙盒目錄介紹:iOS沙盒目錄介紹
一般情況下我們會(huì)將數(shù)據(jù)庫(kù)存放在Document目錄下。(我想的:緩存文件是否可以放在tmp文件下隶债?)*/