MVC,MVVM
M<--->C<--->V
M<--->VM<--->V
VM負責的部分 將 model里屬性值 部分,處理成view顯示的部分,同時兼顧從網(wǎng)絡(luò),資源庫等地方獲取數(shù)據(jù),view部分不直接和model產(chǎn)生關(guān)系,自負責利用viewmodel 暴露的方式,接口來獲取顯示的內(nèi)容
KVO
原理 重寫子類set方法
在valueWillChange和valueDidChange之間,調(diào)用父類set方法改變屬性值,然后通過obver....回調(diào)方法通知監(jiān)聽者被監(jiān)聽的屬性發(fā)生改變
在NSOperation 中修改isFinish 來手動調(diào)用kvo的valueWillChange和valueDidChange來實現(xiàn)對隊列任務(wù)的控制 詳解
自定義 kvo
自定義通知
Runtime
swizzle 原理
每一個方法 Method 是結(jié)構(gòu)體包含著 sel(方法編號選擇器) IMP 方法指針
通過sel找到對應(yīng)的imp 通過imp去調(diào)用具體的方法
swizzle 是將sel對應(yīng)的imp進行交換, 假設(shè)系統(tǒng)中是selector1 對應(yīng) imp1 我們自定義的是selector2 對用的 imp2 通過method_exchangeImplemetation(Method m1,Method m2)將 selector1 指向imp2 selector2指向imp1
添加方法
class_addMethod(class, origSelector,method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
此方法要寫在+load里 原因,+load方法是在類加載時候調(diào)用,執(zhí)行較早,系統(tǒng)調(diào)用,唯一性,不用擔心資源搶奪問題
調(diào)動未實現(xiàn)的方法會發(fā)生crash,補救措施(objc_msgForward,是用于消息轉(zhuǎn)發(fā)的:當向一個對象發(fā)送一條消息虏冻,但它并沒有實現(xiàn)的的候元潘,_objc_msgForward會嘗試做消息轉(zhuǎn)發(fā)鲫咽。)
1 首先會調(diào)用 +(BOOL)resolveInstanceMethod 或者+(BOOL)resolveClassMethod 方法 允許動態(tài)添加未實現(xiàn)的方法,進行補救.只要沒有通過class_addMethod添加對應(yīng)的方法,就會進行下一步,eg:
+(BOOL)resolveInstanceMethod:(SEL)sel{
BOOL isFinish = [super resolveInstanceMethod:sel];
if (sel == NSSelectorFromString(@"testsss")) {
class_addMethod([self class], sel, (IMP)sss, "v@:");
isFinish = YES;
}
return isFinish;
}
2 調(diào)用-(id)forwardingTagetForselector ,嘗試找到一個能響應(yīng)該消息的對象坷衍。如果獲取到撇吞,直接返回該對象 eg:
-(id)forwardingTargetForSelector:(SEL)aSelector{
if(aSelector == NSSelectorFromString(@"test"))
Class class = NSClassFromString(@"Test");
return class;
}
return nil;
}
3 調(diào)用methodSigntureForSelector 嘗試獲得一個方法簽名酒甸。如果獲取不到浮声,則直接調(diào)用doesNotRecognizeSelector拋出異常虚婿。如果能獲取,則返回該方法簽名 eg:
if (aSelector == NSSelectorFromString(@"test")) {
Class class = NSClassFromString(@"Test");
return [NSMethodSignature signatureWithObjCTypes:method_getTypeEncoding(class_getInstanceMethod(class, aSelector))];
}
4 調(diào)用forwardInvocation:方法 利用第三步返回的方法簽名,通過NSInvocation 實現(xiàn)對應(yīng)的方法 eg:
-(void)forwardInvocation:(NSInvocation *)anInvocation{
Class class = NSClassFromString(@"Test");
[anInvocation invokeWithTarget:[[class alloc] init]];
}
GCD
線程之間的通信
[self performSelectorOnMainThread:@selector(dothing:) withObject:@[@"1"] waitUntilDone:YES];
[self performSelector:@selector(dothing:) onThread:thread withObject:nil waitUntilDone:YES];
同步任務(wù): 優(yōu)先級高泳挥,在線程中有執(zhí)行順序然痊,不會開啟新的線程
異步任務(wù): 優(yōu)先級低,在線程中執(zhí)行沒有順序屉符,看cpu閑不閑剧浸。在主隊列中不會開啟新的線程锹引,其他隊列會開啟新的線程,(串行開啟一條線程,并行開啟多條線程)
隊列分為 [串行隊列] 和 [并行隊列] :
串行隊列:隊列中的線程按順序執(zhí)行(不會同時執(zhí)行)
并行隊列:隊列中的線程會并發(fā)執(zhí)行(同時執(zhí)行
串行與并行針對的是隊列,而同步與異步唆香,針對的則是線程
多個請求完成后統(tǒng)一刷新頁面 ,思路:利用group,創(chuàng)建任務(wù)組
通過 dispach_group_enter,通知任務(wù)進入group中,通過dispach_group_leave 通知任務(wù)完成離開group,最后通過dispach_group_notify來通知主線程刷新頁面,eg:
NSURLSession *session = [NSURLSession sharedSession];
dispatch_group_t dispatchGroup = dispatch_group_create();
dispatch_group_enter(dispatchGroup);
NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"任務(wù)1完成");
dispatch_group_leave(dispatchGroup);
}];
[task resume];
dispatch_group_enter(dispatchGroup);
NSURLSessionDataTask *task2 = [session dataTaskWithURL:[NSURL URLWithString:@"https://www.baidu.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"任務(wù)2完成");
dispatch_group_leave(dispatchGroup);
}];
[task2 resume];
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
NSLog(@"end");
});
}
dispatch_group_t group = dispatch_group_create();
NSMutableArray *arr = [NSMutableArray array];
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL);
for (NSInteger i = 0; i<20; i++) {
dispatch_group_async(group, queue, ^(){
dispatch_group_enter(group);
NSLog(@"請求%zd",i);
sleep(3);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[arr addObject:@(i)];
dispatch_group_leave(group);
});
});
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"%zd",arr.count);
});
內(nèi)存管理
SQL
網(wǎng)絡(luò)層通訊
4層網(wǎng)絡(luò)結(jié)構(gòu)
應(yīng)用層(http) 傳輸層(TCP,UDP) 網(wǎng)絡(luò)層(IP協(xié)議) 數(shù)據(jù)鏈路層(網(wǎng)絡(luò)傳輸,路由中轉(zhuǎn))
tcp/udp區(qū)別
tcp建立連接3次握手,斷開連接4次握手,安全穩(wěn)定不會丟包,適合數(shù)據(jù)量大的情況,速度較慢
udp不需要建立連接直接傳輸,速度快,但不穩(wěn)定,容易發(fā)生丟包的問題
http/https區(qū)別
Cocoapods
install和update 區(qū)別
需要增加或移除某一個或多個pods時嫌变,需要使用pod install
1.每一次執(zhí)行pod install命令-下載安裝新的pods-每一個pod的版本都會被記錄在Podfile.lock文件中。這個文件追蹤每個pod的安裝版本并且將它鎖定
2.使用pod install時躬它,它只是解決了之前未列入Podfile.lock的文件中的pods的依賴關(guān)系腾啥。
對于那些已經(jīng)出現(xiàn)在Podfile.lock文件中的pods,它只會下載該文件中指定版本的pod冯吓,并不會去檢索是否存在新的版本
對于Podfile.lock文件中還沒有鎖住版本的新增pod倘待,它會按照Podfile文件中描述的方式去搜索匹配的版本
需要更新這個pods的版本時,需要使用pod update
CocoaPods會去找到指定PODNAME的更新组贺,不再從Podfile.lock列表中的版本作比對凸舵,它會盡可能的更新到最新版本(前提是新版本和你在Podfile中所設(shè)的約束匹配)。
在測試的時候引入這個框架失尖,而release不引入啊奄,podfile文件中需要怎么寫呢?
pod 'afnxxx', :configurations => ['Debug']
git命令
git命令
rebase作用,合并解決沖突
rebase和merge區(qū)別