面試問(wèn)題:
本次時(shí)間:2017-1-6
前言:面試都會(huì)遇到各種各樣的人和各種各樣的問(wèn)題,以下是總結(jié)遇到的問(wèn)題的。大部分的問(wèn)題都是可以網(wǎng)上找到答案的。
有的沒(méi)有整理完善,等有空了再做更新。
1.get和post的區(qū)別
Http定義了與服務(wù)器交互的不同方法,最基本的方法有4種,分別是GET,POST,PUT,DELETE
(1)GET使用URL或Cookie傳參。而POST將數(shù)據(jù)放在BODY中。
(2)GET的URL會(huì)有長(zhǎng)度上的限制,則POST的數(shù)據(jù)則可以非常大。
(3)POST比GET安全,因?yàn)閿?shù)據(jù)在地址欄上不可見(jiàn)。
具體:
get請(qǐng)求和post請(qǐng)求都可以用于做獲取數(shù)據(jù)請(qǐng)求
在請(qǐng)求數(shù)據(jù)安全方面post請(qǐng)求比get請(qǐng)求安全
get是以明文的方式向服務(wù)器發(fā)送請(qǐng)求
post是包裝到請(qǐng)求體body中后,在向服務(wù)器發(fā)送請(qǐng)求
get請(qǐng)求的參數(shù)全部暴露在接口中,一般叫做明文請(qǐng)求或者傻瓜式請(qǐng)求,post請(qǐng)求的參數(shù)一般是以字典的方式進(jìn)行拼接,相對(duì)于get比較安全
如果從服務(wù)器獲取數(shù)據(jù),或者查詢數(shù)據(jù),使用get請(qǐng)求;如果上傳數(shù)據(jù)到服務(wù)器或者修改服務(wù)器上傳數(shù)據(jù)使用post請(qǐng)求
get請(qǐng)求的URL在使用過(guò)程中,會(huì)限制長(zhǎng)度,因此長(zhǎng)度非常長(zhǎng)的請(qǐng)求建議用
post請(qǐng)求
對(duì)文件大小的請(qǐng)求:get不允許向服務(wù)器上傳文件(圖片,pdf,音視頻)
2.runtime機(jī)制,具體使用;objc_class的屬性有哪些?在接手同事的一個(gè)項(xiàng)目時(shí),使用runtime打印出每一個(gè)控制器的方法?或者是類別,都知道類別是不能添加屬性的,但是想給它添加成員屬性,runtime怎么做?
成員變量操作
// 1. 獲取類中指定名稱實(shí)例成員變量的信息
Ivar class_getInstanceVariable ( Class cls, const char *name );
// 2. 獲取類成員變量的信息
Ivar class_getClassVariable ( Class cls, const char *name );
// 3. 添加成員變量
BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types );
// 4. 獲取整個(gè)成員變量列表
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );
屬性操作函數(shù):
// 獲取指定的屬性
objc_property_t class_getProperty ( Class cls, const char *name );
// 獲取屬性列表
objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount );
// 為類添加屬性
BOOL class_addProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
// 替換類的屬性
void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
3.SDWebImage的源碼?他的原理是怎么樣?
4.在使用AFNetworking請(qǐng)求數(shù)據(jù)的時(shí)候,在一個(gè)頁(yè)面需要同時(shí)請(qǐng)求多個(gè)接口的數(shù)據(jù),需要在所有數(shù)據(jù)都請(qǐng)求成功后才能刷新tableview應(yīng)該怎么做?
5.內(nèi)存管理的基本機(jī)制或原理;原則有哪些?
原則:
MRC:
當(dāng)使用new、alloc或copy方法創(chuàng)建一個(gè)對(duì)象時(shí),該對(duì)象引用計(jì)數(shù)器為1。如果不需要使用該對(duì)象,可以向其發(fā)送release或autorelease消息,在其使用完畢時(shí)被銷毀。
ARC:無(wú)效
關(guān)鍵字:
assign: 默認(rèn)修飾符,表示簡(jiǎn)單賦值,一般用于(int, char,double,NSInteger等等)類型的基本數(shù)據(jù)類型.
readonly: 表示"只讀",只會(huì)生get方法.
readwrite: 表示"讀寫",會(huì)生成set,get方法. 默認(rèn)修飾符
setter: 指定set方法的新名字(給set方法起一個(gè)新的名字)
getter: 指定get方法的新名字(給get方法起一個(gè)新的名字)
copy: 所修飾的成員變量,在對(duì)成員變量使用set方法設(shè)置值時(shí),會(huì)將成員變量將要指向的對(duì)象重新復(fù)制一份,讓成員變量指向新復(fù)制的對(duì)象.
復(fù)制一個(gè)新的對(duì)象.(淺拷貝):字符串、block變量、使用copy
mutableCopy:復(fù)制的是一個(gè)指針地址.(深拷貝)
strong: 在arc中作業(yè)對(duì)象成員的默認(rèn)修飾符.
strong修飾的指針,指向一個(gè)對(duì)象,對(duì)象的引用計(jì)數(shù)加1.當(dāng)不再指向的對(duì)象銷毀時(shí),指針會(huì)發(fā)送release消息.weak:修飾的指針,指向一個(gè)對(duì)象,不會(huì)retain,當(dāng)指向的對(duì)象被銷毀時(shí),指針會(huì)自動(dòng)變?yōu)閚il;weak id<Delegate> delegate block用(copy).
unsafe_unretained,修飾的指針,指向一個(gè)對(duì)象,不會(huì)retain,當(dāng)指向的對(duì)象被銷毀時(shí),指針也不會(huì)變?yōu)閚il.
6.gcd、創(chuàng)建線程
GCD:是把任務(wù)放到隊(duì)列中執(zhí)行
任務(wù):同步、異步;同步是一個(gè)一個(gè)的執(zhí)行;異步是可以同時(shí)執(zhí)行多個(gè)
隊(duì)列:并發(fā)、串行;一個(gè)一個(gè)的執(zhí)行是并發(fā);可以同時(shí)多個(gè)執(zhí)行的是串行
dispatch_queue_t queue = dispatch_queue_create("test", nil);//創(chuàng)建一個(gè)隊(duì)列
dispatch_async(queue, ^{// 創(chuàng)建異步線程
for (int i = 0; i < 100; i++) {
NSLog(@"多線程6==%d",i);
}
NSLog(@"多線程");
//用多線程請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)
dispatch_sync(dispatch_get_main_queue(), ^{// 回到主線程
// 一般在主線程更新界面
});
});
[self mainThread]; //執(zhí)行主線程
7.二維碼使用的是第三方還是自己的,如何解決掃描圖像不清析的問(wèn)題?
- 生成二維碼
- 實(shí)例化二維碼濾鏡
- 恢復(fù)濾鏡的默認(rèn)屬性
- 將字符串轉(zhuǎn)換成NSData
- 通過(guò)KVC設(shè)置濾鏡inputMessage數(shù)據(jù),通過(guò)KVC設(shè)置濾鏡的 inputCorrectionLevel (容錯(cuò)率)
- 獲得濾鏡輸出的圖像
- 將CIImage轉(zhuǎn)換成UIImage,并放大顯示
- 通過(guò)位圖創(chuàng)建高清圖片
-
識(shí)別二維碼
- 創(chuàng)建一個(gè)上下文
- 創(chuàng)建一個(gè)探測(cè)器
- 轉(zhuǎn)換原圖片為 CIImage
- 獲取探測(cè)器識(shí)別的圖像特征
- 遍歷圖片特征, 獲取數(shù)據(jù)
- 繪制識(shí)別到的二維碼邊框
- 傳遞識(shí)別的數(shù)據(jù)給外界
-
掃描二維碼
實(shí)例化拍攝設(shè)備
設(shè)置輸入設(shè)備
-
設(shè)置元數(shù)據(jù)輸出處理對(duì)象
- 實(shí)例化拍攝元數(shù)據(jù)輸出
- 設(shè)置輸出數(shù)據(jù)代理
添加拍攝會(huì)話
啟動(dòng)會(huì)話
監(jiān)聽(tīng)元數(shù)據(jù)處理后的結(jié)果
8.藍(lán)牙技術(shù)的問(wèn)題?
9.https請(qǐng)求的問(wèn)題?
10.指針問(wèn)題?
11.設(shè)計(jì)模式
12.頁(yè)面加載的生命周期
- init-初始化程序
- viewDidLoad-加載視圖
- viewWillAppear-UIViewController對(duì)象的視圖即將加入窗口時(shí)調(diào)用;
- viewDidApper-UIViewController對(duì)象的視圖已經(jīng)加入到窗口時(shí)調(diào)用;
- viewWillDisappear-UIViewController對(duì)象的視圖即將消失、被覆蓋或是隱藏時(shí)調(diào)用;
- viewDidDisappear-UIViewController對(duì)象的視圖已經(jīng)消失、被覆蓋或是隱藏時(shí)調(diào)用;
13.程序的生命周期
- Not running: 未運(yùn)行,程序未啟動(dòng)
- Inactive:未激活:程序在前臺(tái)運(yùn)行,不過(guò)沒(méi)有接收到事件。在沒(méi)有事件處理情況下程序
通常停留在這個(gè)狀態(tài)- Active: 激活:程序在前臺(tái)運(yùn)行而且接收到了事件。這也是前臺(tái)的一個(gè)正常的模式
- Backgroud:后臺(tái):程序在后臺(tái)而且能執(zhí)行代碼,大多數(shù)程序進(jìn)入這個(gè)狀態(tài)后會(huì)在在這個(gè)
狀態(tài)上停留一會(huì)。時(shí)間到之后會(huì)進(jìn)入掛起狀態(tài)(Suspended)。有的程序經(jīng)過(guò)
特殊的請(qǐng)求后可以長(zhǎng)期處于Backgroud狀態(tài)- Suspended:掛起:程序在后臺(tái)不能執(zhí)行代碼。系統(tǒng)會(huì)自動(dòng)把程序變成這個(gè)狀態(tài)而且不會(huì)
發(fā)出通知。當(dāng)掛起時(shí),程序還是停留在內(nèi)存中的,當(dāng)系統(tǒng)內(nèi)存低時(shí),系統(tǒng)就
把掛起的程序清除掉,為前臺(tái)程序提供更多的內(nèi)存。
//1. 告訴代理進(jìn)程啟動(dòng)但還沒(méi)進(jìn)入狀態(tài)保存
- (BOOL)application:(UIApplication *)application
willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
//2. 告訴代理啟動(dòng)基本完成程序準(zhǔn)備開(kāi)始運(yùn)行
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
//3. 當(dāng)應(yīng)用程序?qū)⒁敕腔顒?dòng)狀態(tài)執(zhí)行,在此期間,應(yīng)用程序不接收消息或事件,比如來(lái)電話了
- (void)applicationWillResignActive:(UIApplication *)application
//4. 當(dāng)應(yīng)用程序入活動(dòng)狀態(tài)執(zhí)行
- (void)applicationDidBecomeActive:(UIApplication *)application
//5. 當(dāng)程序被推送到后臺(tái)的時(shí)候調(diào)用。所以要設(shè)置后臺(tái)繼續(xù)運(yùn)行,則在這個(gè)函數(shù)里面設(shè)置即可
- (void)applicationDidEnterBackground:(UIApplication *)application
//6. 當(dāng)程序從后臺(tái)將要重新回到前臺(tái)時(shí)候調(diào)用
- (void)applicationWillEnterForeground:(UIApplication *)application
//7. 當(dāng)程序?qū)⒁顺鍪潜徽{(diào)用,通常是用來(lái)保存數(shù)據(jù)和一些退出前的清理工作。這個(gè)需要設(shè)置UIApplicationExitsOnSuspend的鍵值。
- (void)applicationWillTerminate:(UIApplication *)application
//8. 當(dāng)程序載入后執(zhí)行
- (void)applicationDidFinishLaunching:(UIApplication*)application
14.MVC模式
Model
- 模型對(duì)象封裝了應(yīng)用程序的數(shù)據(jù),并定義操控和處理該數(shù)據(jù)的邏輯和運(yùn)算
View
- 視圖對(duì)象是應(yīng)用程序中用戶可以看見(jiàn)的對(duì)象。視圖對(duì)象知道如何將自己繪制出來(lái),并可能對(duì)用戶的操作作出響應(yīng)
Controller
- 在應(yīng)用程序的一個(gè)或多個(gè)視圖對(duì)象和一個(gè)或多個(gè)模型對(duì)象之間,控制器對(duì)象充當(dāng)媒介??刂破鲗?duì)象因此是同步管道程序,通過(guò)它,視圖對(duì)象了解模型對(duì)象的更改,反之亦然。
總結(jié):
- Model和View永遠(yuǎn)不能相互通信,只能通過(guò)Controller傳遞。
- Controller可以直接與Model對(duì)話(讀寫調(diào)用Model),Model通過(guò)Notification和KVO機(jī)制與Controller間接通信。
- Controller可以直接與View對(duì)話,通過(guò)outlet,直接操作View,outlet直接對(duì)應(yīng)到View中的控件,View通過(guò)action向Controller報(bào)告事件的發(fā)生(如用戶Touch我了)。Controller是View的直接數(shù)據(jù)源(數(shù)據(jù)很可能是Controller從Model中取得并經(jīng)過(guò)加工了)。Controller是View的代理(delegate),以同步View與Controller。
15.MVVM模式
16.為什么block使用copy
當(dāng)用__block來(lái)修飾變量int aa = 10 的時(shí)候,在block內(nèi)部調(diào)用變量aa的時(shí)候,使用的是在相同內(nèi)存空間中修改過(guò)的變量aa的值,即變量aa的值從10修改為了100。那么此時(shí)打印aa得到的結(jié)果就是修改過(guò)的值100,且地址還是開(kāi)始聲明aa的時(shí)候所開(kāi)辟的內(nèi)存空間的地址
原因是:當(dāng)變量aa未使用__block修飾的時(shí)候,block會(huì)將“捕捉”到的變量復(fù)制一份,然后對(duì)復(fù)制品進(jìn)行操作。也就是說(shuō)預(yù)編譯的時(shí)候,block已經(jīng)把變量aa復(fù)制了一份出來(lái)(可以理解為重新聲明了一個(gè)同名的變量,此時(shí)的兩個(gè)變量在內(nèi)存中的地址是不同的),當(dāng)最后一句代碼執(zhí)行了block調(diào)用的時(shí)候,block內(nèi)部使用的是自己復(fù)制(本質(zhì)上是深拷貝)出來(lái)的一個(gè)變量
17.關(guān)于為什么使用weak而不是用assign來(lái)對(duì)delegate進(jìn)行標(biāo)注?
delegate一般的類型都是id,即可以指向所有對(duì)象的id類型。所以我們既可以使用assign指向他,也可以使用weak指向他。但是因?yàn)閣eak在不被持有的時(shí)候會(huì)指向nil,所有通過(guò)nil的方法在調(diào)用函數(shù)的時(shí)候,都會(huì)返回為nil,這樣就能夠保證了程序的穩(wěn)定性,就算沒(méi)有東西返回,他還是能夠正常解析(只是解析出來(lái)的值為nil)。而如果使用assign的話,如果一不持有他。那么下次再調(diào)用它的時(shí)候,他將會(huì)指向一個(gè)不知名的地址,即野指針。這樣就會(huì)使得整個(gè)程序crash。
18.數(shù)據(jù)持久化的區(qū)別,什么時(shí)候使用哪一個(gè)效果更好?
分為四類:
- 文件、或是沙盒目錄存儲(chǔ):分三個(gè)目錄
- DocumentsiTunes同步該應(yīng)用時(shí)會(huì)同步此文件夾中的內(nèi)容,適合存儲(chǔ)重要數(shù)據(jù).
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
- Library/Caches: iTunes不會(huì)同步此文件夾,適合存儲(chǔ)體積大,不需要備份的非重要數(shù)據(jù).
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
- Library/Preferences: iTunes同步該應(yīng)用時(shí)會(huì)同步此文件夾中的內(nèi)容,通常保存應(yīng)用的設(shè)置信息。
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
- /tmp: iTunes不會(huì)同步此文件夾,系統(tǒng)可能在應(yīng)用沒(méi)運(yùn)行時(shí)就刪除該目錄下的文件,所以此目錄適合保存應(yīng)用中的一些臨時(shí)文件,用完就刪除.
NSString *path = NSTemporaryDirectory();
NSString *filePath = [[self getDocumentPath] stringByAppendingString:@"fileTest.txt"];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"3316368400@qq.com", @"email", @"3316368400@qq.com", @"emailDisplay", nil];
[dictionary writeToFile:filePath atomically:YES];
- 歸檔(NSKeyedArchiver)
歸檔(又名序列化),把對(duì)象轉(zhuǎn)為字節(jié)碼,以文件的形式存儲(chǔ)到磁盤上,程序運(yùn)行過(guò)程中或者再次重新打開(kāi)程序的時(shí)候,可以通過(guò)解歸檔(返序列化)還原這些對(duì)象。
- 歸檔的對(duì)象是Foundation框架中的對(duì)象
- 歸檔和解歸檔其中任意對(duì)象都需要?dú)w檔和解歸檔整個(gè)文件
歸檔后的文件是加密的,所以歸檔文件的擴(kuò)展名可以隨意取- 在帶鍵的歸檔中,每個(gè)歸檔都有一個(gè)key值,解歸檔時(shí)key值要與歸檔時(shí)key值匹配
- 如果一個(gè)自定義的類A,作為另一個(gè)自定義類B的一個(gè)屬性存在;那么,如果要對(duì)B進(jìn)行歸檔,那么,B要實(shí)現(xiàn)NSCoding協(xié)議。并且,A也要實(shí)現(xiàn)NSCoding協(xié)議.
[NSKeyedArchiver archiveRootObject:obj toFile:appSettingPath];//會(huì)調(diào)用對(duì)象的encodeWithCoder方法
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_name forKey:kAddressCardName];
[aCoder encodeObject:_emailObj forKey:kAddressCardEmail];
[aCoder encodeInteger:_salary forKey:kAddressCardSalary];
}
[NSKeyedUnarchiver unarchiveObjectWithFile:appSettingPath];//會(huì)調(diào)用對(duì)象的initWithCoder方法
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
_name = [aDecoder decodeObjectForKey:kAddressCardName];
_emailObj = [aDecoder decodeObjectForKey:kAddressCardEmail];
_salary = [aDecoder decodeIntegerForKey:kAddressCardSalary];
return self;
}
3. 屬性列表(NSUserDefaults)
NSUserDefaults支持基本數(shù)據(jù)類型:NSNumber(NSInteger、float、double),NSString,NSDate,NSArray,NSDictionary,BOOL,NSData.
- 應(yīng)用域(application domain)是最重要的域,它存儲(chǔ)著你app通過(guò)NSUserDefaults set...forKey添加的設(shè)置。
- 注冊(cè)域(registration domain)僅有較低的優(yōu)先權(quán),只有在應(yīng)用域沒(méi)有找到值時(shí)才從注冊(cè)域去尋找。
- 全局域(global domain)則存儲(chǔ)著系統(tǒng)的設(shè)置
- 語(yǔ)言域(language-specific domains)則包括地區(qū)、日期等
- 參數(shù)域(argument domain)有最高優(yōu)先權(quán)
注意:
偏好設(shè)置是專門用來(lái)保存應(yīng)用程序的配置信息的,一般不要在偏好設(shè)置中保存其他數(shù)據(jù)。
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"marlonxlj" forKey:@"userName"];
[defaults setInteger:28 forKey:@"Age"];
//同步
[defaults synchronize];
4. 數(shù)據(jù)庫(kù)(SQLite、CoreData、第三方類庫(kù)
主要存儲(chǔ)大文件,數(shù)據(jù)量大的時(shí)候采用.
coreData:它使開(kāi)發(fā)者可以把數(shù)據(jù)當(dāng)做對(duì)象來(lái)操作,而不必在乎數(shù)據(jù)在磁盤中的存儲(chǔ)方式。
- 持久化存儲(chǔ)協(xié)調(diào)器NSPersistentStoreCoordinator
- 托管對(duì)象模型NSManagedObjectModel
- 托管對(duì)象上下文NSManagedObjectContext
模型文件操作
1.1 創(chuàng)建模型文件,后綴名為.xcdatamodeld。創(chuàng)建模型文件之后,可以在其內(nèi)部進(jìn)行添加實(shí)體等操作(用于表示數(shù)據(jù)庫(kù)文件的數(shù)據(jù)結(jié)構(gòu))
1.2 添加實(shí)體(表示數(shù)據(jù)庫(kù)文件中的表結(jié)構(gòu)),添加實(shí)體后需要通過(guò)實(shí)體,來(lái)創(chuàng)建托管對(duì)象類文件。
1.3 添加屬性并設(shè)置類型,可以在屬性的右側(cè)面板中設(shè)置默認(rèn)值等選項(xiàng)。(每種數(shù)據(jù)類型設(shè)置選項(xiàng)是不同的)
1.4 創(chuàng)建獲取請(qǐng)求模板、設(shè)置配置模板等。
1.5 根據(jù)指定實(shí)體,創(chuàng)建托管對(duì)象類文件(基于NSManagedObject的類文件)
實(shí)例化上下文對(duì)象
2.1 創(chuàng)建托管對(duì)象上下文(NSManagedObjectContext)
2.2 創(chuàng)建托管對(duì)象模型(NSManagedObjectModel)
2.3 根據(jù)托管對(duì)象模型,創(chuàng)建持久化存儲(chǔ)協(xié)調(diào)器(NSPersistentStoreCoordinator)
2.4 關(guān)聯(lián)并創(chuàng)建本地?cái)?shù)據(jù)庫(kù)文件,并返回持久化存儲(chǔ)對(duì)象(NSPersistentStore)
2.5 將持久化存儲(chǔ)協(xié)調(diào)器賦值給托管對(duì)象上下文,完成基本創(chuàng)建。
// 從應(yīng)用程序包中加載模型文件
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
// 傳入模型對(duì)象,初始化持久化存儲(chǔ)協(xié)調(diào)器
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
// 構(gòu)建SQLite數(shù)據(jù)庫(kù)文件的路徑
NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSURL *url = [NSURL fileURLWithPath:[docs stringByAppendingString:@"person"]];
// 添加持久化存儲(chǔ)器,用sqlite作為存儲(chǔ)庫(kù)
NSError *error = nil;
NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error];
if(store == nil)
{
[NSException raise:@"添加數(shù)據(jù)庫(kù)失敗" format:@"%@", [error localizedDescription]];
}
// 創(chuàng)建托管對(duì)象上下文
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
context.persistentStoreCoordinator = psc;
NSManagedObject *card = [NSEntityDescription insertNewObjectForEntityForName:@"Card" inManagedObjectContext:context];
[card setValue:@"4768558865" forKey:@"no"];
[person setValue:card forKey:@"card"];
// 利用上下文對(duì)象,將數(shù)據(jù)同步到持久化存儲(chǔ)庫(kù)
NSError *errorSave = nil;
BOOL sucess = [context save:&errorSave];
// 從數(shù)據(jù)庫(kù)查詢數(shù)據(jù)
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:context];
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO];
request.sortDescriptors = [NSArray arrayWithObject:sort];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like %@", @"MJ55*"];
request.predicate = predicate;
// 執(zhí)行請(qǐng)求
NSError *errorFetch = nil;
NSArray *objs = [context executeFetchRequest:request error:&errorFetch];
if(errorFetch)
{
[NSException raise:@"查詢錯(cuò)誤" format:@"%@", [errorFetch localizedDescription]];
}
19.copy、mutableCopy區(qū)別?
[對(duì)象:copy]
[對(duì)象:mutableCopy]
對(duì)于不可變對(duì)象,copy只是拷貝了對(duì)象的地址.mutableCopy才是拷貝了一個(gè)新的對(duì)象.
對(duì)于可變對(duì)象,copy,mutableCopy都是拷貝一個(gè)新的對(duì)象.
[注]對(duì)于自定義類的對(duì)象不是隨便就可以使用copy,mutableCopy拷貝一個(gè)新對(duì)象,自定義類必須遵從NSCoping/NSMutableCopy協(xié)議.并且實(shí)現(xiàn)協(xié)議中的copyWithZone:/mutableCopyWithZone:方法.這樣才可以實(shí)現(xiàn)對(duì)自定義對(duì)象的拷貝.
對(duì)于不可變對(duì)象,copy是淺拷貝,mutableCopy是深拷貝.
對(duì)于可變對(duì)象:copy,mutableCopy都是深拷貝.
20.runloop如何喚醒?比如當(dāng)程序開(kāi)始運(yùn)行的時(shí)候去檢測(cè)一個(gè)沙盒目錄的文件
應(yīng)用場(chǎng)景舉例:主線程的 RunLoop 里有兩個(gè)預(yù)置的 Mode:kCFRunLoopDefaultMode 和 UITrackingRunLoopMode。這兩個(gè) Mode 都已經(jīng)被標(biāo)記為"Common"屬性。DefaultMode 是 App 平時(shí)所處的狀態(tài),TrackingRunLoopMode 是追蹤 ScrollView 滑動(dòng)時(shí)的狀態(tài)。當(dāng)你創(chuàng)建一個(gè) Timer 并加到 DefaultMode 時(shí),Timer 會(huì)得到重復(fù)回調(diào),但此時(shí)滑動(dòng)一個(gè)TableView時(shí),RunLoop 會(huì)將 mode 切換為 TrackingRunLoopMode,這時(shí) Timer 就不會(huì)被回調(diào),并且也不會(huì)影響到滑動(dòng)操作。
CFRunLoopSourceRef 是事件產(chǎn)生的地方。Source有兩個(gè)版本:Source0 和 Source1。
? Source0 只包含了一個(gè)回調(diào)(函數(shù)指針),它并不能主動(dòng)觸發(fā)事件。使用時(shí),你需要先調(diào)用 CFRunLoopSourceSignal(source),將這個(gè) Source 標(biāo)記為待處理,然后手動(dòng)調(diào)用 CFRunLoopWakeUp(runloop) 來(lái)喚醒 RunLoop,讓其處理這個(gè)事件。
? Source1 包含了一個(gè) mach_port 和一個(gè)回調(diào)(函數(shù)指針),被用于通過(guò)內(nèi)核和其他線程相互發(fā)送消息。這種 Source 能主動(dòng)喚醒 RunLoop 的線程
CFRunLoopTimerRef 是基于時(shí)間的觸發(fā)器,它和 NSTimer 是toll-free bridged 的,可以混用。其包含一個(gè)時(shí)間長(zhǎng)度和一個(gè)回調(diào)(函數(shù)指針)。當(dāng)其加入到 RunLoop 時(shí),RunLoop會(huì)注冊(cè)對(duì)應(yīng)的時(shí)間點(diǎn),當(dāng)時(shí)間點(diǎn)到時(shí),RunLoop會(huì)被喚醒以執(zhí)行那個(gè)回調(diào)。
CFRunLoopObserverRef 是觀察者,每個(gè) Observer 都包含了一個(gè)回調(diào)(函數(shù)指針),當(dāng) RunLoop 的狀態(tài)發(fā)生變化時(shí),觀察者就能通過(guò)回調(diào)接受到這個(gè)變化。
系統(tǒng)默認(rèn)注冊(cè)了5個(gè)Mode:
- kCFRunLoopDefaultMode: App的默認(rèn) Mode,通常主線程是在這個(gè) Mode 下運(yùn)行的。
- UITrackingRunLoopMode: 界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動(dòng),保證界面滑動(dòng)時(shí)不受其他 Mode 影響。
- UIInitializationRunLoopMode: 在剛啟動(dòng) App 時(shí)第進(jìn)入的第一個(gè) Mode,啟動(dòng)完成后就不再使用。
- GSEventReceiveRunLoopMode: 接受系統(tǒng)事件的內(nèi)部 Mode,通常用不到。
- kCFRunLoopCommonModes: 這是一個(gè)占位的 Mode,沒(méi)有實(shí)際作用。
20.Category中添加屬性和成員變量的區(qū)別?
objc_getAssociatedObject / objc_setAssociatedObject來(lái)訪問(wèn)和生成關(guān)聯(lián)對(duì)象
#import <UIKit/UIKit.h>
@interface UIImage (XLJName)
@property (nonatomic, copy) NSString *XLJ_imageName;
@end
#import "UIImage+XLJName.h"
#import <objc/runtime.h>
static const void *XLJ_imageNameKey = &XLJ_imageNameKey;
@implementation UIImage (XLJName)
- (NSString *)XLJ_imageName
{
return objc_getAssociatedObject(self, XLJ_imageNameKey);
}
- (void)setXLJ_imageName:(NSString *)XLJ_imageName
{
objc_setAssociatedObject(self, XLJ_imageNameKey, XLJ_imageName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
21.iOS 中調(diào)用 self.name= 與 _name="" 的區(qū)別?
self.name =”object”:會(huì)調(diào)用對(duì)象的setName()方法;
name = “object”:會(huì)直接把object賦值給當(dāng)前對(duì)象的name屬性。
22.obj-c有私有方法嗎?私有變量嗎?
由于Objective-C的動(dòng)態(tài)消息傳遞機(jī)制,OC中不存在真正意義上的私有方法。
但是如果你不在.h文件中聲明,只在.m文件中實(shí)現(xiàn),或在.m文件的Class Extension里聲明,那么基本上和私有方法差不多。
23.MVC是什么設(shè)計(jì)模式,你還熟悉什么設(shè)計(jì)模式?
MVC是一種復(fù)合模式
(1)模型:模型持有所有的數(shù)據(jù)、狀態(tài)和程序邏輯。模型獨(dú)立于視圖和控制器。
(2)視圖:用來(lái)呈現(xiàn)模型。視圖通常直接從模型中取得它需要顯示的狀態(tài)與數(shù)據(jù)。對(duì)于相同的信息可以有多個(gè)不同的顯示形式或視圖。
(3)控制器:位于視圖和模型中間,負(fù)責(zé)接受用戶的輸入,將輸入進(jìn)行解析并反饋給模型,通常一個(gè)視圖具有一個(gè)控制器。
設(shè)計(jì)模式分為三大類:
1.創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
2.結(jié)構(gòu)型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
3.行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責(zé)任鏈模式、命令模式、備忘錄模式、狀態(tài)模式、訪問(wèn)者模式、中介者模式、解釋器模式。
4.并發(fā)型模式
5.線程池模式。
設(shè)計(jì)模式的六大原則:
總原則-開(kāi)閉原則
對(duì)擴(kuò)展開(kāi)放,對(duì)修改封閉。在程序需要進(jìn)行拓展的時(shí)候,不能去修改原有的代碼,而是要擴(kuò)展原有代碼,實(shí)現(xiàn)一個(gè)熱插拔的效果。所以一句話概括就是:為了使程序的擴(kuò)展性好,易于維護(hù)和升級(jí)。
想要達(dá)到這樣的效果,我們需要使用接口和抽象類等,后面的具體設(shè)計(jì)中我們會(huì)提到這點(diǎn)。
1、單一職責(zé)原則
不要存在多于一個(gè)導(dǎo)致類變更的原因,也就是說(shuō)每個(gè)類應(yīng)該實(shí)現(xiàn)單一的職責(zé),否則就應(yīng)該把類拆分。
2、里氏替換原則(Liskov Substitution Principle)
任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。里氏替換原則是繼承復(fù)用的基石,只有當(dāng)衍生類可以替換基類,軟件單位的功能不受到影響時(shí),基類才能真正被復(fù)用,而衍生類也能夠在基類的基礎(chǔ)上增加新的行為。
里氏代換原則是對(duì)“開(kāi)-閉”原則的補(bǔ)充。實(shí)現(xiàn)“開(kāi)閉”原則的關(guān)鍵步驟就是抽象化。而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里氏代換原則是對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范。里氏替換原則中,子類對(duì)父類的方法盡量不要重寫和重載。因?yàn)楦割惔砹硕x好的結(jié)構(gòu),通過(guò)這個(gè)規(guī)范的接口與外界交互,子類不應(yīng)該隨便破壞它。
3、依賴倒轉(zhuǎn)原則(Dependence Inversion Principle)
面向接口編程,依賴于抽象而不依賴于具體。寫代碼時(shí)用到具體類時(shí),不與具體類交互,而與具體類的上層接口交互。
4、接口隔離原則(Interface Segregation Principle)
每個(gè)接口中不存在子類用不到卻必須實(shí)現(xiàn)的方法,如果不然,就要將接口拆分。使用多個(gè)隔離的接口,比使用單個(gè)接口(多個(gè)接口方法集合到一個(gè)的接口)要好。
5、迪米特法則(最少知道原則)(Demeter Principle)
一個(gè)類對(duì)自己依賴的類知道的越少越好。無(wú)論被依賴的類多么復(fù)雜,都應(yīng)該將邏輯封裝在方法的內(nèi)部,通過(guò)public方法提供給外部。這樣當(dāng)被依賴的類變化時(shí),才能最小的影響該類。
最少知道原則的另一個(gè)表達(dá)方式是:只與直接的朋友通信。類之間只要有耦合關(guān)系,就叫朋友關(guān)系。耦合分為依賴、關(guān)聯(lián)、聚合、組合等。我們稱出現(xiàn)為成員變量、方法參數(shù)、方法返回值中的類為直接朋友。局部變量、臨時(shí)變量則不是直接的朋友。我們要求陌生的類不要作為局部變量出現(xiàn)在類中。
6、合成復(fù)用原則(Composite Reuse Principle)
盡量首先使用合成/聚合的方式,而不是使用繼承。
24.系統(tǒng)自帶的線程池(NSOpertionQueue)的作用?
凡是需要啟動(dòng)多個(gè)線程的地方都可以使用NSOpertionQueue,加入到NSOpertionQueue中的對(duì)象都需要繼承NSOpertion。 NSOpertionQueue會(huì)在系統(tǒng)內(nèi)部啟動(dòng)一個(gè)獨(dú)立線程去執(zhí)行這個(gè)被加入對(duì)象的main方法。
常用的地方是用nsoprationqueue 下載圖片,文件。如果是自己創(chuàng)建一個(gè)線程池,無(wú)非就是啟動(dòng)多個(gè)線程的時(shí)候,
把這些線程對(duì)象放到一個(gè)大數(shù)組中,如果需要啟動(dòng)線程的時(shí)候,先從數(shù)組中找空閑線程來(lái)使用。
自己管理線程池最大的難題是不好處理當(dāng)啟動(dòng)多個(gè)線程后,用戶在多個(gè)界面的跳轉(zhuǎn)的時(shí)候,對(duì)線程方法的回調(diào)管理。
而NSOpertionQueue可以很好的處理他。
25.類別有什么作用?繼承和類別在實(shí)現(xiàn)中有何區(qū)別?
category 可以在不獲悉,不改變?cè)瓉?lái)代碼的情況下往里面添加新的方法,只能添加,不能刪除修改。
category:類、種類
并且如果類別和原來(lái)類中的方法產(chǎn)生名稱沖突,則類別將覆蓋原來(lái)的方法,因?yàn)轭悇e具有更高的優(yōu)先級(jí).
類別跟類的優(yōu)先級(jí)
類別主要有3個(gè)作用:
(1)將類的實(shí)現(xiàn)分散到多個(gè)不同文件或多個(gè)不同框架中。
(2)創(chuàng)建對(duì)私有方法的前向引用。
(3)向?qū)ο筇砑臃钦絽f(xié)議。
繼承可以增加,修改或者刪除方法,并且可以增加屬性。
非正式協(xié)議:是使用類別category來(lái)實(shí)現(xiàn),非正式協(xié)議是NSObject的一個(gè)類別,這樣任何類的對(duì)象都可以作為委托對(duì)象來(lái)使用,它可以列出對(duì)象能夠執(zhí)行的所有方法,這樣用來(lái)實(shí)現(xiàn)委托, 我們可以使用選擇器來(lái)判斷該非正式協(xié)議中是否有這個(gè)方法。
正式協(xié)議:是一個(gè)命名的方法列表,與非正式協(xié)議相比不同的是,它要求顯示的采用協(xié)議,采用協(xié)議的方法是在類的
@interface聲明中列出協(xié)議的名稱,此時(shí),實(shí)現(xiàn)協(xié)議的類應(yīng)該遵守協(xié)議,承諾實(shí)現(xiàn)協(xié)議中的所有方法。
26.ios平臺(tái)怎么做數(shù)據(jù)的持久化?Coredata和sqlite有無(wú)必然聯(lián)系?coredata是一個(gè)關(guān)系型數(shù)據(jù)庫(kù)嗎?
比如寫入沙盒(其實(shí)是一個(gè)本應(yīng)用程序才可以訪問(wèn)的路徑),因?yàn)閟qlite是c語(yǔ)言的api。 你的問(wèn)題問(wèn)的是數(shù)據(jù)庫(kù)相關(guān),比如存到網(wǎng)絡(luò)上,還提供了一些管理的功能,比如寫入數(shù)據(jù)庫(kù),然而有人也需要obj-c 的api,core data不僅僅是把c的api翻譯成oc 的api,但從邏輯上又分成很多種, Core data與sqlite還是有聯(lián)系的,core data 是對(duì)sqlite的封裝,所以有了 core data 另外,使用更加方便數(shù)據(jù)的持久化本質(zhì)上都是就是寫文件,那么針對(duì)它討論
27.讓一個(gè)物體從界面的一個(gè)點(diǎn)到另一個(gè)點(diǎn),有哪些方法?
28.以下每行代碼執(zhí)行后,persion對(duì)象的retaion count是多少?
Persion *persion = [[Persion alloc] init];
NSLog(@"1---%lu--= 1", (unsigned long)persion.retainCount);
[persion retain];
NSLog(@"2---%lu -- = 2", (unsigned long)persion.retainCount);
[persion release];
NSLog(@"3---%lu --= 1", (unsigned long)persion.retainCount);
[persion release];
NSLog(@"4---%lu --= 1", (unsigned long)persion.retainCount);
29.你在開(kāi)發(fā)項(xiàng)目中時(shí),用到了哪些數(shù)據(jù)存儲(chǔ)方式,iphone中常見(jiàn)的方式有哪些,各有什么區(qū)別?
數(shù)據(jù)存儲(chǔ)五種形式的應(yīng)用范圍和性能區(qū)別
(core data, sqllite,對(duì)象序列化,文件直接讀寫,NSUserDefault(保存數(shù)據(jù)到temp文件夾中)) 文件直接讀寫 >core data> 對(duì)象序列化> sqllite>NSUserDefault.
代碼規(guī)范
- 命名規(guī)范
- 1). 常量的命名
- 2). 枚舉的命名
- 3). 變量和對(duì)象的命名
- 編碼規(guī)范:三個(gè)原則:可復(fù)用, 易維護(hù), 可擴(kuò)展
- 1). 判斷nil或者YES/NO
- 2). 條件賦值
- 3). 初始化方法
- 4). 定義屬性
- 5). BOOL賦值
- 拒絕死值
- 7). 復(fù)雜的條件判斷
- 8). 嵌套判斷
- 9). 參數(shù)過(guò)多
- 10). 回調(diào)方法
- Block的循環(huán)引用問(wèn)題
- __wealk
####??????如果對(duì)你有幫助,或覺(jué)得可以。請(qǐng)右上角star一下,這是對(duì)我一種鼓勵(lì),讓我知道我寫的東西有人認(rèn)可,我才會(huì)后續(xù)不斷的進(jìn)行完善。
###有任何問(wèn)題或建議請(qǐng)及時(shí)issues me,以便我能更快的進(jìn)行更新修復(fù)。
####Email: marlonxlj@163.com