




已閱讀5頁,還剩15頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
課程簡(jiǎn)介.正如它的名字所傳達(dá)的含義,F(xiàn)oundation 框架是所有 iOS 和 Mac OS X 編程所使用的基本工具。要成為這兩個(gè)平臺(tái)上成功的開發(fā)者,必須對(duì)這套工具了如指掌。Foundation 框架定義了數(shù)量眾多的類以及協(xié)議,它們各司其職。但三種類和協(xié)議的地位更加突出,它們是最基本的部分: 根類和相關(guān)的協(xié)議。根類,即NSObject,還伴有一個(gè)同名的協(xié)議。它確定了所有 Objective-C 對(duì)象的基本接口和行為。同時(shí)也有一些協(xié)議,其他類可以采用這些協(xié)議來拷貝這些類的實(shí)例并對(duì)編碼它們的狀態(tài)。 數(shù)值類。數(shù)值類能夠產(chǎn)生一個(gè)實(shí)例(稱為數(shù)值對(duì)象),也就是將字符串、數(shù)字、日期、二進(jìn)制數(shù)據(jù)等基本類型數(shù)據(jù)封裝起來的面向?qū)ο蟀b。 群體類。群體類的一個(gè)實(shí)例(稱為群體)管理著一組對(duì)象。區(qū)分不同類型的群體就要看訪問它所包含的對(duì)象的方式是什么。通常,群體中包含的項(xiàng)目都是一系列數(shù)值對(duì)象。群體和數(shù)值對(duì)象是 Objective-C 編程中極其重要的內(nèi)容,因?yàn)樗鼈兘?jīng)常被用作方法的參數(shù)和返回值。課時(shí):認(rèn)識(shí)根類和Objective-C 對(duì)象摘要:在類繼承中,根類不從其他類繼承,同時(shí)所有其他的類都最終繼承自根類。NSObject 是 Objective-C 繼承中的根類。其他類都從 NSObject 繼承一套基本的接口到 Objectiv在類繼承中,根類不從其他類繼承,同時(shí)所有其他的類都最終繼承自根類。NSObject 是 Objective-C 繼承中的根類。其他類都從 NSObject 繼承一套基本的接口到 Objective-C 運(yùn)行時(shí)體系中。這些類的實(shí)例又都是從 NSObject 繼承而獲得 Objective-C 最根本的特性。但就其自身而言,NSObject 的實(shí)例做不了什么有趣的事,頂多只是個(gè)對(duì)象而已。要使用更多屬性和邏輯來定制你的程序,就必須創(chuàng)造一個(gè)或多個(gè)繼承自 NSObject 的類,或者使用已有的直接或間接繼承自 NSObject 的類。NSObject 采用了 NSObject 的協(xié)議,它聲明了一些附加方法,可以被所有對(duì)象的接口使用。另外,NSObject.h(包含了 NSObject 類定義的頭文件)中包含 NSCopying、NSMutableCopying 和 NSCoding 協(xié)議。當(dāng)某個(gè)類采用了這些協(xié)議后,它便獲得了對(duì)象拷貝和對(duì)象編碼的基本對(duì)象行為。模型類(封裝了應(yīng)用數(shù)據(jù)并管理這些數(shù)據(jù)的實(shí)例的類)經(jīng)常采用對(duì)象拷貝和對(duì)象編碼協(xié)議。NSObject 類和相關(guān)協(xié)議定義了創(chuàng)建對(duì)象、瀏覽繼承鏈、查閱對(duì)象的特征和功能、比較對(duì)象、拷貝對(duì)象和把對(duì)象進(jìn)行編碼等的一系列方法。本文接下來主要講述的就是這類任務(wù)的基本要求。創(chuàng)建對(duì)象通常,創(chuàng)建對(duì)象時(shí),要先為它分配內(nèi)存,然后將它初始化。雖然這是兩個(gè)單獨(dú)的步驟,但它們聯(lián)系甚密。有些類可以通過調(diào)用它們的工廠方法來創(chuàng)建對(duì)象。創(chuàng)建對(duì)象 分配內(nèi)存和初始化要為對(duì)象分配內(nèi)存,對(duì)它的類發(fā)送一個(gè) alloc 消息就能得到該類的一個(gè)“原始”(未初始化)的實(shí)例。當(dāng)你為一個(gè)對(duì)象分配內(nèi)存時(shí),Objective-C 運(yùn)行時(shí)會(huì)在應(yīng)用的虛擬內(nèi)存中為該對(duì)象預(yù)留足夠大的內(nèi)存空間。除了分配內(nèi)存本身之外,這個(gè)環(huán)節(jié)還有另外幾個(gè)用途,例如把實(shí)例變量全部設(shè)為 0 等。為原始實(shí)例分配好內(nèi)存之后,你必須將其初始化。初始化也就是將對(duì)象設(shè)置為初始狀態(tài),換句話說,就是讓它的實(shí)例變量和屬性為合理的值,然后再返回這個(gè)對(duì)象。初始化是為了保證返回的對(duì)象可以被使用。你會(huì)發(fā)現(xiàn)在不少框架中都含有 initializers(初始器)方法,即可以初始化對(duì)象的方法。它們的形式大多類似。初始器是實(shí)例方法,方法開頭為 init,返回一個(gè) id 類型的對(duì)象。根對(duì)象 NSObject 聲明了 init 方法,所有其他的類都繼承了這個(gè)方法。其他的類當(dāng)然也可以聲明自己的初始器,各自要有自己的關(guān)鍵字和參數(shù)類型。例如,NSURL 類聲明了如下初始器:1. - (id)initFileURLWithPath:(NSString *)path isDirectory:(BOOL)isDir當(dāng)你為一個(gè)對(duì)象分配內(nèi)存并將其初始化的時(shí)候,可以將內(nèi)存分配方法和初始化方法嵌套起來。如果使用上邊這個(gè)初始器的話,可以寫成這樣:1. NSURL *aURL = NSURL alloc initFileURLWithPath:NSTemporaryDirectory() isDir:YES;作為一種安全的編程習(xí)慣,你可以檢查返回的對(duì)象以驗(yàn)證對(duì)象的創(chuàng)建是否正確。如果創(chuàng)建過程中發(fā)生了意外而導(dǎo)致對(duì)象創(chuàng)建失敗,初始器將返回 nil。雖然 Objective-C 允許對(duì) nil 發(fā)送消息而不會(huì)產(chǎn)生任何副作用(比如拋出異常),但你的代碼顯然不可能正常工作,因?yàn)闆]有任何方法能夠被調(diào)用。你不應(yīng)該使用 alloc 返回的實(shí)例,而要使用初始器返回的實(shí)例。通過調(diào)用類的工廠方法來創(chuàng)建對(duì)象通過調(diào)用類的工廠方法也能創(chuàng)建一個(gè)對(duì)象。工廠方法是一種類方法,它能夠分配內(nèi)存、初始化,并返回實(shí)例自身。類的工廠方法屬于一種便捷方法,因?yàn)樗鼈冎恍枰徊骄涂梢詣?chuàng)建對(duì)象,而不是上文講過的兩步。它們的形式是這樣的:1. + (type)className (這里的 類名稱 不包含任何前綴)Objective-C 框架中的類有些會(huì)定義一種工廠方法,這種工廠方法實(shí)際上起到了初始器的作用。比如,NSString 就聲明了如下兩種方法:1. - (id)initWithFormat:(NSString *)format, ;2. + (id)stringWithFormat:(NSString *)format, ;3. 下邊的例子就是 NSString 工廠方法的一種用法:1. NSString *myString = NSString stringWithFormat:Customer: %, self.record.customerName;2. 課時(shí):用對(duì)象的術(shù)語來思考3. 摘要:4. 在運(yùn)行時(shí),每個(gè)應(yīng)用都是一組互相協(xié)作的對(duì)象構(gòu)成的;這些對(duì)象互相之間可以通信,以完成應(yīng)用所需的工作。每個(gè)對(duì)象都有自己的角色,至少要對(duì)一件事負(fù)責(zé),并且至少連接一個(gè)其他對(duì)象。(孤立的對(duì)象毫無價(jià)值。)如下5. 在運(yùn)行時(shí),每個(gè)應(yīng)用都是一組互相協(xié)作的對(duì)象構(gòu)成的;這些對(duì)象互相之間可以通信,以完成應(yīng)用所需的工作。每個(gè)對(duì)象都有自己的角色,至少要對(duì)一件事負(fù)責(zé),并且至少連接一個(gè)其他對(duì)象。(孤立的對(duì)象毫無價(jià)值。)如下圖所示,對(duì)象所組成的網(wǎng)絡(luò)中既有框架對(duì)象也有應(yīng)用程序?qū)ο?。?yīng)用程序?qū)ο髸r(shí)自定義的子類的實(shí)例,一般繼承自某個(gè)父類框架。這些對(duì)象組成的網(wǎng)絡(luò)一般被成為對(duì)象圖。6.7. 8. 你需要?jiǎng)?chuàng)建這些連接,或者關(guān)系,在各個(gè)對(duì)象之間進(jìn)行引用。引用的語言形式有很多,其中有實(shí)例變量、全局變量,甚至包括(在有限的作用域內(nèi))本地變量。而關(guān)系,可以是一對(duì)一關(guān)系,也可以是一對(duì)多關(guān)系,可以表示出一系列從屬關(guān)系的概念。這些關(guān)系就是某個(gè)對(duì)象對(duì)其他對(duì)象進(jìn)行訪問、溝通或者控制的手段。被引用的對(duì)象自然也就成了消息的接收者。9. 應(yīng)用的對(duì)象間傳遞的消息是讓應(yīng)用持續(xù)工作的重要因素。好比樂團(tuán)中的演奏家一樣,應(yīng)用中的每個(gè)對(duì)象都有各自的角色,為應(yīng)用的運(yùn)行履行自己的這部分職責(zé)。有的對(duì)象可以顯示一個(gè)橢圓形的界面響應(yīng)點(diǎn)按動(dòng)作,有的會(huì)管理一些承載各種數(shù)據(jù)的數(shù)據(jù)集合,有的則控制整個(gè)應(yīng)用生命周期內(nèi)的各大事件。但為了完成它們各自的任務(wù),它們還必須能夠互相交流。每個(gè)對(duì)象都要有向同一應(yīng)用中別的對(duì)象發(fā)送消息的能力,也要有接收別的對(duì)象發(fā)來的消息的能力。10. 有些對(duì)象之間緊密成對(duì),即互相之間直接相連,它們互發(fā)消息時(shí)是很容易的。但還有些非緊密成對(duì)的對(duì)象,即在對(duì)象圖中被分隔開的對(duì)象,它們之間要進(jìn)行通信就要另想辦法。Cocoa 和 Cocoa Touch 框架含有許多幫助非緊密成對(duì)的對(duì)象進(jìn)行通信的功能和機(jī)制(如下圖所示)。這些機(jī)制和技術(shù)都建立在一些設(shè)計(jì)模式之上(我們會(huì)在后面探討),這樣就使得應(yīng)用更加高效并且具有超強(qiáng)的可擴(kuò)展性。11.課時(shí):管理對(duì)象圖,避免內(nèi)存泄漏摘要:Objective-C 程序里的對(duì)象共同組成一張對(duì)象圖:由各個(gè)對(duì)象和其他對(duì)象的關(guān)系(或引用)而形成的網(wǎng)絡(luò)。對(duì)象之間的引用分為一對(duì)一和一對(duì)多(通過對(duì)象集合)引用。對(duì)象圖十分重要,因?yàn)樗鞘箤?duì)象保持Objective-C 程序里的對(duì)象共同組成一張對(duì)象圖:由各個(gè)對(duì)象和其他對(duì)象的關(guān)系(或引用)而形成的網(wǎng)絡(luò)。對(duì)象之間的引用分為一對(duì)一和一對(duì)多(通過對(duì)象集合)引用。對(duì)象圖十分重要,因?yàn)樗鞘箤?duì)象保持生命力的關(guān)鍵因素。編譯器會(huì)檢查對(duì)象圖中引用的強(qiáng)弱,并根據(jù)需要保持對(duì)象發(fā)出或釋放對(duì)象消息。在 C 語言或 Objective-C 語言中,可以使用含有全局變量、實(shí)例變量或本地變量的結(jié)構(gòu)來構(gòu)造對(duì)象間的引用。這些結(jié)構(gòu)各自都有自己暗含的作用域。比如,本地變量引用的一個(gè)對(duì)象的作用域就是聲明它的函數(shù)塊所在的位置。同樣重要的是,對(duì)象間的引用也是分強(qiáng)弱的。強(qiáng)引用會(huì)指示出自己的所有者是誰;指向別人的對(duì)象擁有被指向的對(duì)象。弱引用則是指向別人的對(duì)象和被指向的對(duì)象之間沒有從屬關(guān)系。對(duì)象的生命周期由它的強(qiáng)引用數(shù)量多少?zèng)Q定。只要對(duì)象有強(qiáng)引用關(guān)系,它就不會(huì)被釋放。Objective-C 里的引用默認(rèn)都是強(qiáng)引用。通常來說這很方便,讓編譯器管理對(duì)象的運(yùn)行時(shí)生命周期,當(dāng)你使用對(duì)象時(shí)它們不會(huì)被釋放。但是如果粗心未作全面檢查,對(duì)象間的強(qiáng)引用可能會(huì)形成無限循環(huán),如下圖左邊所示。這樣的循環(huán)鏈在運(yùn)行時(shí)會(huì)導(dǎo)致運(yùn)行時(shí)不會(huì)釋放任何一個(gè)對(duì)象,它們都有指向自己的強(qiáng)引用。繼而,這樣的死循環(huán)就造成了內(nèi)存泄露。就圖中的對(duì)象而言,如果你取消 A 和 B 之間的引用,則 B、C、D、E 構(gòu)成的子對(duì)象圖則“永遠(yuǎn)”不會(huì)從內(nèi)存中釋放,因?yàn)檫@些對(duì)象每一個(gè)都有強(qiáng)引用,形成了一個(gè)死循環(huán)。如果在 E 和 B 之間引入弱引用,就可以打破強(qiáng)引用死循環(huán)了。為了修正強(qiáng)引用死循環(huán)的問題,精明的程序員會(huì)使用弱引用。運(yùn)行時(shí)會(huì)持續(xù)跟蹤對(duì)象的弱引用。一旦對(duì)象不再有強(qiáng)引用,運(yùn)行時(shí)就會(huì)從釋放該對(duì)象,并將所有指向該對(duì)象的引用改為 nil。對(duì)變量來說(全局、實(shí)例和本地變量),在對(duì)象名前面加上 _weak 限定詞就可以將其標(biāo)記為弱引用。對(duì)于屬性來說,可以使用 weak 選項(xiàng)。在以下這幾類引用中,你應(yīng)該使用弱引用:1. 委托1. property(weak) id delegate;在設(shè)計(jì)模式篇里,“用設(shè)計(jì)模式讓應(yīng)用開發(fā)流水線化”教程將向你詳解委托和目標(biāo)機(jī)制。2.未被頂級(jí)對(duì)象引用的插座變量(Outlet)1. property(weak) IBOutlet NSString *theName;插座變量是對(duì)象間的一種連接(或引用),被歸檔在故事版文件或 nib 文件中,當(dāng)應(yīng)用運(yùn)行并載入故事版或 nib 文件時(shí)就會(huì)恢復(fù)插座變量。故事版或 nib 文件中頂級(jí)對(duì)象的插座變量一般而言是窗口、視圖、視圖控制器或其他控制器等,應(yīng)該為 強(qiáng)引用(默認(rèn)的,或未標(biāo)記的)。3.目標(biāo)1. (void)setTarget:(id _weak)target4.塊對(duì)象中指向 self 的引用1. _block typeof(self) tmpSelf = self;2. self methodThatTakesABlock: 3. tmpSelf doSomething;4. ;塊對(duì)象會(huì)對(duì)它捕獲的變量產(chǎn)生強(qiáng)引用。如果你在塊對(duì)象里使用了 self,則會(huì)對(duì) self 產(chǎn)生強(qiáng)引用。所以,如果 self 對(duì)塊對(duì)象也有強(qiáng)引用(通常都會(huì)這樣),就形成了強(qiáng)引用死循環(huán)。為了避免死循環(huán),你需要在塊對(duì)象的外面創(chuàng)建一個(gè)指向 self 的 弱(或 _block)引用,如上邊的范例所示。課時(shí):管理對(duì)象的可變性,創(chuàng)建并使用值對(duì)象摘要:管理對(duì)象的可變性 可變對(duì)象是指在你創(chuàng)建后能夠變更其狀態(tài)的對(duì)象。一般來說你需要使用屬性或存取方法來進(jìn)行改變。不可變對(duì)象則是創(chuàng)建后便被封裝好,狀態(tài)不可改變的對(duì)象。在 Objective-管理對(duì)象的可變性可變對(duì)象是指在你創(chuàng)建后能夠變更其狀態(tài)的對(duì)象。一般來說你需要使用屬性或存取方法來進(jìn)行改變。不可變對(duì)象則是創(chuàng)建后便被封裝好,狀態(tài)不可改變的對(duì)象。在 Objective-C 框架中創(chuàng)建的大部分類的實(shí)例都是可變的,但有幾種是不可變的。不可變對(duì)象具有如下優(yōu)點(diǎn): 在使用不可變對(duì)象時(shí),不用擔(dān)心它的值會(huì)發(fā)生意外變化。 對(duì)于許多類型的對(duì)象而言,不可變對(duì)象能夠提升應(yīng)用程序的性能。在 Objective-C 框架中,不可變類的實(shí)例通常是封裝起來的離散值或緩沖區(qū)值的集合,比如數(shù)組和字符串。這些類通常帶有一個(gè)可變的衍生類,類名里多出“Mutable”(可變)一詞。比如有一個(gè)NSString類(不可變)和 NSMutableString 類。需要注意的是,對(duì)于 NSNumber 或 NSDate 等封裝了離散值的不可變對(duì)象,就沒必要存在可變的衍生類了。如果你需要經(jīng)常改變對(duì)象的內(nèi)容,那么就使用可變對(duì)象,而不使用不可變對(duì)象。如果你從框架中接收到的對(duì)象是個(gè)不可變對(duì)象,請(qǐng)遵照返回的類型來行事,不要嘗試改變對(duì)象的內(nèi)容。創(chuàng)建并使用值對(duì)象值對(duì)象是指封裝了(C 語言類型的)基本數(shù)據(jù)類型值的對(duì)象,并提供一系列與該值有關(guān)的功能。值對(duì)象在對(duì)象表中代表的是標(biāo)量類型。Foundation 框架為你提供了下列類,用來生成字符串、二進(jìn)制數(shù)據(jù)、日期和時(shí)間、數(shù)字等值對(duì)象: NSString 和 NSMutableString NSData 和 NSMutableData NSDate NSNumber NSValue值對(duì)象在 Objective-C 編程中十分重要,因?yàn)閼?yīng)用會(huì)把這些對(duì)象當(dāng)作方法、函數(shù)的參數(shù)和返回值進(jìn)行調(diào)用。通過傳遞值對(duì)象,框架里的各個(gè)部分甚至不同的框架之間便能夠交換數(shù)據(jù)。因?yàn)橹祵?duì)象代表的是標(biāo)量值,因此你可以在集合或者其他需要用到對(duì)象的地方使用它們。值對(duì)象除了有普通數(shù)據(jù)類型的相同特征和作為編程的必要成分之外,還有更大的優(yōu)勢(shì):你能夠通過更加有效而且十分優(yōu)雅的方式對(duì)這些封裝起來的值進(jìn)行操作。就拿 NSString 類來舉例,它有搜索并替換字符串的方法,有寫入字符串到文件或(更常用)到 URL 的方法,還有構(gòu)建文件系統(tǒng)路徑的方法等。在有些場(chǎng)合中,你可能覺得使用基本數(shù)據(jù)類型更加有效和直接,例如 int(整數(shù)型)、float(浮點(diǎn)型)等等。舉個(gè)具體的例子就是在計(jì)算某個(gè)值的時(shí)候。所以 NSNumber 和 NSValue 對(duì)象很少被當(dāng)作框架中方法的參數(shù)和返回值。然而,需要注意到許多框架會(huì)聲明自己的數(shù)值數(shù)據(jù)類型,并把這些數(shù)據(jù)類型當(dāng)作參數(shù)和返回值進(jìn)行傳遞和調(diào)用,比如 NSInteger 和 CGFloat。你需要在合適的場(chǎng)合使用這些框架定義的數(shù)據(jù)類型,這樣能夠幫助你把代碼提煉出來,遠(yuǎn)離底層平臺(tái)。使用值對(duì)象的基本方法創(chuàng)建值對(duì)象的基本模式是:為你的代碼或框架代碼利用基本數(shù)據(jù)類型值創(chuàng)建一個(gè)值對(duì)象(可能稍后就將其作為方法的參數(shù)傳遞出去)。在你的代碼中,你稍后就會(huì)訪問對(duì)象中封裝的數(shù)據(jù)了。用 NSNumber 類來舉例再合適不過了:1. int n = 5; / 基本數(shù)據(jù)類型的賦值2. NSNumber *numberObject = NSNumber numberWithInt:n; / 利用基本數(shù)據(jù)類型創(chuàng)建一個(gè)值對(duì)象3. int y = numberObject intValue; / 從值對(duì)象中獲得封裝后的數(shù)值(y = n)多數(shù)“值”類會(huì)聲明一個(gè)初始器以及用來創(chuàng)建實(shí)例的工廠方法。有些類比如 NSString 和 NSData 不僅提供了初始器,還有利用存儲(chǔ)在本地、遠(yuǎn)程文件甚至內(nèi)存中的數(shù)據(jù)來創(chuàng)建實(shí)例的工廠方法。這些類還提供了一些補(bǔ)充方法,可以將字符串和二進(jìn)制數(shù)據(jù)寫入某個(gè)文件或 URL 制定的位置中。下邊的范例代碼演示了 initWithContentsOfURL: 方法利用一個(gè) URL 對(duì)象中制定的文件的內(nèi)容創(chuàng)建了一個(gè) NSData 對(duì)象;在使用完數(shù)據(jù)之后,代碼將數(shù)據(jù)對(duì)象寫回文件系統(tǒng)中:1. NSURL *theURL = / 利用字符串路徑創(chuàng)建文件 URL 的代碼2. NSData *theData = NSData alloc initWithContentsOfURL:theURL;3. / 使用得到的數(shù)據(jù)4. theData writeToURL:theURL atomically:YES;大多數(shù)值類除了能夠創(chuàng)建值對(duì)象并讓你訪問封裝好的值以外,還提供一系列簡(jiǎn)單的操作比如比較對(duì)象等。字符串作為 C 語言的超集,Objective-C 關(guān)于字符串的用法和 C 語言一樣。換句話說,單個(gè)字母用單括號(hào)包裹,字符串用雙括號(hào)。不過,Objective-C 框架一般而言不會(huì)使用 C 風(fēng)格的字符串,而是使用 NSString 對(duì)象。在你的第一個(gè) iOS 應(yīng)用教程中,在編寫 HelloWorld 應(yīng)用時(shí)你曾創(chuàng)建了一個(gè)格式化的字符串:1. NSString *greeting = NSString alloc initWithFormat:”Hello, %!”, nameString;NSString 類為字符串提供了一個(gè)對(duì)象包裹,因此自帶有不定長(zhǎng)字符串存儲(chǔ)的內(nèi)存管理功能、支持眾多字符編碼(尤其是 Unicode 編碼)、以及 printf 風(fēng)格的格式化語法。因?yàn)槟銜?huì)經(jīng)常用到字符串,因此 Objective-C 提供了利用常量創(chuàng)建 NSString 對(duì)象的快捷形式。要使用這種快捷形式,只需在常規(guī)的雙引號(hào)包裹的字符串前邊加上 符號(hào),像下面的范例中這樣:1. / 創(chuàng)建字符串“My String”并帶上一個(gè)換行符2. NSString *myString = ”My Stringn”;3. / 創(chuàng)建一個(gè)格式化字符串“1 String”4. NSString *anotherString = NSString stringWithFormat:%d %, 1, String;5. / 利用一個(gè) C 語言字符串創(chuàng)建 Objective-C 字符串6. NSString *fromCString = NSString stringWithCString:A C string encoding:NSASCIIStringEncoding;時(shí)間和日期NSDate 對(duì)象和其他的值對(duì)象不同,因?yàn)樗诟旧鲜菚r(shí)間而不是基本數(shù)據(jù)類型。日期對(duì)象利用參考時(shí)間,按秒封裝了一個(gè)間隔值。參考時(shí)間就是 GMT 2001 年 1 月 1 日的第一個(gè)實(shí)例。光是 NSDate 的實(shí)例自身可能用處還不是很大。它確實(shí)能代表某個(gè)時(shí)刻,但沒有日歷、時(shí)區(qū)和個(gè)別地區(qū)的時(shí)間約定等這些上下文,并無太大意義。幸好 Foundation 類提供了這些概念的實(shí)體: NSCalendar 和 NSDateComponents:你可以將日期和日歷聯(lián)系起來,包括由此引申出的時(shí)間單位例如年、月、小時(shí)、一周中的某一天等。你還可以進(jìn)行日期的計(jì)算。 NSTimeZone:當(dāng)日期和時(shí)間必須反映出某個(gè)地區(qū)的時(shí)區(qū)時(shí),你可以將時(shí)區(qū)對(duì)象和日歷關(guān)聯(lián)起來。 NSLocale:本地化對(duì)象,里面封裝了和時(shí)間有關(guān)的文化和語言格式的規(guī)約。下面的代碼段展示了如何使用 NSDate 對(duì)象配合上述這些對(duì)象來獲取你需要的信息(本例中,當(dāng)前時(shí)間的打印格式為小時(shí),分鐘,秒)。請(qǐng)參考代碼段下邊對(duì)應(yīng)的數(shù)字項(xiàng)后邊的注釋:1. NSDate *now = NSDate date; / 12. NSCalendar *calendar = NSCalendar alloc initWithCalendarIdentifier:NSGregorianCalendar; / 23. calendar setTimeZone:NSTimeZone systemTimeZone; / 34. NSDateComponents *dc = calendar components:(NSHourCalendarUnit|NSMinuteCalendarUnit|5. NSSecondCalendarUnit) fromDate:now; / 46. NSLog(”The time is %d:%d:%d”, dc hour, dc minute, dc second); / 51. 創(chuàng)建一個(gè)表示當(dāng)前時(shí)間的日期對(duì)象。2. 創(chuàng)建一個(gè)表示公歷的對(duì)象。3. 用代表系統(tǒng)偏好設(shè)置中設(shè)定的時(shí)區(qū)的對(duì)象,設(shè)置日歷對(duì)象的時(shí)區(qū)。4. 調(diào)用日歷對(duì)象的 components:fromDate: 方法,將第一步里創(chuàng)建的日期對(duì)象作為參數(shù)傳遞。調(diào)用此方法后會(huì)返回一個(gè)包含了時(shí)間對(duì)象的小時(shí)、分鐘和秒元素的對(duì)象。5. 在控制臺(tái)打印出當(dāng)前的時(shí)、分、秒。雖然這個(gè)范例最終將結(jié)果打印出來,但更加推薦的使用方式是利用日期格式化器(NSDateFormatter 類的實(shí)例)在應(yīng)用的界面上顯示日期信息。在進(jìn)行日期計(jì)算時(shí)一定要選用正確的類和方法;不要對(duì)時(shí)、分、秒、日等數(shù)值單位進(jìn)行硬編碼。課時(shí):創(chuàng)建并使用群體摘要:群體也是一種對(duì)象,它能夠以特定方式存儲(chǔ)其他對(duì)象并允許客戶訪問那些對(duì)象。你通常會(huì)將群體當(dāng)作方法和函數(shù)的參數(shù)進(jìn)行傳遞,也常常從方法和函數(shù)的返回值獲得一個(gè)群體。群體往往包含值對(duì)象,但其實(shí)它們可以包含任群體也是一種對(duì)象,它能夠以特定方式存儲(chǔ)其他對(duì)象并允許客戶訪問那些對(duì)象。你通常會(huì)將群體當(dāng)作方法和函數(shù)的參數(shù)進(jìn)行傳遞,也常常從方法和函數(shù)的返回值獲得一個(gè)群體。群體往往包含值對(duì)象,但其實(shí)它們可以包含任何類型的對(duì)象。大部分群體對(duì)它們所包含的對(duì)象會(huì)產(chǎn)生強(qiáng)引用。Foundation 框架種有好幾種群體,其中三種在 Cocoa 和 Cocoa Touch 編程中極其重要:數(shù)組、字典和集合。這些群體的類同樣分別有不可變與可變的形式。可變?nèi)后w能夠添加和移除對(duì)象,不可變?nèi)后w只能含有它們創(chuàng)建時(shí)所包含的對(duì)象。所有群體都可以進(jìn)行枚舉,也就是輪流檢查所包含的每個(gè)對(duì)象。不同類型的群體會(huì)以各自不同的方式組織它們所包含的對(duì)象: NSArray 和 NSMutableArray:數(shù)組是按順序存儲(chǔ)的一系列對(duì)象。你可以通過某個(gè)對(duì)象的位置序號(hào)來找到它(也就是它的索引)。數(shù)組中的第一個(gè)對(duì)象索引為 0(數(shù)字零) NSDictionary 和 NSMutableDictionary:字典將條目以“鍵值對(duì)(Key-Value)”的形式存儲(chǔ)在一起。鍵是唯一標(biāo)識(shí)符,通常是字符串;值就是你想要存儲(chǔ)的對(duì)象本身。你可以通過鍵來直接訪問它對(duì)應(yīng)的對(duì)象。 NSSet 和 NSMutableSet:集合里的對(duì)象是無序存儲(chǔ)的,并且每個(gè)對(duì)象只能出現(xiàn)一次。通常要訪問集合里的某個(gè)或某幾個(gè)對(duì)象時(shí),你必須使用篩選或?qū)?duì)象進(jìn)行判斷等方式。由于它們的存儲(chǔ)、訪問和性能各有不同,在不同的場(chǎng)合也就各有利弊。在數(shù)組中以特定順序存儲(chǔ)對(duì)象數(shù)組中的對(duì)象是按順序存儲(chǔ)的。因此,當(dāng)順序比較重要時(shí)你就可以選擇數(shù)組。舉個(gè)例子,許多應(yīng)用都采用數(shù)組來存儲(chǔ)表格視圖中的內(nèi)容或者菜單中的項(xiàng)目;索引值為 0 的對(duì)象代表第一排,索引值 1 上的對(duì)象對(duì)應(yīng)第二排,以此類推。訪問數(shù)組中對(duì)象的速度比訪問集合的速度稍慢。NSArray 類有多個(gè)初始器和類工廠方法用來創(chuàng)建和初始化數(shù)組,其中有幾個(gè)尤其常用。你可以利用一系列對(duì)象來創(chuàng)建數(shù)組,使用 arrayWithObjects:count: 和 arrayWithObjects: 方法(及其對(duì)應(yīng)的初始器)即可。前邊一個(gè)方法的第二個(gè)參數(shù)可以用來限制第一個(gè)參數(shù)中的對(duì)象個(gè)數(shù);后面的方法中你可以使用 nil 來中止一系列用半角逗號(hào)分隔的對(duì)象。1. / 創(chuàng)建一個(gè)含有字符串對(duì)象的靜態(tài)數(shù)組2. NSString *objs3 = ”O(jiān)ne”, ”Two”, ”Three”;3. / 用該靜態(tài)對(duì)象創(chuàng)建一個(gè)新數(shù)組對(duì)象4. NSArray *arrayOne = NSArray arrayWithObjects:&(*objs) count:3;5. / 創(chuàng)建一個(gè)用 nil 結(jié)尾的對(duì)象列表的數(shù)組6. NSArray *arrayTwo = NSArray alloc initWithObjects:”O(jiān)ne”, ”Two”, ”Three”, nil;在創(chuàng)建可變數(shù)組時(shí),你可以使用 arrayWithCapacity:(或 initWithCapacity:)方法來創(chuàng)建此數(shù)組。容量參數(shù)只是作為期待數(shù)組大小的預(yù)設(shè)值,能夠讓數(shù)組在運(yùn)行時(shí)更加高效。也就是說,數(shù)組的實(shí)際大小可以超過所指定的容量。一般情況下,要通過索引位置(從 0 起始)訪問數(shù)組中的對(duì)象時(shí)需要調(diào)用 objectAtIndex: 這個(gè)方法:1. NSString *theString = arrayTwo objectAtIndex:1; / 返回?cái)?shù)組中的第二個(gè)對(duì)象NSArray 還有其他方法,你可以訪問數(shù)組中的對(duì)象,也可以訪問它們的索引。比如 lastObject、firstObjectCommonWithArray: 和 indexOfObjectPassingTest: 方法。數(shù)組的另一個(gè)重要功能是對(duì)所包含的每個(gè)對(duì)象均進(jìn)行操作,這個(gè)過程叫做枚舉。你通常會(huì)枚舉某個(gè)數(shù)組,以此判斷某個(gè)或某些對(duì)象是否符合某個(gè)值或者條件,如果條件成立則可以進(jìn)一步進(jìn)行操作。共有三種枚舉方式可供選用:快速枚舉,塊對(duì)象枚舉,或者使用 NSEnumerator 對(duì)象。快速枚舉正如其名稱所示,一般而言在獲取數(shù)組中的對(duì)象時(shí)比其他枚舉方式更快??焖倜杜e有其特定的語法:1. for (type variable in array) /* 規(guī)定 variable,并執(zhí)行所需的操作 */ 比如此例:1. NSArray *myArray = / 獲取數(shù)組2. for (NSString *cityName in myArray) 3. if (cityName isEqualToString:Cupertino) 4. NSLog(”Were near the mothership!”);5. break;6. 7. 有幾種 NSArray 方法是通過塊對(duì)象進(jìn)行枚舉的,最簡(jiǎn)單的一個(gè)是 enumerateObjectsUsingBlock:。塊對(duì)象有三個(gè)參數(shù):當(dāng)前對(duì)象,它的索引值,以及一個(gè)布爾值,如果它為 YES 則枚舉結(jié)束。塊對(duì)象中的代碼效果和花括號(hào)里的快速枚舉效果完全一樣:1. NSArray *myArray = / 獲取數(shù)組2. myArray enumerateObjectsUsingBlock:(id obj, NSUInteger idx, BOOL *stop) 3. if (NSString *)obj isEqualToString:Cupertino) 4. NSLog(”Were near the mothership!”);5. *stop = YES;6. 7. ;NSArray 還有數(shù)組排序、搜索、對(duì)數(shù)組中每個(gè)對(duì)象起作用等的方法。若要往可變數(shù)組中添加對(duì)象,則要調(diào)用 addObject: 方法;新增的對(duì)象會(huì)被放置在數(shù)組末尾。你也可以使用 insertObject:atIndex: 將對(duì)象放在數(shù)組中的某特定位置。通過調(diào)用 removeObject: 或者 removeObjectAtIndex: 方法就可以將對(duì)象從數(shù)組中移除了。用字典存儲(chǔ)鍵值對(duì)利用字典可以將對(duì)象以鍵值對(duì)的形式存儲(chǔ)在群體中,鍵值對(duì)是指一個(gè)標(biāo)識(shí)符(鍵)與一個(gè)對(duì)象(值)組成的對(duì)子。字典是無序群體,因?yàn)殒I值對(duì)可以以任何順序存儲(chǔ)。雖然鍵可以是任意形式,但最好是能夠描述值的字符串,比如 NSFileModificationDate 或 UIApplicationStatusBarFrameUserInfoKey(都是字符串常量)。當(dāng)它們是公有鍵時(shí),用字典在任意類型的對(duì)象之間傳遞信息再好不過了。通過它的初始器和類工廠方法,NSDictionary 類有許多創(chuàng)建字典的方式,但其中兩個(gè)是最為常用的:dictionaryWithObjects:forKeys: 和 dictionaryWithObjectsAndKeys:(或者它們對(duì)應(yīng)的初始器)。前一個(gè)方法中你需要傳入一個(gè)對(duì)象數(shù)組和鍵數(shù)組;鍵和值要在位置上一一對(duì)應(yīng)。后面一個(gè)方法中你需要指定第一個(gè)對(duì)象值和它的鍵、第二個(gè)對(duì)象值和它的鍵、第三個(gè)、第四個(gè),以此類推;用 nil 便可以結(jié)束這個(gè)對(duì)象系列。1. / 首先創(chuàng)建一個(gè)鍵的數(shù)組以及一個(gè)值的補(bǔ)充數(shù)組2. NSArray *keyArray = NSArray arrayWithObjects:IssueDate, IssueName, IssueIcon, nil;3. NSArray *valueArray = NSArray arrayWithObjects:NSDate date, ”Numerology Today”,4. self.currentIssueIcon, nil;5. / 創(chuàng)建字典,將鍵數(shù)組和值數(shù)組傳入6. NSDictionary *dictionaryOne = NSDictionary dictionaryWithObjects:valueArray forKeys:keyArray;7. / 用值、鍵輪流的方式創(chuàng)建數(shù)組,用 nil 來結(jié)束本字典8. NSDictionary *dictionaryTwo = NSDictionary alloc initWithObjectsAndKeys:NSDate date,9. ”IssueDate”, ”Numerology Today”, ”IssueName”, self.currentIssueIcon, ”IssueIcon”, nil;要訪問字典中的對(duì)象值,需要調(diào)用 objectForKey: 方法,并在參數(shù)中指定一個(gè)鍵。1. NSDate *date = dictionaryTwo objectForKey:IssueDate;你可以向可變字典中通過調(diào)用 setObject:forKey: 添加條目,也可以用 removeObjectForKey: 刪除條目,還可以用 setObject:forKey: 來替換任何給定鍵所對(duì)應(yīng)的值。這些方法運(yùn)行速度都很快。用集合存儲(chǔ)無序?qū)ο蠹吓c數(shù)組相似也是對(duì)象群體,但集合中的條目是無序存儲(chǔ)的。你無法通過索引或者鍵來訪問集合里的對(duì)象,而是隨機(jī)訪問(anyObject),通過枚舉群體或者使用篩選器、測(cè)試等方式查找對(duì)象。雖然在 Objective-C 中集合對(duì)象不像字典和數(shù)組那么常用,它們?nèi)匀皇悄承┘夹g(shù)中非常重要的群體類型。在 Core Data(一種數(shù)據(jù)管理技術(shù))中,當(dāng)你聲明一個(gè)一對(duì)多關(guān)系的屬性時(shí),屬性類型就應(yīng)該是 NSSet 或者 NSOrderedSet。集合在 UIKit 框架中的原生觸摸事件處理中也是非常重要的,比如:1. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 2. UITouch *theTouch = touches anyObject;3. / 處理代碼4. 有序集合是集合定義之外的一個(gè)特例。在有序集合中,條目的順序十分重要。測(cè)試某個(gè)條目是否存在時(shí),有序集合比數(shù)組的速度更快。課時(shí):在運(yùn)行時(shí)檢驗(yàn)對(duì)象能力摘要:內(nèi)?。↖ntrospection)是 Objective-C 中 NSObject 類的一個(gè)強(qiáng)大而實(shí)用的特性,可以讓你在運(yùn)行時(shí)獲知關(guān)于對(duì)象的一些信息。這樣,你就能避免一些錯(cuò)誤,比如將消息發(fā)送給一內(nèi)省(Introspection)是 Objective-C 中 NSObject 類的一個(gè)強(qiáng)大而實(shí)用的特性,可以讓你在運(yùn)行時(shí)獲知關(guān)于對(duì)象的一些信息。這樣,你就能避免一些錯(cuò)誤,比如將消息發(fā)送給一個(gè)不認(rèn)識(shí)它的對(duì)象,或者以為某個(gè)對(duì)象繼承自另一個(gè)對(duì)象,實(shí)際上卻不是。在運(yùn)行時(shí),對(duì)象可以傳達(dá)關(guān)于它自己的三種重要類型的信息。 它是否是某個(gè)類或子類的實(shí)例 它是否能響應(yīng)某條消息 它是否遵守某個(gè)協(xié)議探究對(duì)象是否是某個(gè)類或其子類的實(shí)例這樣做的方式是對(duì)對(duì)象調(diào)用 isKindOfClass: 方法:1. static int sum = 0;2. for (id item in myArray) 3. if (item isKindOfClass:NSNumber class) 4. int i = (int)item intValue;5. sum += i;6. 7. isKindOfClass: 方法需要一個(gè) Class 類型的對(duì)象作為參數(shù);要獲得這個(gè)對(duì)象,在類符號(hào)上調(diào)用 class 方法便可。檢查此方法返回的布爾值并進(jìn)行下一步操作。NSObject 還聲明了其他用來探究對(duì)象繼承信息的方法。比如 isMemberOfClass: 方法會(huì)告訴你對(duì)象是否是某個(gè)指定類的實(shí)例,而 isKindOfClass: 會(huì)告訴你對(duì)象是否是某個(gè)類或其子類的成員。探究對(duì)象是否能夠響應(yīng)某個(gè)消息這樣做的方法是對(duì)對(duì)象調(diào)用 respondsToSelector: 方法:1. if (item respondsToSelector:selector(setState:) 2. item setState:self.arcView.font isBold ? NSOnState : NSOffSta
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年中國(guó)FM自動(dòng)選臺(tái)收音機(jī)望遠(yuǎn)鏡數(shù)據(jù)監(jiān)測(cè)研究報(bào)告
- 2025年中國(guó)BOPP鍍鋁膜數(shù)據(jù)監(jiān)測(cè)研究報(bào)告
- 2025年中國(guó)2、5-二甲基苯胺數(shù)據(jù)監(jiān)測(cè)報(bào)告
- 2025至2030年中國(guó)集中操作式電梯井筒模市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)鋁合金吸頂燈市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)茴香粉市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)砼攪拌站市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)電力控制開關(guān)柜市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)深溝外球面球軸承市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 2025至2030年中國(guó)汽車儲(chǔ)液器支架市場(chǎng)分析及競(jìng)爭(zhēng)策略研究報(bào)告
- 初三勵(lì)志主題班會(huì):初三第一次班會(huì)幻燈片PPT
- GB/T 42910-2023無機(jī)膠粘劑高溫壓縮剪切強(qiáng)度試驗(yàn)方法
- 2022年江蘇省射陽中等專業(yè)學(xué)校招聘考試真題及答案
- 給攪拌站送石子合同范本
- 2023年副主任醫(yī)師(副高)-學(xué)校衛(wèi)生與兒少衛(wèi)生(副高)考試歷年真題集錦帶答案
- 法律基礎(chǔ)(第4版)PPT完整全套教學(xué)課件
- 倉管應(yīng)聘求職簡(jiǎn)歷表格
- 五年級(jí)下冊(cè)語文期末考試學(xué)霸奪冠解密卷人教部編版含答案
- 房屋加固工程監(jiān)理規(guī)劃
- 一級(jí)煙草專賣管理師理論考試題庫(含答案)
- von frey絲K值表完整版
評(píng)論
0/150
提交評(píng)論