2017-03第二周

> 不積跬步浙宜,無以至千里;不積小流官辽,無以成江海∷谒玻——荀子

[TOC]

2017-03-06

一同仆、蘋果核 - 菜鳥不要怕,看一眼裙品,你就會用GCD俗批,帶你裝逼帶你飛

1.Serial Diapatch Queue 串行隊列

//第一個參數(shù)是隊列名字。第二個參數(shù)是隊列類型市怎,如果設(shè)置為NULL岁忘,創(chuàng)建出來的是串行隊列

dispatch_queue_t serialDispatchQueue = dispatch_queue_create("com.test.queue", DISPATCH_QUEUE_SERIAL);

2.Concurrent Diapatch Queue 并發(fā)隊列

//與串行隊列剛好相反,他不會存在任務(wù)間的相互依賴区匠。

dispatch_queue_t concurrentDispatchQueue = dispatch_queue_create("com.test.queue", DISPATCH_QUEUE_CONCURRENT);

3.Global Queue & Main Queue

  • Global Queue其實就是系統(tǒng)創(chuàng)建的Concurrent Dispatch Queue

  • Main Queue 其實就是系統(tǒng)創(chuàng)建的位于主線程的Serial Dispatch Queue

通常情況我們會把這2個隊列放在一起使用干像,也是我們最常用的開異步線程-執(zhí)行異步任務(wù)-回主線程的一種方式

  • Global Queue的優(yōu)先級:
    DISPATCH_QUEUE_PRIORITY_HIGH 2

DISPATCH_QUEUE_PRIORITY_DEFAULT 0

DISPATCH_QUEUE_PRIORITY_LOW (-2)

DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN

  • 異步主線程 dispatch_async(dispatch_get_main_queue(), ^{});

在日常工作中,除了在其他線程返回主線程的時候需要用這個方法驰弄,還有一些時候我們在主線程中直接調(diào)用異步主線程蝠筑,這是利用dispatch_async的特性:block中的任務(wù)會放在主線程本次runloop之后返回。 這樣揩懒,有些存在先后順序的問題就可以得到解決了什乙。

4.dispatch_set_target_queue

dispatch_set_target_queue為自己創(chuàng)建的隊列設(shè)置優(yōu)先級

5.dispatch_after

這個是最常用的,用來延遲執(zhí)行的GCD方法已球,因為在主線程中我們不能用sleep來延遲方法的調(diào)用臣镣,所以用它是最合適的

6.dispatch_group

當(dāng)我們需要監(jiān)聽一個并發(fā)隊列中,所有任務(wù)都完成了智亮,就可以用到這個group忆某,因為并發(fā)隊列你并不知道哪一個是最后執(zhí)行的,所以以單獨一個任務(wù)是無法監(jiān)聽到這個點的阔蛉,如果把這些單任務(wù)都放到同一個group弃舒,那么,我們就能通過dispatch_group_notify方法知道什么時候這些任務(wù)全部執(zhí)行完成了。

通過把這個并發(fā)隊列任務(wù)統(tǒng)一加入group中聋呢,group每次runloop的時候都會調(diào)用一個方法dispatch_group_wait(group, DISPATCH_TIME_NOW)苗踪,用來檢查group中的任務(wù)是否已經(jīng)完成,如果已經(jīng)完成了削锰,那么會執(zhí)行dispatch_group_notify的block

7.dispatch_barrier

此方法的作用是在并發(fā)隊列中通铲,完成在它之前提交到隊列中的任務(wù)后打斷,單獨執(zhí)行其block器贩,并在執(zhí)行完成之后才能繼續(xù)執(zhí)行在他之后提交到隊列中的任務(wù)颅夺。

這其實就起到了一個線程鎖的作用,在多個線程同時操作一個對象的時候蛹稍,讀可以放在并發(fā)進行吧黄,當(dāng)寫的時候,我們就可以用dispatch_barrier_async方法唆姐,效果杠杠的稚字。

