本文記錄ios開發(fā)中的一些需要知道的細節(jié)厕妖,后期會持續(xù)更新首尼,有需要請關注。
入口函數(shù)int main(int argc, char * argv[])
argc
記錄了用戶在運行程序的命令行
中輸入的參數(shù)
的個數(shù)
言秸。
arg[]
指向的數(shù)組中至少有一個字符指針
软能,即arg[0].他通常指向程序中的可執(zhí)行文件
的文件名
。在有些版本的編譯器中還包括程序
文件所在的路徑举畸。
int argc
這個東東用來表示你在命令行下輸入命令的時候查排,一共有多少個參數(shù)。比方說你的程序編譯后抄沮,可執(zhí)行文件是test.exe
D:\tc2>test
這個時候跋核,argc
的值是1
但是
D:\tc2>test.exe myarg1 myarg2
的話,argc
的值是3合是。也就是 命令名
加上兩個參數(shù)了罪,一共三個參數(shù)
char *argv[]
這個東東用來取得你所輸入的參數(shù)
D:\tc2>test
這個時候,argc
的值是1聪全,argv[0]
的值是 "test"
D:\tc2>test myarg1 myarg2
這個時候泊藕,argc
的值是3,argc[0]
的值是"test",argc[1]
的值是"myarg1"娃圆,argc[2]
的值是"myarg2"玫锋。
這個東東一般用來為程序提供非常重要的信息,如:數(shù)據(jù)文件名讼呢,等等撩鹿。
如:copy a.c b.txt
這個時候,a.c和b.txt就是所謂的“非常重要的信息”悦屏。不指定這兩個文件节沦,你沒法進行拷貝。
當你的程序用到argc和argv這兩個參數(shù)的時候础爬,可以簡單地通過判斷argc的值甫贯,來看看程序的參數(shù)是否符合要求
exit()
是程序退出時的返回碼】囱粒可以用其他程序接收叫搁,判斷是否正常退出。如exit(-1)
認為異常開發(fā)
UIViewController生命周期
1:initialize函數(shù)并不會每次創(chuàng)建對象都調用供炎,只有在這個類第一次創(chuàng)建對象時才會調用渴逻,做一些類的準備工作,再次創(chuàng)建這個類的對象音诫,initalize方法將不會被調用惨奕,對于這個類的子類,如果實現(xiàn)了initialize方法纽竣,在這個子類第一次創(chuàng)建對象時會調用自己的initalize方法墓贿,之后不會調用,如果沒有實現(xiàn)蜓氨,那么它的父類將替它再次調用一下自己的initialize方法润文,以后創(chuàng)建也都不會再調用蜡峰。因此央星,如果我們有一些和這個相關的全局變量并鸵,可以在這里進行初始化担忧。
2:init方法和initCoder方法相似检号,只是被調用的環(huán)境不一樣焰望,如果用代碼進行初始化秕磷,會調用init锈颗,從nib文件或者歸檔進行初始化顷霹,會調用initCoder。
3:loadView方法是開始加載視圖的起始方法击吱,除非手動調用淋淀,否則在ViewController的生命周期中沒特殊情況只會被調用一次。
4:viewDidLoad方法是我們最常用的方法的覆醇,類中成員對象和變量的初始化我們都會放在這個方法中朵纷,在類創(chuàng)建后炭臭,無論視圖的展現(xiàn)或消失,這個方法也是只會在將要布局時調用一次袍辞。
5:viewWillAppear:視圖將要展現(xiàn)時會調用鞋仍。
6:viewWillLayoutSubviews:在viewWillAppare后調用,將要對子視圖進行布局搅吁。
7:viewDidLayoutSubviews:已經布局完成子視圖威创。
8:viewDidAppear:視圖完成顯示時調用。
9:viewWillDisappear:視圖將要消失時調用谎懦。
10:viewDidDisappear:視圖已經消失時調用那婉。
11:dealloc:controller被釋放時調用。
注意
:經過測試党瓮,從nib文件加載的controller详炬,只要不釋放,在每次viewWillAppare時都會調用layoutSubviews方法寞奸,有時甚至會在viewDidAppare后在調用一次layoutSubviews呛谜,而重點是從代碼加載的則只會在開始調用一次,之后都不會枪萄,所以注意隐岛,在layoutSubviews中寫相關的布局代碼十分危險。
線程同步異步瓷翻,隊列串行并發(fā)
1聚凹、 隊列分為串行和并行
2、 任務的執(zhí)行分為同步和異步
3齐帚、 隊列只是負責任務的調度妒牙,而不負責任務的執(zhí)行;任務是在線程中執(zhí)行的对妄。
隊列和任務的特點
隊列的特點:先進先出湘今,排在前面的任務最先執(zhí)行。
串行隊列:任務按照順序被調度剪菱,前一個任務不執(zhí)行完畢摩瞎,隊列不會調度。
并行隊列:只要有空閑的線程孝常,隊列就會調度當前任務旗们,交給線程去執(zhí)行,不需要考慮前面是都有任務在執(zhí)行构灸,只要有線程可以利用上渴,隊列就會調度任務。
主隊列:專門用來在主線程調度任務的隊列,所以主隊列的任務都要在主線程來執(zhí)行驰贷,主隊列會隨著程序的啟動一起創(chuàng)建盛嘿,我們只需get即可
全局隊列:是系統(tǒng)為了方便程序員開發(fā)提供的,其工作表現(xiàn)與并發(fā)隊列一致括袒,那么全局隊列跟并發(fā)隊列的區(qū)別是什么呢次兆?
1.全局隊列:無論ARC還是MRC都不需要考錄釋放,因為系統(tǒng)提供的我們只需要get就可以了
2.并發(fā)隊列:再MRC下锹锰,并發(fā)隊列創(chuàng)建出來后芥炭,需要手動釋放dispatch_release()
同步執(zhí)行:不會開啟新的線程,任務按順序執(zhí)行
異步執(zhí)行:會開啟新的線程恃慧,任務可以并發(fā)的執(zhí)行
同步和異步的區(qū)別
同步:在當前線程中執(zhí)行园蝠。
異步:在另一條線程中執(zhí)行。
同步和異步決定了要不要開啟新的線程痢士。
同步:在當前線程中執(zhí)行任務彪薛,不具備開啟新線程的能力。
異步:在新的線程中執(zhí)行任務怠蹂,具備開啟新線程的能力善延。
并發(fā)和串行決定了任務的執(zhí)行方式
并發(fā):多個任務并發(fā)(同時)執(zhí)行。
串行:一個任務執(zhí)行完畢后城侧,再執(zhí)行下一個任務易遣。
并發(fā)和并行
并發(fā)性(Concurrence):指兩個或兩個以上的事件或活動在同一時間間隔內發(fā)生。并發(fā)的實質是一個物理CPU(也可以多個物理CPU) 在若干道程序之間多路復用嫌佑,并發(fā)性是對有限物理資源強制行使多用戶共享以提高效率豆茫。
并行性(parallelism)指兩個或兩個以上事件或活動在同一時刻發(fā)生。在多道程序環(huán)境下屋摇,并行性使多個程序同一時刻可在不同CPU上同時執(zhí)行揩魂。
區(qū)別:一個處理器同時處理多個任務和多個處理器或者是多核的處理器同時處理多個不同的任務。
前者是邏輯上的同時發(fā)生(simultaneous)摊册,而后者是物理上的同時發(fā)生肤京。
兩者的聯(lián)系:
并行的事件或活動一定是并發(fā)的,但反之并發(fā)的事件或活動未必是并行的茅特。并行性是并發(fā)性的特例,而并發(fā)性是并行性的擴展棋枕。
單例創(chuàng)建(宏)
宏定義:
#define AH_SINGLETON_DEF(_type_) + (_type_ *)sharedInstance;\
+(instancetype) alloc __attribute__((unavailable("call sharedInstance instead")));\
+(instancetype) new __attribute__((unavailable("call sharedInstance instead")));\
-(instancetype) copy __attribute__((unavailable("call sharedInstance instead")));\
-(instancetype) mutableCopy __attribute__((unavailable("call sharedInstance instead")));\
#define AH_SINGLETON_IMP(_type_) + (_type_ *)sharedInstance{\
static _type_ *theSharedInstance = nil;\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
theSharedInstance = [[super alloc] init];\
});\
return theSharedInstance;\
}
宏使用:
@interface AHSingleton : NSObject
AH_SINGLETON_DEF(AHSingleton);
@end
@implementation DJSingleton
AH_SINGLETON_IMP(AHSingleton);
@end
以scheduledTimerWithTimeInterval的方式觸發(fā)的timer白修,在滑動頁面上的列表時,timer會暫停重斑,為什么兵睛?該如何解決?
原因在于滑動時當前線程的runloop切換了mode用于列表滑動,導致timer暫停祖很。
runloop中的mode主要用來指定事件在runloop中的優(yōu)先級笛丙,有以下幾種:
* Default(NSDefaultRunLoopMode):默認,一般情況下使用假颇;
* Connection(NSConnectionReplyMode):一般系統(tǒng)用來處理NSConnection相關事件胚鸯,開發(fā)者一般用不到;
* Modal(NSModalPanelRunLoopMode):處理modal panels事件笨鸡;
* Event Tracking(NSEventTrackingRunLoopMode):用于處理拖拽和用戶交互的模式姜钳。
* Common(NSRunloopCommonModes):模式合集。默認包括Default形耗,Modal哥桥,Event Tracking三大模式,可以處理幾乎所有事件激涤。
回到題中的情境拟糕。滑動列表時倦踢,runloop的mode由原來的Default模式切換到了Event Tracking模式送滞,timer原來好好的運行在Default模式中,被關閉后自然就停止工作了硼一。
解決方法其一是將timer加入到NSRunloopCommonModes中累澡。其二是將timer放到另一個線程中,然后開啟另一個線程的runloop般贼,這樣可以保證與主線程互不干擾愧哟,而現(xiàn)在主線程正在處理頁面滑動。示例代碼如下:
// 方法1
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
// 方法2
dispatch_async(dispatch_get_global_queue(0, 0), ^{
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(repeat:) userInfo:nil repeats:true];
[[NSRunLoop currentRunLoop] run];
});
objc中的類方法和實例方法有什么本質區(qū)別和聯(lián)系哼蛆?
類方法:
類方法是屬于類對象的
類方法只能通過類對象調用
類方法中的self是類對象
類方法可以調用其他的類方法
類方法中不能訪問成員變量
類方法中不能直接調用對象方法
實例方法:
實例方法是屬于實例對象的
實例方法只能通過實例對象調用
實例方法中的self是實例對象
實例方法中可以訪問成員變量
實例方法中直接調用實例方法
實例方法中也可以調用類方法(通過類名)
runtime如何通過selector找到對應的IMP地址蕊梧?(分別考慮類方法和實例方法)
每一個類對象中都一個方法列表,方法列表中記錄著方法的名稱,方法實現(xiàn),以及參數(shù)類型,其實selector本質就是方法名稱,通過這個方法名稱就可以在方法列表中找到對應的方法實現(xiàn).
如何用GCD同步若干個異步調用?(如根據(jù)若干個url異步加載多張圖片腮介,然后在都下載完成后合成一張整圖)
使用Dispatch Group追加block到Global Group Queue,這些block如果全部執(zhí)行完畢肥矢,就會執(zhí)行Main Dispatch Queue中的結束處理的block。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ /*加載圖片1 */ });
dispatch_group_async(group, queue, ^{ /*加載圖片2 */ });
dispatch_group_async(group, queue, ^{ /*加載圖片3 */ });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 合并圖片
});
dispatch_barrier_async的作用是什么叠洗?
在并行隊列中甘改,為了保持某些任務的順序,需要等待一些任務完成后才能繼續(xù)進行灭抑,使用 barrier 來等待之前任務完成十艾,避免數(shù)據(jù)競爭等問題。 dispatch_barrier_async 函數(shù)會等待追加到Concurrent Dispatch Queue并行隊列中的操作全部執(zhí)行完之后腾节,然后再執(zhí)行 dispatch_barrier_async 函數(shù)追加的處理忘嫉,等 dispatch_barrier_async 追加的處理執(zhí)行結束之后荤牍,Concurrent Dispatch Queue才恢復之前的動作繼續(xù)執(zhí)行。
打個比方:比如你們公司周末跟團旅游庆冕,高速休息站上康吵,司機說:大家都去上廁所,速戰(zhàn)速決访递,上完廁所就上高速晦嵌。超大的公共廁所,大家同時去力九,程序猿很快就結束了耍铜,但程序媛就可能會慢一些,即使你第一個回來跌前,司機也不會出發(fā)棕兼,司機要等待所有人都回來后,才能出發(fā)抵乓。 dispatch_barrier_async 函數(shù)追加的內容就如同 “上完廁所就上高速”這個動作伴挚。
(注意:使用 dispatch_barrier_async ,該函數(shù)只能搭配自定義并行隊列 dispatch_queue_t 使用灾炭。不能使用: dispatch_get_global_queue 茎芋,否則 dispatch_barrier_async 的作用會和 dispatch_async 的作用一模一樣。 )
蘋果為什么要廢棄dispatch_get_current_queue蜈出?
dispatch_get_current_queue容易造成死鎖
addObserver:forKeyPath:options:context:各個參數(shù)的作用分別是什么田弥,observer中需要實現(xiàn)哪個方法才能獲得KVO回調?
// 添加鍵值觀察
/*
1 觀察者铡原,負責處理監(jiān)聽事件的對象
2 觀察的屬性
3 觀察的選項
4 上下文
*/
[self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:@"Person Name"];
observer中需要實現(xiàn)一下方法:
// 所有的 kvo 監(jiān)聽到事件偷厦,都會調用此方法
/*
1. 觀察的屬性
2. 觀察的對象
3. change 屬性變化字典(新/舊)
4. 上下文,與監(jiān)聽的時候傳遞的一致
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)contex
IBOutlet連出來的視圖屬性為什么可以被設置成weak?
參考鏈接: Should IBOutlets be strong or weak under ARC?
文章告訴我們:
因為既然有外鏈那么視圖在xib或者storyboard中肯定存在燕刻,視圖已經對它有一個強引用了只泼。
不過這個回答漏了個重要知識,使用storyboard(xib不行)創(chuàng)建的vc卵洗,會有一個叫_topLevelObjectsToKeepAliveFromStoryboard的私有數(shù)組強引用所有top level的對象请唱,所以這時即便outlet聲明成weak也沒關系。