第一篇:黑馬程序員:IOS面試寶典之OC語言
OC語言(★★)
有人可能會問對于我們學iOS的同學來講,面試還會問Objective-C基礎嗎?答案是會的,但是不會太多,因此我給了兩顆星的重要程度。一般筆試的時候出現Objective-C基礎題的概率比較大,口頭面試的時候比較少,比如自己在面試的時候一些對基礎知識比較看重的面試官會深究著Objective-C基礎去問,比如Objective-C內存管理等等。
一、Objective-C語法
1.面向對象都有哪些特性以及你對這些特性的理解
繼承:繼承是從已有類得到繼承信息創建新類的過程。提供繼承信息的類被稱為父類(超類、基類);得到繼承信息的類被稱為子類(派生類)。繼承讓變化中的軟件系統有了一定的延續性,同時繼承也是封裝程序中可變因素的重要手段。
封裝:通常認為封裝是把數據和操作數據的方法綁定起來,對數據的訪問只能通過已定義的接口。面向對象的本質就是將現實世界描繪成一系列完全自治、封閉的對象。我們在類中編寫的方法就是對實現細節的一種封裝;我們編寫一個類就是對數據和數據操作的封裝。可以說,封裝就是隱藏一切可隱藏的東西,只向外界提供最簡單的編程接口。
多態性:多態性是指允許不同子類型的對象對同一消息作出不同的響應。簡單的說就是用同樣的對象引用調用同樣的方法但是做了不同的事情。多態性分為編譯時的多態性和運行時的多態性。如果將對象的方法視為對象向外界提供的服務,那么運行時的多態性可以解釋為:當A系統訪問B系統提供的服務時,B系統有多種提供服務的方式,但一切對A
系統來說都是透明的。方法重載(overload)實現的是編譯時的多態性(也稱為前綁定),而方法重寫(override)實現的是運行時的多態性(也稱為后綁定)。運行時的多態是面向對象最精髓的東西,要實現多態需要做兩件事:1.方法重寫(子類繼承父類并重寫父類中已有的或抽象的方法);2.對象造型(用父類型引用引用子類型對象,這樣同樣的引用調用同樣的方法就會根據子類對象的不同而表現出不同的行為)。
抽象:抽象是將一類對象的共同特征總結出來構造類的過程,包括數據抽象和行為抽象兩方面。抽象只關注對象有哪些屬性和行為,并不關注這些行為的細節是什么。
2.我們說的Objective-C是動態運行時語言是什么意思?(When we call objective c is runtime language what does it mean?)主要是將數據類型的確定由編譯時,推遲到了運行時。這個問題其實淺涉及到兩個概念,運行時和多態。簡單來說, 運行時機制使我們直到運行時才去決定一個對象的類別,以及調用該類別對象指定方法。多態:不同對象以自己的方式響應相同的消息的能力叫做多態。意思就是假設生物類(life)都用有一個相同的方法-eat;那人類屬于生物,豬也屬于生物,都繼承了life后,實現各自的eat,但是調用是我們只需調用各自的eat方法。也就是不同的對象以自己的方式響應了相同的消息(響應了eat這個選擇器)。因此也可以說,運行時機制是多態的基礎.3.readwrite,readonly, assign,retain,copy,nonatomic, strong, weak屬性的作用?并區別strong(強引用)、weak(弱引用)?什么情況使用copy,assign和retain? readwrite 是可讀可寫特性;需要生成getter方法和setter方法時;
readonly 是只讀特性只會生成getter方法不會生成setter方法,不希望屬性在類外改變;
assign 是賦值特性,setter方法將傳入參數賦值給實例變量;僅設置變量時;, assign用于簡單數據類型,如NSInteger,double,bool;retain 表示持有特性,setter方法將傳入參數先保留,再賦值,傳入參數的retaincount會+1;
copy 表示賦值特性,setter方法將傳入對象復制一份;需要完全一份新的變量時;nonatomic 非原子操作,決定編譯器生成的setter getter是否是原子操作;atomic表示多線程安全,一般使用nonatomic。
retain 和copy用戶對象,copy用于當 a指向一個對象, b也想指向同樣的對象的時候,如果用assign,a如果釋放,再調用b會crash,如果用copy 的方式,a和b各自有自己的內存,就可以解決這個問題。retain 會使計數器加1,也可以解決assign的問題。另外:atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。在多線程環境下,原子操作是必要的,否則有可能引起錯誤的結果。
其實從這個也可以引申到內存管理的一系列問題.面試官會讓你講講MRC和ARC的理解,隨即也引申出Block的內存機制,為啥推薦Block用copy,Block會存在哪些內存問題?循環引用?
4.分別描述內存管理要點、autorelease、release、NSAutoreleasePool?并說明autorelease是什么時候被release的?簡述什么時候由你負責釋放對象,什么時候不由你釋放?[NSAutoreleasePool release]和[NSAutoreleasePool drain]有什么區別? 內存管理要點: Objective-C 使用引用計數機制(retainCount)來管理內存。內存每被引用一次,該內存的引用計數+1,每被釋放一次引用計數-1。當引用計數 = 0 的時候,調用該對象的 dealloc 方法,來徹底從內存中刪除該對象。alloc,allocWithZone,new(帶初始化)時:該對象引用計數 +1;
retain:手動為該對象引用計數 +1;copy:對象引用計數 +1;
mutableCopy:生成一個新對象,新對象引用計數為 1;release:手動為該對象引用計數-1;
autorelease:把該對象放入自動釋放池,當自動釋放池釋放時,其內的對象引用計數-1。
NSAutoreleasePool: NSAutoreleasePool是通過接收對象向它發送的autorelease消息,記錄該對象的release消息,當自動釋放池被銷毀時,會自動向池中的對象發送release消息。autorelease 是在自動釋放池被銷毀,向池中的對象發送release只能釋放自己擁有的對象, 區別是:在引用計數環境下(在不使用ARC情況下),兩者基本一樣,在GC(垃圾回收制)環境下,release 是一個no-op(無效操作),所以無論是不是GC都使用drain
面試中內存管理,release和autorelease的含義?這里尤其要強調下autorelease,它引申出自動釋放池,也能引申出Run loop!5.自動釋放池是什么,如何工作 ? 當 您向一個對象發送一個autorelease消息時,Cocoa就會將該對象的一個引用放入到最新的自動釋放池。它仍然是個對象,因此自動釋放池定義的作用域內的其它對象可以向它發送消息。當程序執行到作用域結束的位置時,自動釋放池就會被釋放,池中的所有對象也就被釋放。
1>.Objective-C 是 通過一種“referring counting”(引用計數)的方式來管理內存的, 對象在開始分配內存(alloc)的時候引用計數為1,以后每當碰到有copy,retain的時候引用計數都會加1, 每當碰到release和autorelease的時候引用計數就會減1,如果此對象的計數變為了0, 就會被系統銷毀.2>.NSAutoreleasePool 就是用來做引用計數的管理工作的,這個東西一般不用自己管理.3>.autorelease和release沒什么區別,只是引用計數減1的時機不同而已,autorelease會在對象的使用真正結束的時候才做引用計數減1.6.IPhone OS有沒有垃圾回收?autorelease 和垃圾回收制(gc)有什么關系? IPhone OS 中沒有垃圾回收。autorelease只是延遲釋放,gc是每隔一段時間詢問程序,看是否有無指針指向的對象,若有,就將它回收。他們兩者沒有什么關系。
7.簡述NotificationCenter、KVC、KVO、Delegate?并說明它們之間的區別? KVO(Key-Value-Observing):是鍵值監聽,鍵值觀察機制,當觀察者為一個對象的屬性進行了注冊,被觀察對象的isa指針被修改的時候,isa指針就會指向一個中間類,而不是真實的類。所以 isa指針其實不需要指向實例對象真實的類。所以我們的程序最好不要依賴于isa指針。在調用類的方法的時候,最好要明確對象實例的類名
KVC(Key-Value-Coding)內部的實現:是鍵值編碼,一個對象在調用setValue的時候,(1)首先根據方法名找到運行方法的時候所需要的環 境參數。(2)他會從自己isa指針結合環境參數,找到具體的方法實現的接口。(3)再直接查找得來的具體的方法實現。Delegate:代理的目的是改變或傳遞控制鏈。允許一個類在某些特定時刻通知到其他類,而不需要獲取到那些類的指針。可以減少框架復雜度。消息的發送者(sender)告知接收者(receiver)某個事件將要發生,delegate同意然然后發送者響應事件,delegate機制使得接收者可以改變發送者的行為。通常發送者和接收者的關系是直接的一對多的關系。
Notification:消息的發送者告知接收者事件已經發生或者將要發送,僅此而已,接收者并不能反過來影響發送者的行為。通常發送者和接收者的關系是間接的多對多關系。
1).效率肯定是delegate比nsnotification高。
2).delegate方法比notification更加直接,最典型的特征是,delegate方法往往需要關注返回值,也就是delegate方法的結果。比如-windowShouldClose:,需要關心返回的是yes還是no。所以delegate方法往往包含should這個很傳神的詞。也就是好比你做我的delegate,我會問你我想關閉窗口你愿意嗎?你需要給我一個答案,我根據你的答案來決定如何做下一步。相反的,notification最大的特色就是不關心接受者的態度,我只管
把通告放出來,你接受不接受就是你的事情,同時我也不關心結果。所以notification往往用did這個詞匯,比如NSWindowDidResizeNotification,那么nswindow對象放出這個notification后就什么都不管了也不會等待接受者的反應。
1)兩個模塊之間聯系不是很緊密,就用notification傳值,例如多線程之間傳值用notificaiton。
2)delegate只是一種較為簡單的回調,且主要用在一個模塊中,例如底層功能完成了,需要把一些值傳到上層去,就事先把上層的函數通過delegate傳到底層,然后在底層call這個delegate,它們都在一個模塊中,完成一個功能,例如說 NavgationController 從 B 界面到A 點返回按鈕(調用popViewController方法)可以用delegate比較好。
What is lazy loading? 就是懶漢模式,只在用到的時候才去初始化。也可以理解成延時加載。我覺得最好也最簡單的一個列子就是tableView中圖片的加載顯示了。一個延時載,避免內存過高,一個異步加載,避免線程堵塞。
9.OC有多繼承嗎?沒有的話可以用什么方法替代? 多繼承即一個子類可以有多個父類,它繼承了多個父類的特性。Object-c的類沒有多繼承,只支持單繼承,如果要實現多繼承的話,可以通過類別和協議的方式來實現,OC類似于多繼承,是在用protocol委托代理來實現的;可以實現多個接口,通過實現多個接口可以完成C++的多重繼承;Category是類別,一般情況用分類好,用Category去重寫類的方法,僅對本Category有效,不會影響到其他類與原有類的關系。
10.分別描述類別(categories)和延展(extensions)是什么?以及兩者的區別?繼承和類別在實現中有何區別?為什么Category只能為對象添加方法,卻不能添加成員變量? 類別:在沒有原類.m文件的基礎上,給該類添加方法;
延展:一種特殊形式的類別,主要在一個類的.m文件里聲明和實現延展的作用,就是給某類添加私有方法或是私有變量。兩個的區別:延展可以添加屬性并且它添加的方法是必須要實現的。延展可以認為是一個私有的類目。
繼承和類別在實現中的區別:類別可以在不獲悉,不改變原來代碼的情況下往里面添加新的方法,只能添加,不能刪除修改。并且如果類別和原來類中的方法產生名稱沖突,則類別將覆蓋原來的方法,因為類別具有更高的優先級。Category只能為對象添加方法,卻不能添加成員變量的原因:如果可以添加成員變量,添加的成員變量沒有辦法初始化
11.Objective-C有私有方法么?私有變量呢?如多沒有的話,有沒有什么代替的方法? objective-c類里面的方法只有兩種, 靜態方法和實例方法.但是可以通過把方法的聲明和定義都放在.m文件中來實現一個表面上的私有方法。有私有變量,可以通過@private來修飾,或者把聲明放到.m文件中。在Objective‐C中,所有實例變量默認都是私有的,所有實例方法默認都是公有的
12.#include與#import的區別? #import與@class的區別? #import指令是Object-C針對#include的改進版本,#import確保引用的文件只會被引用一次,這樣你就不會陷入遞歸包含的問題中。
#import與@class二者的區別在于:
1>#import會鏈入該頭文件的全部信息,包括實體變量和方法等;而@class只是告訴編譯器,其后面聲明的名稱是類的名稱,至于這些類是如何定義的,暫時不用考慮。
2>在頭文件中,一般只需要知道被引用的類的名稱就可以了。不需要知道其內部的實體變量和方法,所以在頭文件中一般使用@class來聲明這個名稱是類的名稱。而在實現類里面,因為會用到這個引用類的內部的實體變量和方法,所以需要使用#import來包含這個被引用類的頭文件。
3>在編譯效率方面考慮,如果你有100個頭文件都#import了同一個頭文件,或者這些文件是依次引用的,如A–>B, B–>C, C–>D這樣的引用關系。當最開始的那個頭文件有變化的話,后面所有引用它的類都需要重新編譯,如果你的類有很多的話,這將耗費大量的時間。而是用@class則不會。
4>如果有循環依賴關系,如:A–>B, B–>A這樣的相互依賴關系,如果使用#import來相互包含,那么就會出現編譯錯誤,如果使用@class在兩個類的頭文件中相互聲明,則不會有編譯錯誤出現。所以,一般來說,@class是放在interface中的,只是為了在interface中引用這個類,把這個類作為一個類型來用的。在實現這個接口的實現類中,如果需要引用這個類的實體變量或者方法之類的,還是需要import在@class中聲明的類進來.13.淺復制和深復制的區別?(Difference between shallow copy and deep copy?)淺層復制(copy):只復制指向對象的指針,而不復制引用對象本身。意思就是說我有個A對象,復制一份后得到A_copy對象后,對于淺復制來說,A和A_copy指向的是同一個內存資源,復制的只不過是是一個指針,對象本身資源還是只有一份,那如果我們對A_copy執行了修改操作,那么發現A引用的對象同樣被修改,這其實違背了我們復制拷貝的一個思想。
深層復制(mutableCopy):復制引用對象本身。深復制就好理解了,內存中存在了兩份獨立對象本身,當修改A時,A_copy不變。
用網上一哥們通俗的話將就是:
淺復制好比你和你的影子,你完蛋,你的影子也完蛋
深復制好比你和你的克隆人,你完蛋,你的克隆人還活著。
14.類變量的@protected,@private,@public,@package聲明各有什么含義? 變量的作用域不同,@protected 該類和所有子類中的方法可以直接訪問這樣的變量,這是默認的;@private 該類中的方法可以訪問這樣的變量,子類不可以;@public除了自己和子類方法外,也可以被其他類或者其他模塊中的方法訪問;@package 目前尚未得出結論.15.static 關鍵字的作用? 1>函數體內 static 變量的作用范圍為該函數體,不同于 auto 變量,該變量的內存只被分配一次,因此其值在下次調用時仍維持上次的值;
2>在模塊內的 static 全局變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
3>在模塊內的 static 函數只可被這一模塊內的其它函數調用,這個函數的使用范圍被限制在聲明 它的模塊內;
4>在類中的 static 成員變量屬于整個類所擁有,對類的所有對象只有一份拷貝;
5>在類中的 static 成員函數屬于整個類所擁有,這個函數不接收 this 指針,因而只能訪問類的static 成員變量
16.關鍵字volatile有什么含意?并給出三個不同的例子
一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:
? 并行設備的硬件寄存器(如:狀態寄存器)
? 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)? 多線程應用中被幾個任務共享的變量
17.Objective-C與C、C+++之間的聯系和區別?
Objective-C和C++都是C的面向對象的超集。
Object與C++的區別主要點:Objective-C是完全動態的,支持在運行時動態類型決議(dynamic typing),動態綁定(dynamic binding)以及動態裝載(dynamic loading);而C++是部分動態的,編譯時靜態綁定,通過嵌入類(多重繼承)和虛函數(虛表)來模擬實現。
Objective-C 在語言層次上支持動態消息轉發,其消息發送語法為 [object function];而且C++ 為 object->function()。兩者的語義也不同,在 Objective-C 里是說發送消息到一個對象上,至于這個對象能不能響應消息以及是響應還是轉發消息都不會 crash;而在 C++ 里是說對象進行了某個操作,如果對象沒有這個操作的話,要么編譯會報錯(靜態綁定),要么程序會 crash 掉的(動態綁定)。
18.目標-動作機制
目標是動作消息的接收者。一個控件,或者更為常見的是它的單元,以插座變量(參見“插座變量”部分)的形式保有其動作消息的目標。
動作是控件發送給目標的消息,或者從目標的角度看,它是目標為了響應動作而實現的方法.程序需要某些機制來進行事件和指令的翻譯。這個機制就是目標-動作機制。
19.動態綁定
在運行時確定要調用的方法 , 動態綁定將調用方法的確定也推遲到運行時。在編譯時,方法的調用并不和代碼綁定在一起,只有在消實發送出來之后,才確定被調用的代碼。通過
動態類型和動態綁 定技術,代碼每次執行都可以得到不同的結果。運行時因子負責確定消息的接收者和被調用的方法。運行時的消息分發機制為動態綁定提供支持。當向一個動態類型確定了的對象發送消息時,運行環境系統會通過接收者的isa指針定位對象的類,并以此為起點確定被調用的方法,方法和消息是動態綁定的。而且,不必在Objective-C 代碼中做任何工作,就可以自動獲取動態綁定的好處。在每次發送消息時,特別是當消息的接收者是動態類型已經確定的對象時,動態綁定就會例行而透明地發生
20.iPad開發與iPhone開發有什么不同?
開發iPad和iPhone應用使用的是相同的SDK,它們之間的區別主要體現在設備硬件和UI操作上。
(1)設備硬件:由于iPad不具備電話功能,iPad1也沒有相機,所以相關的特性如電話、SMS等無法使用。
(2)UI操作:由于iPad屏幕大小為9.7英寸,而iPhone的屏幕是3.5英寸,這就決定了兩者操作方式的不同。有些控件,如UIPopoverController, UISliptViewController 只能在iPad中使用,而不能在iPhone中使用;而且當需要presentModalViewController時,Window presentation style 只對iPad有效;除此之外,iPad產品開發中還需針對iPad大屏幕考慮加入多指手勢以增加用戶體驗
21.換膚技術使用了什么技術? 22.談談你對runtime的了解? 23.算法和數據結構
第二篇:黑馬程序員:IOS面試寶典之c語言
黑馬程序員:IOS面試寶典之c語言
C語言語法
1.局部變量能否和全局變量重名?
答:能,局部會屏蔽全局。要用全局變量,需要使用“::”;局部變量可以與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。對于有些編譯器而言,在同一個函數內可以定義多個同 名的局部變量,比如在兩個循環體內都定義一個同名的局部變量,而那個局部變量的作用域就在那個循環體內。
2.如何引用一個已經定義過的全局變量?
答:extern 可以用引用頭文件的方式,也可以用extern關鍵字,如果用引用頭文件方式來引用某個在頭文件中聲明的全局變理,假定你將那個編寫錯了,那么在編譯期 間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那么在編譯期間不會報錯,而在連接期間報錯。
3.全局變量可不可以定義在可被多個.C文件包含的頭文件中?為什么?
答:可以,在不同的C文件中以static形式來聲明同名全局變量。
可以在不同的C文件中聲明同名的全局變量,前提是其中只能有一個C文件中對此變量賦初值,此時連接不會出錯.4.關鍵字volatile有什么含意?并舉出三個不同的例子?
一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:
1)并行設備的硬件寄存器(如:狀態寄存器)
2)一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)3)多線程應用中被幾個任務共享的變量
5.static 關鍵字的作用是什么?
(1)函數體內 static 變量的作用范圍為該函數體,不同于 auto 變量,該變量的內存只被分配一次,因此其值在下次調用時仍維持上次的值;
(2)在模塊內的 static 全局變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
(3)在模塊內的 static 函數只可被這一模塊內的其它函數調用,這個函數的使用范圍被限制在聲明
它的模塊內;
(4)在類中的 static 成員變量屬于整個類所擁有,對類的所有對象只有一份拷貝;
(5)在類中的 static 成員函數屬于整個類所擁有,這個函數不接收 this 指針,因而只能訪問類的static 成員變量。
6.堆和棧的區別是什么?
管理方式:對于棧來講,是由編譯器自動管理,無需我們手工控制;對于堆來說,釋放工作由程序員控制,容易產生memory leak。
申請大小:棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統 預先規定好的,在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩余空間時,將提示 overflow。因此,能從棧獲得的空間較小。堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由于系統是用鏈表來存儲的空閑內存地 址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。
碎片問題:對于堆來講,頻繁的new/delete勢必會造成內存空間的不連續,從而造成大量的碎片,使程序效率降低。對于棧來講,則不會存在這個 問題,因為棧是先進后出的隊列,他們是如此的一一對應,以至于永遠都不可能有一個內存塊從棧中間彈出 分配方式:堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,比如局部變量的分配。動態分配由 alloca函數進行分配,但是棧的動態分配和堆是不同的,他的動態分配是由編譯器進行釋放,無需我們手工實現。
分配效率:棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的 效率比較高。堆則是C/C++函數庫提供的,它的機制是很復雜的
7.static全局變量與普通的全局變量有什么區別?static局部變量和普通局部變量有什么區別?static函數與普通函數有什么區別?
答: 1)全局變量(外部變量)的說明之前再冠以static 就構成了靜態的全局變量。全局變量本身就是靜態存儲方式,靜態全局變量當然也是靜態存儲方式。這兩者在存儲方式上并無不同。這兩者的區別在于非靜態全局變量的作用域是整個源程序,當一個源程序由多個源文件組成時,非靜態的全局變量在各個源文件中都是有效的。而靜態全局變量則限制了其作用域,即只在定義該變量的源文件內有效,在同一源程序的其它源文件中不能使用它。由于靜態全局變量的作用域局限于一個源文件內,只能為該源文件內的函數公用,因此可以避免在其它源文件中引起錯誤。
2)從以上分析可以看出,把局部變量改變為靜態變量后是改變了它的存儲方式即改變了它的生存期。把全局變量改變為靜態變量后是改變了它的作用域,限制了它的使用范圍。
3)static函數與普通函數作用域不同,僅在本文件。只在當前源文件中使用的函數應該說明為內部函數(static),內部函數應該在當前源文件中說明和定義。對于可在當前源文件以外使用的函數,應該在一個頭文件中說明,要使用這些函數的源文件要包含這個頭文件
綜上所述: static全局變量與普通的全局變量有什么區別:
static全局變量只初使化一次,防止在其他文件單元中被引用;
static局部變量和普通局部變量有什么區別:
static局部變量只被初始化一次,下一次依據上一次結果值;
static函數與普通函數有什么區別:
static函數在內存中只有一份,普通函數在每個被調用中維持一份拷貝
8.關鍵字const的作用分別是什么?
const int a;int const a;const int *a;int const *a;int * const a;int const * const a;1> 前兩個的作用是一樣:a 是一個常整型數
2> 第三、四個意味著 a 是一個指向常整型數的指針(整型數是不可修改的,但指針可以)3> 第五個的意思:a 是一個指向整型數的常指針(指針指向的整型數是可以修改的,但指針是不可修改的)4> 最后一個意味著:a 是一個指向常整型數的常指針(指針指向的整型數是不可修改的,同時指針也是不可修改的)9.struct與union的區別是什么?
設有以下說明和定義:
typedef union
{ long i;int k[5];char c;} DATE;
struct data { int cat;DATE cow;double dog;} too;
DATE max;
則語句 printf(“%d”,sizeof(struct data)+sizeof(max));的執行結果是:___52____ 考點:區別struct與union.(一般假定在32位機器上)
答:DATE是一個union, 變量公用空間.里面最大的變量類型是int[5], 占用20個字節.所以它的大小是20.data是一個struct, 每個變量分開占用空間.依次為int4 + DATE20 + double8 = 32.所以結果是 20 + 32 = 52.當然...在某些16位編輯器下, int可能是2字節,那么結果是 int2 + DATE10 + double8 = 20 10.關于指針的理解
1.請寫出下題輸出結果:
1.Main(){ 2.Int a[5] = {1,2,3,4,5};
3.Int *ptr =(int *)(&a+1);4.Printf(“%d,%d”,*(a+1),*(ptr – 1));5.} 答:2,5
*(a+1)就是a[1],*(ptr-1)就是a[4],執行結果是2.5,&a+1不是首地址+1,系統會認為加一個a數組的偏 移,是偏移了一個數組的大小(本例是5個int,int *ptr=(int *)(&a+1);則ptr實際 是&(a[5]),也就是a+5原因如下:
&a是數組指針,其類型為 int(*)[5];而指針加1要根據指針類型加上一定的值,不同類型的指針+1之后增加的大小不同。a是長度為5的int數組指針,所以要加 5*sizeof(int)所以ptr實際是a[5],但是prt與(&a+1)類型是不一樣的(這點很重要),所以prt-1只會減去sizeof(int*),a,&a的地址是一樣的,但意思不一樣,a是數組首地址,也就是a[0]的地址,&a是對象(數組)首地址,a+1是數組下一元素的地址,即a[1],&a+1是下一個對象的地址,即a[5].2.寫出下列代碼的輸出內容
#include
int inc(int a)
{ return(++a);}
int multi(int*a,int*b,int*c)
{
return(*c=*a**b);}
typedef int(FUNC1)(int in);
typedef int(FUNC2)(int*,int*,int*);
void show(FUNC2 fun,int arg1, int*arg2)
{
FUNC1 p=&inc;
int temp =p(arg1);
fun(&temp,&arg1, arg2);
printf(“%dn”,*arg2);
}
main()
{
int a;
//局部變量a為0;
show(multi,10,&a);
return 0;
}
答:110
3.以下為Windows NT下的32位C++程序,請計算sizeof的值void Func(char str[100]){
sizeof(str)= ? } void *p = malloc(100);sizeof(p)= ? 答案:這題 很常見了,Func(char str[100])函數中數組名作為函數形參時,在函數體內,數組名失去了本身的內涵,僅僅只是一個指針;在失去其內涵的同時,它還失去了其常量特性,可以作自增、自減等 操作,可以被修改。Windows NT 32位平臺下,指針的長度(占用內存的大小)為4字節,故sizeof(str)、sizeof(p)都為4。
第三篇:黑馬程序員:IOS面試寶典之關于動畫
關于動畫
1.談談你對Core Graphic 繪圖的了解? CoreGraphics也稱為Quartz 2D 是UIKit下的主要繪圖系統,頻繁的用于繪制自定義視圖。Core Graphics是高度集成于UIView和其他UIKit部分的。Core Graphics數據結構和函數可以通過前綴CG來識別。
視圖可以通過子視圖、圖層或實現drawRect:方法來表現內容,如果說實現了drawRect:方法,那么最好就不要混用其他方法了,如圖層和子視圖。自定義繪圖大部分是由UIKit或者Core Graphics來實現的。
2D繪圖一般可以拆分成以下幾個操作: 線條 , 路徑 , 文本 , 圖片 , 漸變 由于像素是依賴于目標的,所以2D繪圖并不能操作單獨的像素,我們可以從上下文(Context)讀取它。
繪圖就好比在畫布上拿著畫筆機械的進行畫畫,通過制定不同的參數來進行不同的繪制。
http://www.tmdps.cn/articles/jIJzMf
http://blog.csdn.net/mangosnow/article/details/37054765
2.Core Animation(核心動畫)? CoreAnimation也就是核心動畫, 是一組非常強大的動畫處理API, 可以使用少量的代碼做出絢麗的效果, 是直接作用在CALayer上的, 并非UIView, 并且Core Animation的動畫執行過程都是在后臺操作, 不會阻塞主線程.所有動畫都是作用在CALayer上的, 當把動畫添加到Layer上, 是不直接修改它的屬性, Core Animation維護了兩個平行layer的層次結構, 模型層樹可以看到Layer的狀態, 表示層樹則是動畫正在表現的值的近似.Core Animation的使用步驟: 1> 使用它需要先添加QuartzCore.framework框架和引入主頭文件
3>.通過調用CALayer的addAnimation:forKey:方法增加CAAnimation對象到CALayer中,這樣就能開始執行動畫了
4>.通過調用CALayer的removeAnimationForKey:方法可以停止CALayer中的動畫
1.轉場動畫? CATransition-轉場動畫, 作為CAAnimation的子類,用于做轉場動畫,能夠為層提供移出屏幕和移入屏幕的動畫效果。iOS比Mac OS X的轉場動畫效果少一點.UINavigationController就是通過CATransition實現了將控制器的視圖推入屏幕的動畫效果.如下是轉場動畫的過渡效果:
使用UIView的動畫函數, 實現轉場動畫 1> 單視圖:
+(void)transitionWithView:(UIView*)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options
animations:(void(^)(void))animations completion:(void(^)(BOOL finished))completion;參數說明:
duration:動畫的持續時間 view:需要進行轉場動畫的視圖 options:轉場動畫的類型
animations:將改變視圖屬性的代碼放在這個block中 completion:動畫結束后,會自動調用這個block 2> 雙視圖: +(void)transitionFromView:(UIView*)fromView toView:(UIView*)toView
duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options finished))completion;參數說明:
duration:動畫的持續時間 options:轉場動畫的類型
animations:將改變視圖屬性的代碼放在這個block中 completion:動畫結束后,會自動調用這個block
completion:(void
(^)(BOOL 2.一個動畫怎么實現? 以轉場動畫為例: 1> 創建CATransition對象
CATransition *animation = [CATransition animation];2> 設置運動時間(即動畫時間)animation.duration = DURATION;3> 設置運動type(類型)
animation.type = type;if(subtype!= nil){ 4> 設置子類(和type配合使用, 指定運動的方向)animation.subtype = subtype;} 5> 設置運動速度(動畫的運動軌跡,用于變化起點和終點之間的插值計算,形象點說它決定了動畫運行的節奏,比如是均勻變化(相同時間變化量相同)還是先快后慢,先慢后快還是先慢再快再慢)animation.timingFunction = UIViewAnimationOptionCurveEaseInOut;
6> 將動畫添加到view的Layer層
[view.layer addAnimation:animation forKey:@“animation”];動畫類型如下: typedef enum : NSUInteger { Fade = 1, //淡入淡出 Push, //推擠 Reveal, //揭開 MoveIn, //覆蓋 Cube, //立方體 SuckEffect, //吮吸 OglFlip, //翻轉 RippleEffect, //波紋
PageCurl, //翻頁 PageUnCurl, //反翻頁 CameraIrisHollowOpen, //開鏡頭 CameraIrisHollowClose, //關鏡頭 CurlDown, //下翻頁 CurlUp, //上翻頁 FlipFromLeft, //左翻轉 FlipFromRight, //右翻轉 } AnimationType;3.CADisplayLink CADisplayLink是一種以屏幕刷新頻率觸發的時鐘機制,每秒鐘執行大約60次左右
CADisplayLink是一個計時器,可以使繪圖代碼與視圖的刷新頻率保持同步,而NSTimer無法確保計時器實際被觸發的準確時間 使用方法:
定義CADisplayLink并制定觸發調用方法 將顯示鏈接添加到主運行循環隊列
第四篇:黑馬程序員:IOS面試寶典之UITableView與UICollectionView
黑馬程序員:IOS面試寶典之UITableView與UICollectionView 1.UITableView的重用機制?(或者如何在一個view上顯示多個tableView,tableView要求不同的數據源以及不同的樣式(要求自定義cell), 如何組織各個tableView的delegate和dataSource?請說說實現思路?)查看UITableView頭文件,會找到NSMutableArray*visiableCells,和NSMutableArray*reusableTableCells兩 個結構。visiableCells內保存當前顯示的cells,reusableTableCells保存可重用的cells。TableView顯示之初,reusableTableCells為空,那么tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。開始的cell都是通過 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 來創 建,而且cellForRowAtIndexPath只是調用最大顯示cell數的次數。比如:有100條數據,iPhone一屏最多顯示10個cell。程序最開始顯示TableView的情況是: 1.用[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 創建10次cell,并給cell指定同樣的重用標識(當然,可以為不同顯示類型的cell指定不同的標識)。并且10個cell全部都加 入到 visiableCells數組,reusableTableCells為空。
2.向下拖動tableView,當cell1完全移出屏幕,并且 cell11(它也是alloc出來的,原因同上)完全顯示出來的時候。cell11加入到visiableCells,cell1移出 visiableCells,cell1加入到reusableTableCells。
3.接著向下拖動tableView,因為reusableTableCells中已 經有值,所以,當需要顯示新的cell, cellForRowAtIndexPath再次被調用的時 候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。cell1加入到visiableCells,cell1 移出reusableTableCells;cell2移出 visiableCells,cell2加入到reusableTableCells。之后再需要顯示的Cell就可 以正常重用了
2.在一個tableView 中需要自定義多種樣式的cell(兩種或三種),通常你如何實現,說說思路即可? 比如:有100條數據,iPhone一屏最多顯示10個cell。程序最開始顯示TableView的情況是: 1.用[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 創建10次cell,并給cell指定同樣的重用標識(當然,可以為不同顯示類型的cell指定不同的標識)。并且10個cell全部都加 入到 visiableCells數組,reusableTableCells為空。
2.向下拖動tableView,當cell1完全移出屏幕,并且 cell11(它也是alloc出來的,原因同上)完全顯示出來的時候。cell11加入到visiableCells,cell1移出 visiableCells,cell1加入到reusableTableCells。
3.接著向下拖動tableView,因為reusableTableCells中已 經有值,所以,當需要顯示新的cell, cellForRowAtIndexPath再次被調用的時 候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。cell1加入到visiableCells,cell1 移出reusableTableCells;cell2移出 visiableCells,cell2加入到
reusableTableCells。之后再需要顯示的Cell就可 以正常重用了
3.UITableView的性能優化? 滑動的時候有種卡的感覺是為什么?怎么解決?
然而在使用第三方應用時,卻經常遇到性能上的問題,普遍表現在滾動時比較卡,特別是table cell中包含圖片的情況時。實際上針對性地優化一下就可以解決tableView滑動的時候卡頓的問題, 在iOS應用中,UITableView應該是使用率最高的視圖之一了。iPod、時鐘、日歷、備忘錄、Mail、天氣、照片、電話、短信、Safari、App Store、iTunes、Game Center?幾乎所有自帶的應用中都能看到它的身影,可見它的重要性。然而在使用第三方應用時,卻經常遇到性能上的問題,普遍表現在滾動時比較卡,特別是table cell中包含圖片的情況時。
實際上只要針對性地優化一下: 1>同一時間其實只需要存在一屏幕的cell對象即可,不需要為每一行創建一個cell。
UITableView是UIScrollView的子類,因此它可以自動響應滾動事件(一般為上下滾動)。它內部包含0到多個UITableViewCell對象,每個table cell展示各自的內容。當新cell需要被顯示時,就會調用tableView:cellForRowAtIndexPath:方法來獲取或創建一個 cell;而不可視時,它又會被釋放。由此可見,同一時間其實只需要存在一屏幕的cell對象即可,不需要為每一行創建一個cell。此 外,UITableView還可以分為多個sections,每個區段都可以有自己的head、foot和cells。而在定位一個cell時,就需要2 個字段了:在哪個section,以及在這個section的第幾行。這在iOS SDK中是用NSIndexPath來表述的,UIKit為其添加了indexPathForRow:inSection:這個創建方法。其他諸如編輯之類的就不提了,因為和本文無關。
介紹完原理,接下來就開始優化吧。
使用不透明視圖。
不透明的視圖可以極大地提高渲染的速度。因此如非必要,可以將table cell及其子視圖的opaque屬性設為YES(默認值)。其中的特例包括背景色,它的alpha值應該為1(例如不要使用clearColor);圖像的alpha值也應該為1,或者在畫圖時設為不透明。
不要重復創建不必要的table cell。
前面說了,UITableView只需要一屏幕的UITableViewCell對象即可。因此在cell不可見時,可以將其緩存起來,而在需要時繼續使用它即可。而UITableView也提供了這種機制,只需要簡單地設置一個identifier即可:
static NSString *CellIdentifier = @“xxx”;UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];if(cell == nil){ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];} 值得一提的是,cell被重用時,它內部繪制的內容并不會被自動清除,因此你可能需要調用setNeedsDisplayInRect:或setNeedsDisplay方法。此 外,在添加table cell的時候,如果不需要動畫效果,最好不要使用insertRowsAtIndexPaths:withRowAnimation:方法,而是直接調 用reloadData方法。因為前者會對所有indexPaths調用tableView:cellForRowAtIndexPath:方法,即便該 cell并不需要顯示(不知道是不是bug),這就可能創建大量多余的cell。勘誤:只是在模擬器上測試如此,真機調試時沒有這種bug。
減少視圖的數目。
UITableViewCell包含了textLabel、detailTextLabel和imageView等view,而
你還可以自定義一些視圖放在它的contentView里。然而view是很大的對象,創建它會消耗較多資源,并且也影響渲染的性能。如果你的table cell包含圖片,且數目較多,使用默認的UITableViewCell會非常影響性能。奇怪的是,使用自定義的view,而非預定義的view,明顯會快些。當然,最佳的解決辦法還是繼承UITableViewCell,并在其drawRect:中自行繪制:
-(void)drawRect:(CGRect)rect { if(image){ [image drawAtPoint:imagePoint];self.image = nil;} else { [placeHolder drawAtPoint:imagePoint];} [text drawInRect:textRect withFont:font lineBreakMode:UILineBreakModeTailTruncation];} 不過這樣一來,你會發現選中一行后,這個cell就變藍了,其中的內容就被擋住了。最簡單的方法就是將cell的selectionStyle屬性設為UITableViewCellSelectionStyleNone,這樣就不會被高亮了。此外還可以創建CALayer,將內容繪制到layer上,然后對cell的contentView.layer調用addSublayer:方法。這個例 子中,layer并不會顯著影響性能,但如果layer透明,或者有圓角、變形等效果,就會影響到繪制速度了。解決辦法可參見后面的預渲染圖像。
不要做多余的繪制工作。
在實現drawRect:的時候,它的rect參數就是需要繪制的區域,這個區域之外的不需要進行繪制。例如上例中,就可以用CGRectIntersectsRect、CGRectIntersection或CGRectContainsRect判斷是否需要繪制image和text,然后再調用繪制方法。
預渲染圖像。
你會發現即使做到了上述幾點,當新的圖像出現時,仍然會有短暫的停頓現象。解決的辦法就是在bitmap context里先將其畫一遍,導出成UIImage對象,然后再繪制到
屏幕,詳細做法可見《利用預渲染加速iOS設備的圖像顯示》。
不要阻塞主線程。
做到前幾點后,你的table view滾動時應該足夠流暢了,不過你仍可能讓用戶感到不爽。常見的現象就是在更新數據時,整個界面卡住不動,完全不響應用戶請求。出現這種現象的原因就是主線程執行了耗時很長的函數或方法,在其執行完畢前,無法繪制屏幕和響應用戶請求。其中最常見的就是網絡請求了,它通常都需要花費數秒的時間,而你不應該讓用戶等待那么久。解決辦法就是使用多線程,讓子線程去執行這些函數或方法。這里面還有一個學問,當下載線程數超過2時,會顯著影響主線程的性能。因此在使用 ASIHTTPRequest時,可以用一個NSOperationQueue
來維護下載請求,并將其
maxConcurrentOperationCount設為2。而NSURLRequest則可以配合GCD來實現,或者使用NSURLConnection的setDelegateQueue:方法。當然,在不需要響應用戶請求時,也可以增加下載線程數,以加快下載速度:
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if(!decelerate){ queue.maxConcurrentOperationCount = 5;} }(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { queue.maxConcurrentOperationCount = 2;} 此外,自動載入更新數據對用戶來說也很友好,這減少了用戶等待下載的時間。例如每次載入50條信息,那就可以在滾動到倒數第10條以內時,加載更多信息:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { if(count-indexPath.row < 10 &&!updating){ updating = YES;[self update];} }// update方法獲取到結果后,設置updating為NO 還有一點要注意的就是當圖片下載完
成后,如果cell是可見的,還需要更新圖像:
NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];for(NSIndexPath *visibleIndexPath in indexPaths){ if(indexPath == visibleIndexPath){ MyTableViewCell *cell =(MyTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];cell.image = image;[cell setNeedsDisplayInRect:imageRect];break;} }// 也可不遍歷,直接與頭尾相比較,看是否在中間即可。最后還是前面所說過的insertRowsAtIndexPaths:withRowAnimation:方法,插入新行需要在主線程執行,而一次插入很多行的話(例如50行),會長時間阻塞主線程。而換成reloadData方法的話,瞬間就處理完了。l 4 tableview的cell里如何嵌套collection view?
思路同網易新聞類似, 用自定義的繼承自UITableViewCell的類, 在initWithFrame的構造方法中, 初始化自定義的繼承自UICollectionView的類 下拉和上拉的原理? 上拉和下拉的原理可以參照新浪微博的上拉和下拉刷新, 以tableView的上拉刷新為例:
1> 為了進行無縫閱讀, 通過tableView的代理方法, willDisplayCell判斷是否是最后一行,2> 如果是最后一行, 在顯示最后一行的同時, 判斷當前是否存在上拉刷新 3> 如果當前沒有上拉刷新, 就進行加載數據, 啟動”橘花”
以tableView的下拉刷新為例: 1> 判斷當前的上拉刷新視圖是否動畫
2> 如果沒有動畫, 就不是上拉刷新 3> 然后下拉刷新加載數據 4> 加載完畢數據關閉刷新
第五篇:黑馬程序員:IOS面試寶典數據存儲
數據存儲(★★)
1、IOS中常用的數據存儲方式有哪些?
答:1.數據存儲有四種方案,NSUserDefault,KeyChain,File,DB.2.其中File有三種方式:plist,Archiver,Stream 3.DB包括core Data和FMDB
2、說一說你對sqlite的認識
SQLite是目前主流的嵌入式關系型數據庫,其最主要的特點就是輕量級、跨平臺,當前很多嵌入式操作系統都將其作為數據庫首選。雖然SQLite是一款輕型數據庫,但是其功能也絕不亞于很多大型關系數據庫。學習數據庫就要學習其相關的定義、操作、查詢語言,也就是大家日常說得SQL語句。和其他數據庫相比,SQLite中的SQL語法并沒有太大的差別,因此這里對于SQL語句的內容不會過多贅述,大家可以參考SQLite中其他SQL相關的內容,這里還是重點講解iOS中如何使用SQLite構建應用程序。先看一下SQLite數據庫的幾個特點:
1.基于C語言開發的輕型數據庫
2.在iOS中需要使用C語言語法進行數據庫操作、訪問(無法使用ObjC直接訪問,因為libqlite3框架基于C語言編寫)
3.SQLite中采用的是動態數據類型,即使創建時定義了一種類型,在實際操作時也可以存儲其他類型,但是推薦建庫時使用合適的類型(特別是應用需要考慮跨平臺的情況時)
4.建立連接后通常不需要關閉連接(盡管可以手動關閉)
在iOS中操作SQLite數據庫可以分為以下幾步(注意先在項目中導入libsqlite3框架):
1.打開數據庫,利用sqlite3_open()打開數據庫會指定一個數據庫文件保存路徑,如果文件存在則直接打開,否則創建并打開。打開數據庫會得到一個sqlite3類型的對象,后面需要借助這個對象進行其他操作。
2.執行SQL語句,執行SQL語句又包括有返回值的語句和無返回值語句。3.對于無返回值的語句(如增加、刪除、修改等)直接通過sqlite3_exec()函數執行;
4.對于有返回值的語句則首先通過sqlite3_prepare_v2()進行sql語句評估(語法檢測),然后通過sqlite3_step()依次取出查詢結果的每一行數據,對于每行數據都可以通過對應的sqlite3_column_類型()方法獲得對應列的數據,如此反復循環直到遍歷完成。當然,最后需要釋放句柄。
3、說一說你對FMDB的認識
FMDB是一個處理數據存儲的第三方框架,框架是對sqlite的封裝,整個框架非常輕量級但又不失靈活性,而且更加面向對象。FMDB有如下幾個特性:
1.FMDB既然是對于libsqlite3框架的封裝,自然使用起來也是類似的,使用前也要打開一個數據庫,這個數據庫文件存在則直接打開否則會創建并打開。這里FMDB引入了一個MFDatabase對象來表示數據庫,打開數據庫和后面的數據庫操作全部依
賴此對象。
2.對于數據庫的操作跟前面KCDbManager的封裝是類似的,在FMDB中FMDatabase類提供了兩個方法executeUpdate:和executeQuery:分別用于執行無返回結果的查詢和有返回結果的查詢。當然這兩個方法有很多的重載這里就不詳細解釋了。唯一需要指出的是,如果調用有格式化參數的sql語句時,格式化符號使用“?”而不是“%@”、等。
3.我們知道直接使用libsqlite3進行數據庫操作其實是線程不安全的,如果遇到多個線程同時操作一個表的時候可能會發生意想不到的結果。為了解決這個問題建議在多線程中使用FMDatabaseQueue對象,相比FMDatabase而言,它是線程安全的。
4.將事務放到FMDB中去說并不是因為只有FMDB才支持事務,而是因為FMDB將其封裝成了幾個方法來調用,不用自己寫對應的sql而已。其實在在使用libsqlite3操作數據庫時也是原生支持事務的(因為這里的事務是基于數據庫的,FMDB還是使用的SQLite數據庫),只要在執行sql語句前加上“begin transaction;”執行完之后執行“commit transaction;”或者“rollback transaction;”進行提交或回滾即可。另外在Core Data中大家也可以發現,所有的增、刪、改操作之后必須調用上下文的保存方法,其實本身就提供了事務的支持,只要不調用保存方法,之前所有的操作是不會提交的。在FMDB中FMDatabase有beginTransaction、commit、rollback三個方法進行開啟事務、提交事務和回滾事務。
4、說一說你對Core Data的認識
Core Data使用起來相對直接使用SQLite3的API而言更加的面向對象,操作過
程通常分為以下幾個步驟:
1.創建管理上下文
創建管理上下可以細分為:加載模型文件->指定數據存儲路徑->創建對應數據類型的存儲->創建管理對象上下方并指定存儲。
經過這幾個步驟之后可以得到管理對象上下文NSManagedObjectContext,以后所有的數據操作都由此對象負責。同時如果是第一次創建上下文,Core Data會自動創建存儲文件(例如這里使用SQLite3存儲),并且根據模型對象創建對應的表結構。
2.查詢數據
對于有條件的查詢,在Core Data中是通過謂詞來實現的。首先創建一個請求,然后設置請求條件,最后調用上下文執行請求的方法。
3.插入數據
插入數據需要調用實體描述對象NSEntityDescription返回一個實體對象,然后設置對象屬性,最后保存當前上下文即可。這里需要注意,增、刪、改操作完最后必須調用管理對象上下文的保存方法,否則操作不會執行。
4.刪除數據
刪除數據可以直接調用管理對象上下文的deleteObject方法,刪除完保存上下文即可。注意,刪除數據前必須先查詢到對應對象。
5.修改數據
修改數據首先也是取出對應的實體對象,然后通過修改對象的屬性,最后保存上下文。
5、OC中有哪些數據存儲方式,各有什么區別? OC中有四種數據存儲方式: 1).NSUserDefaults,用于存儲配置信息 2).SQLite,用于存儲查詢需求較多的數據 3).CoreData,用于規劃應用中的對象
4).使用基本對象類型定制的個性化緩存方案.NSUserDefaults:對象中儲存了系統中用戶的配置信息,開發者可以通過這個實例對象對這些已有的信息進行修改,也可以按照自己的需求創建新的配置項。SQLite擅長處理的數據類型其實與NSUserDefaults差不多,也是基礎類型的小數據,只是從組織形式上不同。開發者可以以關系型數據庫的方式組織數據,使用SQL DML來管理數據。一般來說應用中的格式化的文本類數據可以存放在數據庫中,尤其是類似聊天記錄、Timeline等這些具有條件查詢和排序需求的數據。CoreData是一個管理方案,它的持久化可以通過SQLite、XML或二進制文件儲存。它可以把整個應用中的對象建模并進行自動化的管理。從歸檔文件還原模型時CoreData并不是一次性把整個模型中的所有數據都載入內存,而是根據運行時狀態,把被調用到的對象實例載入內存。框架會自動控制這個過程,從而達到控制內存消耗,避免浪費。無論從設計原理還是使用方法上看,CoreData都比較復雜。因此,如果僅僅是考慮緩存數據這個需求,CoreData絕對不是一個優選方案。CoreData的使用場景在于:整個應用使用CoreData規劃,把應用內的數據通過CoreData建模,完全基于CoreData架構應用。使用基本對象類型定制的個性化緩存方案:從需求出發分析緩存數據有哪些要求:按Key查找,快速讀取,寫入不影響正常操作,不浪費內存,支持歸檔。這些都是基本需求,那么再進一步或許還需要固定緩存項數量,支持隊列緩存,緩存過期等。
數據存儲這一塊,面試常問, 你常用哪一種數據存儲?什么是序列化?sqlite是直接用它還是用封裝了它的第三方庫?尤其是會問sqlite和core data的區別?
5、IOS平臺怎么做數據的持久化?coredata和sqlite有無必然聯系?coredata是一個關系型數據庫嗎?
iOS中可以有四種持久化數據的方式: 屬性列表、對象歸檔、SQLite3和Core Data coredata可以使你以圖形界面的方式快速的定義app的數據模型,同時在你的代碼中容易獲取到它。coredata提供了基礎結構去處理常用的功能,例如保存,恢復,撤銷和重做,允許你在app中繼續創建新的任務。在使用coredata的時候,你不用安裝額外的數據庫系統,因為coredata使用內置的sqlite數據庫。coredata將你app的模型層放入到一組定義在內存中的數據對象。coredata會追蹤這些對象的改變,同時可以根據需要做相應的改變,例如用戶執行撤銷命令。當coredata在對你app數據的改變進行保存的時候,core data會把這些數據歸檔,并永久性保存。mac os x中sqlite庫,它是一個輕量級功能強大的關系數據引擎,也很容易嵌入到應用程序。可以在多個平臺使用,sqlite是一個輕量級的嵌入式sql數據庫編程。與coredata框架不同的是,sqlite是使用程序式的,sql的主要的API來直接操作數據表。Core Data不是一個關系型數據庫,也不是關系型數據庫管理系統(RDBMS)。雖然Core Dta支持SQLite作為一種存儲類型, 但它不能使用任意的SQLite數據庫。Core Data在使用的過程種自己創建這個數據庫。Core Data支持對
一、對多的關系。
6、如果后期需要增加數據庫中的字段怎么實現,如果不使用CoreData呢?
編寫SQL語句來操作原來表中的字段 增加表字段
ALTER TABLE 表名 ADD COLUMN 字段名字段類型;? 刪除表字段
ALTER TABLE 表名 DROP COLUMN 字段名;
.修改表字段
ALTER TABLE 表名 RENAME COLUMN 舊字段名 TO 新字段名;
7、SQLite數據存儲是怎么用?
添加SQLite動態庫:
導入主頭文件:#import
8、簡單描述下客戶端的緩存機制?
1>緩存可以分為:內存數據緩存、數據庫緩存、文件緩存 2>每次想獲取數據的時候 3>先檢測內存中有無緩存
4>再檢測本地有無緩存(數據庫文件)5>最終發送網絡請求
6>將服務器返回的網絡數據進行緩存(內存、數據庫、文件),以便下次讀取
9、你實現過多線程的Core Data么?NSPersistentStoreCoordinator,NSManagedObjectContext和NSManagedObject中的哪些需要在線程中創建或者傳遞?你是用什么樣的策略來實現的?
1>CoreData是對SQLite數據庫的封裝
2>CoreData中的NSManagedObjectContext在多線程中不安全
3>如果想要多線程訪問CoreData的話,最好的方法是一個線程一個NSManagedObjectContext 4>每個NSManagedObjectContext對象實例都可以使用同一個NSPersistentStoreCoordinator實例,這是因為NSManagedObjectContext會在便用NSPersistentStoreCoordinator前上鎖
10、core data數據遷移
博客地址: http://blog.csdn.net/jasonblog/article/details/17842535
11、FMDB的使用和對多張表的處理
博客地址: http://blog.csdn.net/wscqqlucy/article/details/8464398
12、說說數據庫的左連接和右連接的區別
數據庫左連接和右連接的區別:主表不一樣通過左連接和右連接,最小條數為3(記錄條數較小的記錄數),最大條數為12(3×4)技術博客的地址 : http://