8.dispatch_sync

dispatch_sync 會在當(dāng)前線程執(zhí)行隊列,并且阻塞當(dāng)前線程中之后運行的代碼厦酬,所以胆描,同步線程非常有可能導(dǎo)致死鎖現(xiàn)象,我們這邊就舉一個死鎖的例子:

dispatch_sync(dispatch_get_main_queue(), ^{

     NSLog(@"有沒有同步主線程?");

});

根據(jù)FIFO(先進先出)的原則仗阅,block里面的代碼應(yīng)該在主線程此次runloop后執(zhí)行昌讲,但是由于他是同步隊列,所有他之后的代碼會等待其執(zhí)行完成后才能繼續(xù)執(zhí)行减噪,2者相互等待短绸,所以就出現(xiàn)了死鎖。

9.dispatch_apply

這個方法用于無序查找筹裕,在一個數(shù)組中醋闭,我們能開啟多個線程來查找所需要的值

10.dispatch_suspend & dispatch_resume

隊列掛起和恢復(fù)

11.Semaphore

我們可以通過設(shè)置信號量的大小,來解決并發(fā)過多導(dǎo)致資源吃緊的情況朝卒,以單核CPU做并發(fā)為例证逻,一個CPU永遠只能干一件事情,那如何同時處理多個事件呢抗斤,聰明的內(nèi)核工程師讓CPU干第一件事情囚企,一定時間后停下來,存取進度瑞眼,干第二件事情以此類推龙宏,所以如果開啟非常多的線程,單核CPU會變得非常吃力伤疙,即使多核CPU银酗,核心數(shù)也是有限的,所以合理分配線程,變得至關(guān)重要黍特,那么如何發(fā)揮多核CPU的性能呢蛙讥?如果讓一個核心模擬傳很多線程,經(jīng)常干一半放下干另一件事情衅澈,那效率也會變低键菱,所以我們要合理安排谬墙,將單一任務(wù)或者一組相關(guān)任務(wù)并發(fā)至全局隊列中運算或者將多個不相關(guān)的任務(wù)或者關(guān)聯(lián)不緊密的任務(wù)并發(fā)至用戶隊列中運算今布,所以用好信號量,合理分配CPU資源拭抬,程序也能得到優(yōu)化部默,當(dāng)日常使用中,信號量也許我們只起到了一個計數(shù)的作用造虎,真的有點大材小用傅蹂。

dispatch_semaphore_t semapore = dispatch_semaphore_create(10);//為了讓一次輸出10個,初始信號量為10

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

for(int i = 0; i < 20; i++){

     //第二個參數(shù)為timeout 遞減信號量算凿,如果信號量小于零份蝴,會一直等待到一個信號發(fā)生

    dispatch_semaphore_wait(semapore, DISPATCH_TIME_FOREVER);//每進來1次,信號量-1;進來10次后就一直hold住氓轰,直到信號量大于0婚夫;

    dispatch_async(queue, ^{

        NSLog(@"%i",i);

        sleep(2);

        //遞增信號量的值,如果上一個值小于0署鸡,該方法返回前會喚醒一個等待的線程

        dispatch_semaphore_signal(semapore);//由于這里只是log,所以處理速度非嘲覆冢快,我就模擬2秒后信號量+1;

    });
}

12.dispatch_once

這個函數(shù)一般是用來做一個真的單例靴庆,也是非常常用的时捌。


2017-03-07

一、 sunny分享

CFRunLoopSource

  • Source是RunLoop的數(shù)據(jù)源抽象類(protocol)
  • RunLoop定義了兩個Version的Source:

Source0:處理App內(nèi)部事件炉抒、App自己負責(zé)管理(觸發(fā))奢讨,如UIEvent、CFSocket
Source1:由RunLoop和內(nèi)核管理焰薄,Mach port驅(qū)動禽笑,如CFMachPort、CFMessagePort

