1.簡(jiǎn)述OC中內(nèi)存管理機(jī)制
- 答:內(nèi)存管理機(jī)制:使用引用計(jì)數(shù)管理,分為ARC和MRC,MRC需要程序員自己管理內(nèi)存,ARC則不需要.但是并不是 所有對(duì)象在ARC環(huán)境下均不需要管理內(nèi)存,子線程和循環(huán)引用并不是這樣.與retain配對(duì)使用的是release,retain代表引用計(jì) 數(shù)+1,release代表引用計(jì)數(shù)-1,當(dāng)引用計(jì)數(shù)減為0時(shí),對(duì)象則被系統(tǒng)自動(dòng)銷毀.與alloc配對(duì)使用的是dealloc,alloc代表為對(duì)象開(kāi) 辟內(nèi)存空間,dealloc則代表銷毀對(duì)象的內(nèi)存空間.
2.readwrite,readonly,assign,retain,copy,nonatomic,atomic,strong,weak的作用?
- 答:讀寫(xiě)屬性:readonly和readwrite; 語(yǔ)義屬性:assign/retain/copy; 原子性:nonatomic.
① readwrite代表可讀,可寫(xiě),即有setter和getter方法,是默認(rèn)屬性.readonly代表只可讀,即只有g(shù)et方法,因?yàn)椴粫?huì)生成setter方法,所以它不可以和copy/retain/assign組合使用.
② weak和assign均是弱引用,assign修飾基本數(shù)據(jù)類型,weak修飾對(duì)象類型.strong和weak用于ARC下(ARC下的代理使用 weak,block塊使用copy).strong相當(dāng)于retain.weak相當(dāng)于assign;assign/retain/copy這些屬性用 于指定set訪問(wèn)器的語(yǔ)義,也就是說(shuō),這些屬性決定了以何種方式對(duì)數(shù)據(jù)成員賦值.
assign,直接賦值,引用計(jì)數(shù)不改變,適用于基本數(shù)據(jù)類型.
retain,淺拷貝,使用的是原來(lái)的內(nèi)存空間,只能適用于Objective-C對(duì)象類型,而不能適用于Core Foundation對(duì)象(retain會(huì)增加對(duì)象的引用計(jì)數(shù),而基本數(shù)據(jù)和Core Foundation對(duì)象都沒(méi)有引用計(jì)數(shù)).
copy:對(duì)象的拷貝,新申請(qǐng)一塊內(nèi)存空間,并把原始內(nèi)容復(fù)制到那片空間.新對(duì)象的引用計(jì)數(shù)為1,此屬性只對(duì)那些遵循了NSCopy協(xié)議的對(duì)象類型有效.③nonatomic,非原子性訪問(wèn),不加同步,是異步操作.默認(rèn)為atomic,原子操作,atomic是Objc使用的一種線程保護(hù)技術(shù),基本上來(lái) 講,是防止在寫(xiě)未完成的時(shí)候被另外一個(gè)線程讀取,造成數(shù)據(jù)錯(cuò)誤,而這種機(jī)制是消耗系統(tǒng)內(nèi)存資源的,所以在移動(dòng)端,都選擇nonatomic.
-
另: 內(nèi)存分為5個(gè)區(qū),分別是棧區(qū),堆區(qū),全局區(qū),文字常量區(qū),程序代碼區(qū).
- 棧區(qū):由編譯器自動(dòng)分配釋放,不需要管理內(nèi)存.
- 堆區(qū):一般有程序員分配釋放.
- 全局區(qū):存放全局變量和靜態(tài)變量.
- 文字常量區(qū):存放常量字符串.
- 程序代碼區(qū):存放二進(jìn)制代碼.
3.類變量的@protected,@private,@public,@package,聲明各有什么含義?
- @protected 受保護(hù)的.本類,子類可見(jiàn).
- @private 私有的,類內(nèi)可用
- @public 公有的,類內(nèi),子類,外部均可用
- @package 可見(jiàn)度在@protected和@public之間,這個(gè)類型最常用于框架類的實(shí)例變量.
4.線程是什么?進(jìn)程又是什么?區(qū)別和聯(lián)系.
- 進(jìn)程:正在運(yùn)行的程序,負(fù)責(zé)程序的內(nèi)存分配.
- 線程:線程是進(jìn)程中一個(gè)獨(dú)立執(zhí)行的控制單元(路徑),一個(gè)進(jìn)程至少包含一條線程,即主線程.
創(chuàng)建線程的目的:開(kāi)辟一條新的執(zhí)行路徑,運(yùn)行指定的代碼,與主線程的代碼實(shí)現(xiàn)同時(shí)執(zhí)行.
5.對(duì)多線程開(kāi)發(fā)的理解,iOS中有幾種實(shí)現(xiàn)多線程的方式.
- 多線程的使用場(chǎng)景:防止卡頓,可以同時(shí)完成多個(gè)任務(wù),且不影響主線程,把耗時(shí)操作放在子線程中執(zhí)行,但是會(huì)消耗內(nèi)存.
- 實(shí)現(xiàn)多線程的方式
- ①NSThread(內(nèi)存需要自己管理.觸發(fā))
- ②NSOperationQueue(不再關(guān)注線程,當(dāng)前可執(zhí)行任務(wù)個(gè)數(shù)queue.maxConcurrentOperationCount)
- ③GCD
詳解三種實(shí)現(xiàn)多線程的方式:
GCD:
GCD里面包含了串行隊(duì)列、并行隊(duì)列剖张、主隊(duì)列稼稿、全局隊(duì)列。
dispatch_queue_t q = dispatch_queue_create(“qqq”,DISPATCH_QUEUE_SERIAL);//創(chuàng)建一個(gè)串行隊(duì)列
dispatch_sync(q,^{
});//開(kāi)啟同步任務(wù)
dispatch_async(q,^{
})虱咧;//開(kāi)啟異步任務(wù)
并行隊(duì)列:DISPATCH_QUEUE_CONCURRENT
主隊(duì)列:dispatch_queue_t q = dispatch_get_main_queue();
全局隊(duì)列:dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
NSThread
獲取當(dāng)前線程:NSThread * current = [NSThread currentThread];
獲取主線程:NSThread * main = [NSThread mainThread];
使用NSThread創(chuàng)建線程的兩種方式:
- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
暫停當(dāng)前線程:
[NSThread sleepForTimeInterval:2];
NSOperationQueue
創(chuàng)建一個(gè)操作隊(duì)列:NSOperationQueue * queue = [[NSOperationQueue alloc]init];
添加NSOperation到NSOperationQueue中:[queue addOperation:operation];
添加一組operation:[queue addOperations:operations waitUntilFinished:NO];
添加一個(gè)block形式的operation:[queue addOperationWithBlock:^(){
}];
添加NSOperation的依賴對(duì)象:[operation2 addDependency:operation1];
設(shè)置隊(duì)列的最大操作數(shù):[queue setMaxConcurrentOperationCount:1];
等待options完成:[operation waitUntilFinished];
暫停、繼續(xù)queue:[queue setSuspended:YES] [queue setSuspend:NO]
6.線程同步和異步的區(qū)別?ios中如何實(shí)現(xiàn)線程的同步?
- 同步:任務(wù)順序執(zhí)行,下一個(gè)任務(wù)依賴于上一任務(wù)的完成.
- 異步:任務(wù)執(zhí)行順序不定,一起執(zhí)行.
- 實(shí)現(xiàn):設(shè)置依賴:NSOpreationQueue GCD中的串行隊(duì)列.
7.iOS類是否可以多繼承,如果沒(méi)有,怎么實(shí)現(xiàn)?
- 不可以多繼承.
- 可以通過(guò)類目,延展,協(xié)議實(shí)現(xiàn)多繼承.
- 類目:類目也叫分類,英文category,在沒(méi)有原類.m文件的基礎(chǔ)上,給該類添加方法.類目里不能添加實(shí)例變量,不 能添加和原始類方法名相同的方法,否則會(huì)發(fā)生覆蓋.一個(gè)類可以添加多個(gè)類目,類目中的方法可以成為原始類的一部分,和原始類方法級(jí)別相同,可以被子類繼 承.
- 延展:Extension,是一種特殊形式的類目,主要是在一個(gè)類的.m里面聲明與實(shí)現(xiàn).作用:就是給某類添加私有方法或者私有變量.
雖然延展是給一個(gè)類定義私有方法,但是OC沒(méi)有絕對(duì)的私有方法,其實(shí)還是可以調(diào)用的,延展里面聲明的變量只能在該類內(nèi)部 使用,外界訪問(wèn)不了.如果是新建文件建的的某類延展.h文件,則不能添加實(shí)例變量,如果括號(hào)里沒(méi)有類目名,則認(rèn)為延展里面的方法為全都必須實(shí)現(xiàn),如果有, 則可選實(shí)現(xiàn).
類目寫(xiě)的方法必須實(shí)現(xiàn),延展寫(xiě)的方法非必須.
8.棧和堆的區(qū)別?
- 棧:內(nèi)存系統(tǒng)管理(系統(tǒng)開(kāi)辟,系統(tǒng)釋放),先進(jìn)后出.
- 堆:內(nèi)存自己管理(自己開(kāi)辟,自己釋放).先進(jìn)先出.
9.iOS本地?cái)?shù)據(jù)存儲(chǔ)都有幾種方式?
- ①.NSkeyedArchiver:采用歸檔的形式來(lái)保存數(shù)據(jù),該數(shù)據(jù)對(duì)象需要遵守NSCoding協(xié)議,并且該對(duì)象 對(duì)應(yīng)的類必須提供encodeWithCoder:和initWithCoder:方法.前一個(gè)方法告訴系統(tǒng)怎么對(duì)對(duì)象進(jìn)行編碼,而后一個(gè)方法則是告訴系 統(tǒng)怎么對(duì)對(duì)象進(jìn)行解碼.
- ②.NSUserDefaults:用來(lái)保存應(yīng)用程序設(shè)置和屬性,用戶保存的數(shù)據(jù).用戶再次打開(kāi)程序或者開(kāi)機(jī)后這些數(shù)據(jù) 仍然存在.NSUserDefaults可以存儲(chǔ)的數(shù)據(jù)類型包 括:NSData,NSString,NSNumber,NSDate,NSArray.NSDictionary,其他類型的數(shù)據(jù)需要先行轉(zhuǎn)換.
- ③.Write寫(xiě)入方式:永久保存在磁盤中.具體:a.獲得文件保存的路徑.b.生成該路徑下的文件,c,往文件中寫(xiě)入數(shù)據(jù).d.從文件中讀出數(shù)據(jù).
- ④.SQLite:采用SQLite數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)數(shù)據(jù),SQLite作為一種輕量級(jí)數(shù)據(jù)庫(kù).具體:a.添加SQLite 相關(guān)的庫(kù)以及頭文件,b.使用數(shù)據(jù)庫(kù)存數(shù)數(shù)據(jù):打開(kāi)數(shù)據(jù)庫(kù),編寫(xiě)數(shù)據(jù)庫(kù)語(yǔ)句,執(zhí)行,關(guān)閉數(shù)據(jù)庫(kù).另:寫(xiě)入數(shù)據(jù)庫(kù),字符串可以采用char方式,而從數(shù)據(jù)庫(kù) 中取出char類型,當(dāng)char類型有表示中文字符時(shí),會(huì)出現(xiàn)亂碼,這是因?yàn)閿?shù)據(jù)庫(kù)默認(rèn)使用ascII編碼方式,所以想要正確從數(shù)據(jù)庫(kù)中取出中文,需要使 用NSString來(lái)接受從數(shù)據(jù)庫(kù)取出的字符串.
- ⑤.CoreData:原理是對(duì)SQLite的封裝,開(kāi)發(fā)者不需要接觸sql語(yǔ)句,就可以對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作.
10.ios動(dòng)態(tài)類型和動(dòng)態(tài)綁定
- 多態(tài):父類指針指向子類對(duì)象.
動(dòng)態(tài)類型:只有在運(yùn)行期,才能確定其真正類型.
動(dòng)態(tài)加載:根據(jù)不同的條件,加載不同的資源.32和64位.
11.深拷貝和淺拷貝的理解.
- 深拷貝;拷貝的內(nèi)容.
- 淺拷貝:拷貝的指針.
深拷貝如:
NSMutableDictionary * dic = [@{} mutableCopy];
NSMutableArray * ary = [@[] mutableCopy];
12.怎么實(shí)現(xiàn)一個(gè)singleton的類.
- 單例是一種設(shè)計(jì)模式,對(duì)象只有一個(gè).缺點(diǎn):對(duì)象不會(huì)被釋放,如果創(chuàng)建很多的話會(huì)占用很多內(nèi)存,優(yōu)點(diǎn):可以當(dāng)做工具類使用.
static SortDetailsModelDown * single = nil;
+(SortDetailsModelDown *)shareSortDetailsModelDown {
@synchronized(self){
if (!single) {
single = [[SortDetailsModelDown alloc]init]; }
} return single;
}
13.什么是安全釋放?
先釋放再置空.
14.RunLoop是什么?
事件循環(huán),是線程里面的一個(gè)組件.主線程的RunLoop是自動(dòng)開(kāi)啟的.分為:計(jì)時(shí)源(timer source),事件源(輸入源):input source.防止CPU中斷(保證程序執(zhí)行的線程不會(huì)被系統(tǒng)終止).
Runloop提供了一種異步執(zhí)行代碼的機(jī)制,并不能并行執(zhí)行任務(wù),是事件接收和分發(fā)機(jī)制的一個(gè)實(shí)現(xiàn).每一個(gè)線程都有其對(duì)應(yīng)的RunLoop,但是默認(rèn)非主線程的RunLoop是沒(méi)有運(yùn)行的,需要為RunLoop添加至少一個(gè)事件源,然后run它.
一般情況下我們是沒(méi)有必要去啟動(dòng)線程的RunLoop的,除非你在一個(gè)單獨(dú)的線程中需要長(zhǎng)時(shí)間的檢測(cè)某個(gè)事件.
RunLoop,正如其名所示,是線程進(jìn)入和被線程用來(lái)響應(yīng)事件以及調(diào)用事件處理函數(shù)的地方.
input source傳遞異步事件,通常是來(lái)自其他線程和不同程序的消息.
timer source傳遞同步事件.
當(dāng)有事件發(fā)生時(shí),RunLoop會(huì)根據(jù)具體的事件類型通知應(yīng)用程序作出響應(yīng).
當(dāng)沒(méi)有事件發(fā)生時(shí),RunLoop會(huì)進(jìn)入休眠狀態(tài),從而到達(dá)省電的目的.
當(dāng)事件再次發(fā)生時(shí),RunLoop會(huì)被重新喚醒,處理事件.
一般在開(kāi)發(fā)中很少會(huì)主動(dòng)創(chuàng)建RunLoop,而通常會(huì)把事件添加到RunLoop中.
15.什么是序列化和反序列化,可以用來(lái)做什么?如何在OC中實(shí)現(xiàn)復(fù)雜對(duì)象的存儲(chǔ).
序列化和反序列化:歸檔和反歸檔,進(jìn)行本地化,進(jìn)行數(shù)據(jù)存儲(chǔ).
CoreData:數(shù)據(jù)托管.有四種存儲(chǔ)方式:xml,sqlite,二進(jìn)制,內(nèi)存.
遵循NSCoding協(xié)議之后,進(jìn)行歸檔即可實(shí)現(xiàn)復(fù)雜對(duì)象的存儲(chǔ).
16.寫(xiě)一個(gè)標(biāo)準(zhǔn)宏MIN,這個(gè)宏輸入兩個(gè)參數(shù)并返回較小的一個(gè).
define MIN(A,B) (A)>(B)?(B):(A)
17.iPhone OS 有沒(méi)有垃圾回收機(jī)制,簡(jiǎn)易闡述一下OC內(nèi)存管理.
木有.引用計(jì)數(shù),ARC和MRC,swift(自動(dòng)引用計(jì)數(shù)).
18.簡(jiǎn)述應(yīng)用程序按HOME鍵進(jìn)入后臺(tái)時(shí)的生命周期,以及從后臺(tái)進(jìn)入前臺(tái)時(shí)的生命周期.
//前者:HOME->后臺(tái)
- (void)applicationWillResignActive:(UIApplication *)application
- (void)applicationDidEnterBackground:(UIApplication *)application
//后者:后臺(tái)->前臺(tái)
- (void)applicationWillEnterForeground:(UIApplication *)application
- (void)applicationDidBecomeActive:(UIApplication *)application
//另:各個(gè)程序運(yùn)行狀態(tài)時(shí)代理的回調(diào)
//告訴代理進(jìn)程啟動(dòng)但還沒(méi)進(jìn)入狀態(tài)保存
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
//告訴代理啟動(dòng)基本完成程序準(zhǔn)備開(kāi)始運(yùn)行
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
//當(dāng)應(yīng)用程序?qū)⒁敕腔顒?dòng)狀態(tài)執(zhí)行装黑,在此期間限番,應(yīng)用程序不接收消息或事件,比如來(lái)電話了
- (void)applicationWillResignActive:(UIApplication *)application
//當(dāng)應(yīng)用程序入活動(dòng)狀態(tài)執(zhí)行想幻,這個(gè)剛好跟上面那個(gè)方法相反
- (void)applicationDidBecomeActive:(UIApplication *)application
//當(dāng)程序被推送到后臺(tái)的時(shí)候調(diào)用粱栖。所以要設(shè)置后臺(tái)繼續(xù)運(yùn)行,則在這個(gè)函數(shù)里面設(shè)置即可
- (void)applicationDidEnterBackground:(UIApplication *)application
//當(dāng)程序從后臺(tái)將要重新回到前臺(tái)時(shí)候調(diào)用脏毯,這個(gè)剛好跟上面的那個(gè)方法相反闹究。
- (void)applicationWillEnterForeground:(UIApplication *)application
//當(dāng)程序?qū)⒁顺鍪潜徽{(diào)用,通常是用來(lái)保存數(shù)據(jù)和一些退出前的清理工作食店。這個(gè)需要要設(shè)置UIApplicationExitsOnSuspend的鍵值渣淤。
- (void)applicationWillTerminate:(UIApplication *)application
//當(dāng)程序載入后執(zhí)行
- (void)applicationDidFinishLaunching:(UIApplication*)application
在上面8個(gè)方法對(duì)應(yīng)的方法中鍵入NSLog打印。
現(xiàn)在啟動(dòng)程序看看執(zhí)行的順序:
- 啟動(dòng)程序
Log[40428:11303] willFinishLaunchingWithOptions
Log[40428:11303] didFinishLaunchingWithOptions
Log[40428:11303] applicationDidBecomeActive
- 按下home鍵
Log[40428:11303] applicationWillResignActive
Log[40428:11303] applicationDidEnterBackground
- 雙擊home鍵吉嫩,再打開(kāi)程序
Log[40428:11303] applicationWillEnterForeground
Log[40428:11303] applicationDidBecomeActive
19.ViewController的 alloc,loadView,viewDidLoad,viewWillAppear,viewDidUnload,dealloc,init分別是在 什么時(shí)候調(diào)用?在自定義ViewController的時(shí)候這幾個(gè)函數(shù)里面應(yīng)該做什么工作?
- alloc:申請(qǐng)內(nèi)存時(shí)調(diào)用.
- loadView:加載視圖時(shí)調(diào)用.
- viewDidLoad;視圖已經(jīng)加載后調(diào)用.
- viewWillAppear:視圖將要出現(xiàn)時(shí)調(diào)用.
- viewDidUnload:視圖已經(jīng)加載但是沒(méi)有加載出來(lái)時(shí)調(diào)用.
- dealloc:銷毀該視圖時(shí)調(diào)用.
- init;初始化該視圖時(shí)調(diào)用.
20.描述應(yīng)用程序的啟動(dòng)順序.
- a.程序入口main函數(shù)創(chuàng)建UIApplication實(shí)例和UIApplication代理實(shí)例.
- b.在UIApplication代理實(shí)例中重寫(xiě)啟動(dòng)方法,設(shè)置根ViewController
- c.在第一ViewController中添加控件,實(shí)現(xiàn)應(yīng)用程序界面.