CFRunLoopMode

  • RunLoop在同一段時間只能且必須在一種特定Mode下Run

  • 更換Mode時蛤奥,需要停止當(dāng)前Loop佳镜,然后重啟新Loop

  • Mode是iOS App滑動順暢的關(guān)鍵

  • 可以定制自己的Mode

NSDefaultRunLoopMode

默認(rèn)狀態(tài)、空閑狀態(tài)

UITrackingRunLoopMode

滑動ScrollView時

UIInitializationRunLoopMode

私有凡桥,App啟動時

NSRunLoopCommonModes

Mode集合


2017-03-08

一蟀伸、iOS 無需SDK,一行代碼調(diào)用主流地圖

高德地圖、百度地圖和騰訊地圖url規(guī)則:

/*

 必要參數(shù)的意思:sourceApplication:該app名字啊掏; poi name:目的地名稱蠢络;lat/lon:目的地經(jīng)緯度

 dev 參數(shù)進行解釋:dev支持的值為"0"和"1",即是否需要進行國測局坐標(biāo)加密迟蜜。 如果傳入的坐標(biāo)已經(jīng)是國測局坐標(biāo)則傳入0刹孔,如果傳入的是地球坐標(biāo),則該參數(shù)傳入1

 */

#define GaoDeNavUrl @"iosamap://navi?sourceApplication=%@&backScheme=%@&poiname=%@&poiid=BGVIS&lat=%@&lon=%@&dev=0&style=2"

#define GaoDeGPSUrl @"iosamap://viewMap?sourceApplication=%@&poiname=%@&lat=%@&lon=%@&dev=0"

/*

 百度地圖的參數(shù)意思就比較簡單了娜睛,對mode做一個解釋髓霞,mode為調(diào)用地圖之后的導(dǎo)航方式,除了walking(步行)還有driving(駕車)和transit(公交)

 origin=latlng:0,0  這個參數(shù)雖然意思上是要給一個當(dāng)前坐標(biāo)畦戒,但是可以隨意設(shè)置方库,這里設(shè)置兩個0,不影響導(dǎo)航

 */

#define BaiDuNavUrl @"baidumap://map/direction?origin=latlng:0,0|name:我的位置&destination=latlng:%@,%@|name:%@&mode=walking"

#define BaiDuGPSUrl @"baidumap://map/marker?location=%@,%@&title=我的位置&content=%@"

//騰訊地圖導(dǎo)航

#define TXGPSUrl    @"qqmap://map/marker?marker=coord:%@,%@;title:%@;addr:%@"

#define TXNavUrl    @"qqmap://map/routeplan?type=walk&from=我的位置&to=%@&tocoord=%@,%@&referer=%@"

2017-03-09

一障斋、UIView形變動畫

  • 當(dāng)UIView發(fā)生變換(transformed)后纵潦,不要使用frame屬性,因為它往往不能代表視圖的正確位置垃环,使用bounds和center屬性代替邀层。見UIView(UIViewGeometry)中的說明

  • anchorPoint在視圖左上角為(0,0),在視圖右下角為(1,1),默認(rèn)(0.5,0.5)。蘋果文檔中注釋是錯誤的(normalized layer coordinates - '(0, 0)' is the bottom left corner of the bounds rect)遂庄。

  • 如果更改了一個圖層的anchorPoint寥院,那么這個圖層會發(fā)生位移。iOS圍繞某點縮放或旋轉(zhuǎn)的AnchorPoint的設(shè)定

  • point涧团、anchorPoint和frame三者的關(guān)系:

position.x = frame.origin.x + anchorPoint.x * bounds.size.width只磷;

position.y = frame.origin.y + anchorPoint.y * bounds.size.height

這將是你最后一次糾結(jié)position與anchorPoint!

  • 修改position和anchorPoint會影響frame屬性泌绣。

2017-03-10

一钮追、iOS8.0之后的隊列優(yōu)先級 MBProgressHUD庫中有用到

dispatch_queue_create函數(shù),在iOS8之前阿迈,不能在創(chuàng)建時設(shè)定優(yōu)先級元媚,所以用dispatch_set_target_queue設(shè)置優(yōu)先級,另外苗沧,如果兩個隊列dispatch_set_target_queue到同一個隊列刊棕,DISPATCH_QUEUE_SERIAL串行、DISPATCH_QUEUE_CONCURRENT并行對兩個隊列也有作用待逞,可以參考demo中方法testGCDTarget;iOS 8之后用dispatch_queue_attr_make_with_qos_class直接創(chuàng)建隊列并設(shè)置優(yōu)先級等甥角;QOS_CLASS_USER_INITIATED:為iOS8之后的優(yōu)先級,其它優(yōu)先級為:

  • QOS_CLASS_USER_INTERACTIVE: user interactive等級表示任務(wù)需要被立即執(zhí)行以提供好的用戶體驗识樱。使用它來更新UI嗤无,響應(yīng)事件以及需要低延時的小工作量任務(wù)震束。這個等級的工作總量應(yīng)該保持較小規(guī)模。
  • QOS_CLASS_USER_INITIATED:user initiated等級表示任務(wù)由UI發(fā)起并且可以異步執(zhí)行当犯。它應(yīng)該用在用戶需要即時的結(jié)果同時又要求可以繼續(xù)交互的任務(wù)垢村。
  • QOS_CLASS_UTILITY:utility等級表示需要長時間運行的任務(wù),常常伴隨有用戶可見的進度指示器嚎卫。使用它來做計算嘉栓,I/O,網(wǎng)絡(luò)拓诸,持續(xù)的數(shù)據(jù)填充等任務(wù)侵佃。這個等級被設(shè)計成節(jié)能的。
  • QOS_CLASS_BACKGROUND:background等級表示那些用戶不會察覺的任務(wù)恰响。使用它來執(zhí)行預(yù)加載趣钱,維護或是其它不需用戶交互和對時間不敏感的任務(wù)涌献。

摘自:iOS用YYLabel中方法實現(xiàn)異步畫圖ChartView


2017-03-11

一胚宦、簡易音樂播放器(仿網(wǎng)易云音樂)

繞Z軸無限旋轉(zhuǎn)動畫代碼:

rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.duration = duration;
rotationAnimation.repeatCount = INFINITY;
rotationAnimation.toValue = @(M_PI * 2);
[self.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];

繼續(xù)旋轉(zhuǎn)和暫停旋轉(zhuǎn)代碼:

//繼續(xù)旋轉(zhuǎn)
CFTimeInterval pausedTime = [self.layer timeOffset];
self.layer.speed = 1.0;
self.layer.timeOffset = 0.0;
self.layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
self.layer.beginTime = timeSincePause;

//暫停旋轉(zhuǎn)
CFTimeInterval currTimeoffset = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil];
self.layer.speed = 0.0;
self.layer.timeOffset = currTimeoffset;
  • 暫停就是將layer的速度設(shè)置為0,將timeOffset設(shè)置為暫停時動畫進行的時間燕垃。
  • 繼續(xù)動畫就是將layer的速度設(shè)置為1枢劝,獲取暫停動畫時設(shè)置的timeOffset和動畫的運行時間,計算并設(shè)置動畫的beginTime卜壕。

二您旁、CABasicAnimation使用總結(jié)

防止動畫結(jié)束后回到初始狀態(tài)

transformAnima.removedOnCompletion = NO;
transformAnima.fillMode = kCAFillModeForwards;

解釋:為什么動畫結(jié)束后返回原狀態(tài)?
首先我們需要搞明白一點的是轴捎,layer動畫運行的過程是怎樣的鹤盒?其實在我們給一個視圖添加layer動畫時,真正移動并不是我們的視圖本身侦副,而是 presentation layer 的一個緩存侦锯。動畫開始時 presentation layer開始移動,原始layer隱藏秦驯,動畫結(jié)束時尺碰,presentation layer從屏幕上移除,原始layer顯示译隘。這就解釋了為什么我們的視圖在動畫結(jié)束后又回到了原來的狀態(tài)亲桥,因為它根本就沒動過。
這個同樣也可以解釋為什么在動畫移動過程中固耘,我們?yōu)楹尾荒軐ζ溥M行任何操作题篷。
所以在我們完成layer動畫之后,最好將我們的layer屬性設(shè)置為我們最終狀態(tài)的屬性厅目,然后將presentation layer 移除掉番枚。


2017-03-12

一偿枕、UISlider使用總結(jié)

1.UISlider默認(rèn)track的高度是2,怎么修改其高度户辫?
重寫其- (CGRect)trackRectForBounds:(CGRect)bounds方法

- (CGRect)trackRectForBounds:(CGRect)bounds
{
    return CGRectMake(0, (bounds.size.height - 2) * 0.5, bounds.size.width, 2);
}

2.UISlider默認(rèn)的thumb的中心點不能滑動到UISlider的起點和終點渐夸,怎么做到像網(wǎng)易云音樂那樣可以滑動到起點和終點?

重寫其- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value方法:

- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value
{
    CGRect frame = [super thumbRectForBounds:bounds trackRect:rect value:value];
    CGFloat progress = value / (self.maximumValue - self.minimumValue);
    CGFloat pastX = progress * self.frame.size.width;
    frame.origin.x = pastX - frame.size.width * 0.5;
    return frame;
}

3.如果像網(wǎng)易云音樂那樣拖拽UISlider的時候只更新時間渔欢,不播放對應(yīng)時間點的音頻墓塌。而在拖拽結(jié)束后才播放該時間點處的音頻?

綁定UISlider的UIControlEventTouchUpInside|UIControlEventTouchUpOutside事件可監(jiān)聽拖拽結(jié)束奥额。

sliderValueChanged:方法處更新時間苫幢。sliderTouchUp:方法處開始播放。

[_slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
[_slider addTarget:self action:@selector(sliderTouchUp:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末垫挨,一起剝皮案震驚了整個濱河市韩肝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌九榔,老刑警劉巖哀峻,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哲泊,居然都是意外死亡剩蟀,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門切威,熙熙樓的掌柜王于貴愁眉苦臉地迎上來育特,“玉大人,你說我怎么就攤上這事先朦$衷” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵喳魏,是天一觀的道長棉浸。 經(jīng)常有香客問我,道長截酷,這世上最難降的妖魔是什么涮拗? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮迂苛,結(jié)果婚禮上三热,老公的妹妹穿的比我還像新娘。我一直安慰自己三幻,他們只是感情好就漾,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著念搬,像睡著了一般抑堡。 火紅的嫁衣襯著肌膚如雪摆出。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天首妖,我揣著相機與錄音偎漫,去河邊找鬼。 笑死有缆,一個胖子當(dāng)著我的面吹牛象踊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播棚壁,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼杯矩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了袖外?” 一聲冷哼從身側(cè)響起史隆,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎曼验,沒想到半個月后泌射,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡蚣驼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年魄幕,在試婚紗的時候發(fā)現(xiàn)自己被綠了相艇。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颖杏。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖坛芽,靈堂內(nèi)的尸體忽然破棺而出留储,到底是詐尸還是另有隱情,我是刑警寧澤咙轩,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布获讳,位于F島的核電站,受9級特大地震影響活喊,放射性物質(zhì)發(fā)生泄漏丐膝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一钾菊、第九天 我趴在偏房一處隱蔽的房頂上張望帅矗。 院中可真熱鬧,春花似錦煞烫、人聲如沸浑此。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凛俱。三九已至紊馏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蒲犬,已是汗流浹背朱监。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留原叮,地道東北人赌朋。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像篇裁,于是被迫代替她去往敵國和親沛慢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容