




下載本文檔
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
Objective-CC詫言增加了面向對象功能的詫言,是開發MacOSX、iPodtouchiPad在為C詫言加入了面向對象功能的詫言中,C++是最有名的一種。Objective-C和C++完全丌同。Objective-CJava、C#Ruby也有所丌同,是一門比Objective-C最大的特點是支持面向對象編程,具備徆多勱態詫言才有的勱態特征,同時在效率上還可以媲美C詫言。學習過其他面向對象詫言的人可能會對Objective-C為C詫言添加的功能乊少感到驚訝。MacOSXiOS的逐步更新,Objective-C運行的系統環境也做了同步升級。同時Objective-C詫言本身也引入了丌少新的特性,包括一種新的內存管理斱式——ARC。另外屬性和代碼塊(block)的使用范圍也得到了擴大。Objective-C的編程MacOSXiOS應用為目的來介縐Objective-CC詫言基礎,但并丌要求精通C詫言。Objective-C和蘋果公司的產品和運行環境緊密相關,介縐Objective-C的時候無中的主要類,同時也盡可能了MacOSX和iOS的丌同乊處。 GUI控件的使用,所以并丌是說讀了本書就能立刻做出一個具有優美界面的應用程序。已絆有太多的優秀書籍介縐GUI編程的斱斱面面,請參考這些的內容。Xcode是蘋果公司向開發人員提供的集成開發環境,用亍開發MacOSX和iOS的應用,其中自帶了Objective-C的編譯器。到筆者寫作本書為止,Xcode可以免費安裝(叧能安裝在蘋果系統中,沒有Windows版)。而丏叧要加入蘋果公司的開發者計劃,成為AppleDeveloper,就可免費獲取創建iOS應用和Mac應用的資源,包 戒iPad的真機上測試自己開發的應用并發布到AppleStore,則需要加入蘋果公司的iOS開發者計劃。本代碼都是終端類型的程序,叧要安裝了Xcode,丌需要對Xcode作任何Objective-CARC的斱斱面面,從工作原理AFoundationBCoreFoundationC MacOSX和iOS的軟件開發環境的可擴展性非常好,也徆人性化,叧要具備基礎知識就能夠開發出簡單的應用。但如果要開發一個真正的應用,還需要具備系統化的Objective-C知識,因為運行環境是為了最大限度地發揮Objective-C的特征而設Objective-C的基礎知識乊后,你也就可以更加得心應手地使用2011年10月5日,Apple公司(NeXT公司)的締造者逝丐。總能第1 與 與 與 第2 類的接口與 與 編 與 參考文檔和 與 第3 使用self調用斱 使用super調用斱 與 第4 多 空指針 與 與 類的前置 類對 類變 第5 計 斱法和對象所與 與 常量修飾符 分數類 什么是 斱法 斱法dealloc的定 循環和弱循環 弱自勱nil化的弱 第6 回 弱自勱nil 實時 第7 屬性 與 原子 第8 類 初始 選擇器和SEL類 cocoa環境和 Touch和 框 與 第9 字符串類 數組 數組對象的所 枚丼器 集合 詞典 包裹 關亍 第10 范 范 范 類擴 與 關聯 第11 抽象 類 第12 協 協議的 與 第13 對象的及對象的淺和深區 實現可變歸 屬性 第14 塊對 C編譯器 塊對象和類型 塊對象的 作為Objective-C對象的塊對 第15 委 通 與 反應 第16 應用 與 iOS中資源的 加載nib文 在 X中加載nib文 在iOS中加載nib文 默訃 本地 沙盒 第17 通 main函數和MyViewerCtrl 類 類 與 第18 異 異常表示類 與 日志輸出函數 異常的發生和異常的 異常處理程序的斷 斷言 與 與 多線 373使 互 死 條件 NSOperation和NSOperationQueue的簡單用 類 類 類 連 398 第20章
屬 根據鍵路徑迚行 一對多關系的 一對多關系的可變 什么是Cocoa紼 Objective-C近年來一直備受關注,它誕生于1983年,設計之初和C++一樣都是為給C語 發布之前,Objective-C一直都是一門默默無聞的小眾語言,而C++則長期占據編程語言榜的前幾名。隨著 銷量的爆發性增長,Objective-C語言的份額也迅速增長。在TIOBE編程語言榜上,Objective-C只用了短短的3年時間就從2009年8月的第二十名增長到了2012年7月的第三名(僅次于C語言和Java,截至今天仍然因為Objective-C流行的時間還比較短,所以就算是開發過多個上架AppiOS程序員也仍可能不完全了解Objective-C語言。例如,不知道消息轉發背后的工作機制,不了解Objective-C幾種內存管理之間的區別,不清楚該如何選擇Delegate、Notification和KVO等。本書是一本專門講解Objective-C的,雖然作者并不會教你如何使用Xcode開發一個運 上的App,但用了20章的內容深入講解了Objective-C的各個特性。2014年蘋果公司在WWDC2014開發者大會上發布了用于MacOSX和iOS編程的新一代編程語言Swift,相信很多讀者一定在為應該學習Objective-C還是應該直接學習Swift而感到困惑。Swift于2014年才發布,而目前市面上至少有上百萬個App和類庫都是用Objective-C編得Objective-C。除了講解Objective-C語言本身外,本書還介紹了與其密不可分的Foundation框架,介紹了本書的作者荻原剛志教授從 還誕的201就始寫cSX的bcieC編程門書,是eie-C方面正的專。者寫這本時把人認嚴謹天性發揮到了致,了400頁來講解eie。本已經再版了三次,本次譯的就是的第三版。作者在講述每個知識點的時候都精心配置了示例代碼,所有的示例代碼均可運行。相信過本的習一能打堅的btvC礎發更妙的p。Objective-C是一門為C語言增加了面向對象功能的語言,是開發MacOSX、、iPodtouch和iPad應用的主要語言。在為C語言加入了面向對象功能的語言中,C是最有名的一種。Objective-C和C完全不同。Objective-C和大家所熟知的Java、C#和Ruby也有所不同,是一門比較獨特的語言。Objective-C最大的特點是支持面向對象編程,具備很多動態語言才有的動態特征,同時在效率上還可以媲美C語言。學習過其他面向對象語言的人可能會對Objective-C為C語言添加隨著MacOSX和iOS的逐步更新,Objective-C運行的系統環境也做了同步升級。同時Objective-C語言本身也引入了不少新的特性,包括一種新的內存管理方式——ARC。另外屬性和代碼塊(block)的使用范圍也得到了擴大。Objective-C的編程風格這些年一直在不停地本書以開發MacOSX或iOS應用為目的來介紹Objective-C,默認讀者具備C語言基礎,但并不要求精通C語言。Objective-C和蘋果公司的產品和運行環境緊密相關,介紹Objective-C的時候無法脫離具體的操作系統或框架。本書在介紹語言本身的同時也介紹了Foundation框架中的主要類,同時也盡可能了MacOSX和iOS的不同之處。另,書不一解cSX和 形面程書不涉及I件使用,所以并不是說讀了本書就能立刻做出一個具有優美界面的應用程序。已經有太多的優秀書介紹I編的方面面請參這些的。Xcode是蘋果公司向開發人員提供的集成開發環境,用于開發MacOSX和iOS的應用,其中自帶了Objective-C的編譯器。到筆者寫作本書為止,Xcode可以免費安裝(只能安裝在蘋果系統中,沒有Windows版。而且只要加入蘋果公司的開發者計劃,成為AppleDeveloper,就可免費獲取創建iOS應用和Mac應用的資源,包括開發工具、示例代碼、技術文 或iPad的真機上測試自己開發的應用并發布到AppleStore,則需要加入蘋果公司的iOS本代碼都是終端類型的程序,只要安裝了Xcode,不需要對Xcode作任何設置,就 序詳細介紹了Objective-C新引入的內存管理方式ARC的方方面面,從工作原理到編程時的各種注意事項。以使用ARC為前提對示例程序做了大幅修改,同時簡化了手動內存本書中講解的所有內容都經過了實際編碼測試。本書的代碼在MacOSX10.7和iOS5以上AFoundationBCoreFoundationC編碼原則 MacOSX和iOS的軟件開發環境的可擴展性非常好,也很人性化,只要具備基礎知識就能夠開發出簡單的應用。但如果要開發一個真正的應用,還需要具備系統化的Objective-C知識,因為運行環境是為了最大限度地發揮Objective-C的特征而設計的。通過本書學習了Objective-C的基礎知識之后,你也就可以更加得心應手地使用其他框架了。開始享受你的Objective-C2011年10月5日,Apple公司(NeXT公司)的締造者逝世。總能像魔第3類和 33.13.1(inhertance(superclass(subclass繼承意味著子類繼承了父類的所有特性,父類的數據成員和成員函數自動成為子類的數據成和成員函數。除此之外,子類還可讓我們來看幾個例子。在圖3-1中,類BA的子類BA的實例但重寫了method2。類C也是類A的子類,類C中增加了新的實例變量z和新的方法method3。類B和類C都是類A的子類,無論類A、類B和類C的任何一個實例變量都能夠執行方法method1和3-1繼承的概念父類和子類是一種相對的稱呼。例如,在上例中,如果以B為父類又派D,那么類B相對于類A是子類,相對于類D卻為父類。繼承的概 類的擴展。為了避免這種命名上的,C++中把父類稱為基類(baseclass),把子類稱為派生類或導出類(derivedclass)。考慮到面向對象的程序設計中一般都使用父類、子類的叫法,本書也.2類的層次結假如以某個類為父類生成若干子類,然后再繼承這些子類并生成的子類,如此循環下去就可能會生成一顆倒立的樹,它由通過繼承而彼此關聯的類組成,這樣的樹稱為類層次結構(cassheacy。3-2類層次結構的概念ClassClassClassClassClassClassClassClassClassClassClassClassClassClassClassRootNSObjectCocoa環境下的根類,Cocoa中所有的類都直接或間接地繼承了NSObjectA。新建的任何類都必須是NSObject或它的繼承類的子類。NSObject中定義了所有Objective-C對象的基本由于這種類的層次關系,Objective-C的所有對象都繼承了NSObject類中定義的各種屬性。Objective-C的對象能夠作為對象來使用,就是因為類NSObject中定義了對象的基本功能在面向對象的語言中,有的和Objective-C一樣有唯一根類,例如JavaSmalltalk等;有的則不存在唯一根類,如C++。A實際上,除了NSObject之外,Cocoa環境中還有一個根類NSProxy(詳細內容請參考第19章 33.23.2語類定@interface類名:父類{實例變量的.}方法的.至此為止本父類都使用了NSObject,這是因為Objective-C中所有的類都要繼承根類,而NSObjectObjective-C中所有類的根類。如果子類有想繼承的類,就要直接指明該類為父類,否則就需要指定NSObject為父類。前文中定義Volume類的時候,因為Volume類并沒有特別想繼承的類,所以直接使用了NSObject作為父類。實例變量的中只需要新增的變量。如果沒有新增的變量,則只需要加上{}即可,有時甚至連{}都可以省略。 下面展示了定義類AB時接口部分的情況。變量x和方法method1繼承于類A,所以不需要重新,方法method2的也可以被省略。@i@interfaceB:-(voidmethod2 //這個方法被覆蓋圖3-1中定義類C時的接口部分如下所示,需要對變量z和方法method3進行@i@interfaceC:{i z}-(void)method3;@end利用繼承定義新 假設有一個已經定義好了的類Alpha,那么頭文件Alpha.h就應該已經存在。要定義類Alpha的Beta的時候,頭文件Betah中必須包含Alpha.h。不知道父類定義的話是無法定義子類的。所以圖3-3的文件Gammam的方法中調用了方法doSomething,這個方法是從類Alpha繼承而來的。文件Gammam引入的頭文件Gamma.h中引入了Betah,Betah中又引入了Alphah,所以Gamma.m可以調用方法doSomething。3-3繼承和頭文件的關系##import"Alpha.h...@implementationAlph...-(void)doSomething{......@e"MQIB#import"Beta.h...@implementationBet...@e#FUB#import"Gamma.h...@implementation...[selfdoSomething]...@e(BNNB(BNNB@interfaceGamma:Bet{...}...@e#import"Beta.h#FUB@interfaceBeta:Alph{...}...@e#import"Alpha.h"MQIB@e#import<Foundation/NSObject.@interfaceAlpha:NSObjec{...}-(void)doSomething .3繼承和方法調如圖3-4Amethod1、method2、method3。類B是類A的子類,類B中重新定義了method2。類C是類B的子類,類C中重新定義了method1。3-4繼承和方法 我們來看看給類B的實例變量發送消息時的情況。首先,假設向類B的實例對象發送了對應method1的消息,即進行了方法調用。雖然類B中沒有method1的定義,但因為類B的父類類A中定義了method1,所以會找到類A的method1,調用成功。消息method3的情況下也是同樣的道理,類A中定義的method3會被執行。method2同前兩個消息不同,類B中定義了method2,所以會使用自身定義的method2來響應這個消息。而給類C的實例發送消息的話會怎么樣呢?類C中有method1的定義,所以會直接使用類C中定義的method1來響應這個消息。類C中沒有method2的定義,所以調用的時候會使用類B中定義的method2來響應。類C和類B中都沒有定義method3,所以類A中的定義method3會被調用。.4調用父類的方子類繼承了父類之后,有時就可能會希望調用父類的方法來執行子類中定義的其他處理,或者34B的eho2的定義中調用類A的ehod,那么該怎么辦呢?通過ef調用ehod2ehod2。如果子類中想調用父類的方法,可以通過super關鍵字來發送消息。使用super發送消息后,就會調用父類或父類的父類中定義的方法。如圖3-5所示,類C中定義了method1和method3。類C的method1中通過super調用了method3,這時被調用的method3是類A中定義的method3。3-5super送消息
利用繼承定義新 [supermethod3[supermethod2super和self不同,并不確定指向某個對象。所以super只能被用于調用父類的方法指定為.5定--(id)in{self=[superinit]; /*定要在第一行調用父類的init方法*/if(self!=nil){ /*返回了初始化好的實例時*/ 子類專/**}returnself}請注意第一行調用了父類的init方法,父類的init方初始化父類中定義的實例變量。下如果所有的類的初始化方法都這樣寫,那么根類NSObject的init方法就一定會被執行。否則執行的時候父類的初始化方法可能會出錯。出錯時則會返回nil,這種情況下子類也不需要再進行初始化,直接返回nil就可以了。如果父類是Nbe,則基本上不可能初始化出錯,因此不判斷這個返回值也是可以的。使用傳入的參數或通過從文件讀入變量進行初始化時,因為值的類型錯誤或文件失敗等原因,初始sf進行了賦8章中詳細說明,這里只需要記住這是初始化方法的一種固定寫法即可。生成實例對象的方法alloc會把實例對象的變量都初始化為0(后面會提到的實例變量isa除外。所以,如果子類中新追加的實例變量的初值可以為0,則可以跳過子類的初始化。但是為了明 3從程序的書寫角度來說,設定初始值的方法有兩種,即可以在初始化方法中完成實例變量的初始化,也可以在初始化方法中先設置實例變量為默認值,然后再調用別的方法來設置實例變量oue也可以通過先調用初始化方法init,然后再調用setax等方法來設定音量的最大值、最小值和變化幅度。原則上來說,初始賦值之后值不再發生變化的變量和需要顯示設.1追加新方法的例我們來定義一個帶有靜音功能的類MuteVolume。該類只有一個功能,即當收到mute消息時,類MuteVolume的定義非常簡單,父類是已經定義Volume。子MuteVolume除了可以使用父類Volume中定義的所有實例變量和方法之外,還新增加了一個mute方法。代碼3-1文件MuteVolueme.h-版本1##import"Volume.h@interfaceMuteVolume:Vol *父類是Volume*-(id)mute;@end這里使用了Volume作為父類,并引入了頭文件Volumeh。Volume的父類是NSObject,所以MuteVolumeNSObject的派生類。因Volumeh中已經引入了Foundation/NSObjecth(2-2),代碼3-2MuteVolume.m1#impo#import"MuteVolume.h"@implementationMuteVolume-(id)mut{val=minreturnself}代碼 3-3用于測試類MuteVolume的main程
使用繼承的程序示 ##import"MuteVolume.h"#import<stdio.h>intmain(void{idvcharbuf[8]v=[[MuteVolumealloc]initWithMin:0max:10step:2];while(scanf("%s",buf)>0){switch(buf[0])case'u':[vup];breakcase'd':[vdown];breakcase'm':[vmute];break;case'q':return0;}printf("Volume=%d\n",[vvalue])}return0}量。具體來說,第一個字符為u時表示提高音量,d表示降低音量,m表示靜音,q表示退出程序。%%clangmain.mVolume.mMuteVolume.m-frameworkFoundati3.3.2方法重寫的例假設該例子要實現兩個功能。第一個功能是,當再次收到mute消息時,音量會恢復原值;第二個功能是,在靜音狀態下收到up或down消息時,會返回最小音量值,同時改變音量值。實現這些功能的方法有很多,這里我們增加一個BOOL類型的變量muting,同時修改方法initWithMin:max:step:和方法value的實現。碼 3-4文件MuteVolume.h-版本##import"Volume.h@interfaceMuteVolume:Vol { muting} 3//*override*(id)initWithMin:(int)amax:(int)bstep:(int)s(int)value@end代碼 3-5文件MuteVolume.m-版本#impo#import"MuteVolume.h"@implementationMuteVolume/*override*(id)initWithMin:(int)amax:(int)bstep:(int){self=[superinitWithMin:amax:bstep:s];if(self!=nil)muting=NO;returnself;}/*override*(int)valu{returnmuting?min:va}(id)mut{muting=!muting;returnself;}初始化方法initWithMinmaxstep:首先調用了父類的初始化方法,然后對新增value方法根據當前是否為靜音狀態返回不同的值。靜音狀態下,返回最min。mute方法中只需要改變實例變量muting的狀態來標識是否靜音,不需要更改音量值val。.1self調用方如果想在一個方法中調用當前類中定義的方法,可self。但如果存在繼承關系,通過self繼承和方法調 在圖3-6的例子中,有三個類A、B、CAmethod1、method2method3三個方法。類B繼承了類A,重寫了method1和method3。類C繼承了類B,重寫了method2。[selfmethod1];[selfmethod2]假設類B的方法method3想調用method1和method2,通過self調用了method1和method2。我們來分析一下這個過到底哪個函數被調用了。對類B的實例對象調用method3方法時,首先會通過self調用method1,這個method1就是類B自身定義的method1。接著,method3通過self調用method2,因為類B中并沒有method2的定義,所以就會調用從類A中繼承而來的method2。而如果是類C的實例對象調用方法method3的話會怎么樣呢?我們首先來看看method3,因為類C中并沒有定義method3,所以調用的是類B中定義的method3。要注意這個時候selfC的實例對象,當selfmethod1]執行時,因為類C中沒有定義method1,所以調用的是類B中定義的method1。然后,當selfmethod2]執行時,因為類C中定義了method2,所以執行的是類C中定義的method2,而不是上例中類A中定義的method2。另外還有一點需要注意,就算類B中定義了method2,調用的也是類C中定義的method2。也就是說,self指的是收到當前消息的實例變量,因此,就算是同一個程序,根據實例的類的不使用self的時候要一定,要仔細分辨到底調用了哪個類的方法。即便如此,利用self的特性來編程也是很常見的,詳細內容請參考11.1節的內容。而如果self而使用super,程序執行的結果會怎樣呢3-7是用super替代圖3-6中的self的情況。使用super調用方法時,最后被調用的方法是類B的父類中定義的方法。所以無論是類B還是類C的實例變量調用了method3,最后調用到的都是類A中定義的method1和method2。 3[supermethod1];[supermethod2測試程序中有三A、B、CA中定method1method2B中對method1進行了重寫,通過self調用了method1,通過super調用了method2。類C重寫了method1。碼 3-6文件##import<Foundation/NSObject.h>#import<stdio.h>@interfaceA:NSObjec(void)method1(void)method2;@end@implementation(void)method1{printf("method1ofClassA\n");(void)method2{printf("method2ofClassA\n");}@end@interfaceB:(void)method2;@end@implementation(void)method2printf("method2ofClassB\n");printf("self-->");[selfmethod1]printf("super-->");[supermethod2];}方法定義時的注意事 @i@interfaceC:(void)method1;@end@implementation(void)method1{printf("method1ofClassC\n");}@endintmain(void{idx=[[Balloc]init];idy=[[Calloc]init];printf("---instanceofB---\n");[xmethod1];[xmethod2]printf("---instanceofC---\n");[ymethod1];[ymethod2];return0;}程序執行之后輸出如下。可以看出BC的實例分別調用了不同的方法----instanceofB---method1ofClassAmethod2ofClassBself-->method1ofClassAsuper-->method2ofClassA---instanceofC---method1ofClassCmethod2ofClassBself-->method1ofClassCsuper-->method2ofClassA.1(通常是.m文件行。這樣一來,就算其他模塊了接口文件,也無法獲得這個方法的定義,無法調用這個方 3讓我們來看一個簡單的例子,類ClickVolume是類Volume的一個子類,它的主要功能是當音量發生變化(提高或降低)時發出提示音。提高或降低音量時發出提示音使用一個共同的方法playClick,定義如下所述。因為這個功能不會在其他地方使用到,所以我們把它定義成一個局@i@interfaceClickVolume:Volidup playClic法沒有在這@end@implementationClickVolvoidplayClick{//類內部定義的局部方}(id)up[selfplayClick]return[superup]}(id)down[selfplayClick]return[superdown]}未在接口中的局部方法和沒有進行屬性的C語言函數一樣,只能被定義在局部方法之后的方法調用。在上面的例子中,playClick就必須定義up和down的前面。定義順序方面出現的問題,可以使用第10章介紹的“范疇”(category)來解決。編程的時候使用局部方法可以增強程序的可性,但在繼承的時候可能會出現問題。例如,.2指定初始化方法等。(dsgadnaze就是指能確保所有實例變量都能被初始化的方法,這種方是始化,類非始方調指始化法成初化通常接參最多3.5方法定義時的注意事 子類的指定初始化方法,必須調用超類的指定初始化方法3-8中所示,按照類層次從底向上,各個類的指定初始化方被連鎖調用,一直到最上層的NSObject的指定初始化方法——init???????如果子類中想重寫父類中的指定初始化方法,就一定要調用父類的指定初始化方法,而不能調用父類的非指定初始化方法。原因是非指定初始化方法內部會調用指定初始化方法,造成遞歸循環請看圖3-9中的例子,類A的指定初始化方法是initWithMax:。init是類A的非指定初始化方法。類B是類A的子類,在B中重寫了指定初始化方法initWithMax:。initWithMax:中調用A的init。如圖所示,如果類A的init中通過self調用了initWithMax:,那么,當初始化對象是類B的實例時,就又會調用到類B的initWithMax:,這樣就變成了一個遞歸循環,3-9繼承時重寫指定初始化方法的錯誤 -(id)in{[selfinitWithMax:100];returnself;}-(id)initWithMax:(int)ma
-(id)initWithMax:(int)ma{[superinit];maximum=max;returnself;}{...}
再讓我們回頭看一下圖3-8,圖3-8中類的非指定初始化方法都調用了指定初始化方法來進行初ObeciveC沒有特殊的語法或關鍵字來表明哪個方法是指定初始化方法,所以通常需要通過文檔或注釋來標明指定初始化方法。CocoaAPI文檔中的絕大多數類都標明了哪個方法是指定初始化方法。 3202080代末, (BradCox)發明了Objective-C并創建了公司Stepstone。后來NeXTSoftware公司獲得了Objective-C語言的,1996年蘋果公司宣布收購NeXT公司,擁有Objective-C言的所。Objective-C身的規范是公開的,編譯器也是NeXTstep司Objective-C譯器是基于GUNgcc譯器擴NeXTstep司又把這些擴展貢獻出來,所以現在的gcc是能夠編譯Objective-C程序的。但是gcc和Cocoa使用不同的類庫,所以本例子程序無法在gcc環境下執行。因為gcc的問題,很多開源社區把編譯器由gcc為了llvm。蘋果公司也為LLVM(.org/)項目提供了支援can增加了bjctie-C新功能(例如,ARC動技術等。蘋果公司的Cocoa并沒有開源,但OPENSTEP(Cocoa的基礎)被NeXT公司開源了(OpenStep是一個開放的操作系統的規范,OPENSTEP是基于OpenStep規范的操作系統的名字,由NeXT公司開發。OpenStep在自由軟件的實現叫作 )。這個項目的界面采OPENSTEP格,并提供了兩個相當于MacOSXFoundationApplicationKit程序庫,應用程序使Objective-CGUNStepUnixWindows也有人嘗試Cocoa應用序移植到GUNStep上面專欄:Objective-C與開源第19并行NSOperation在MacOSX中使用的連接的概況。 19章并行編.1線程的基本概(had(pocsACU只有一個線程,但也可以創建多個線程并在進并行執行。應用在執行某一處理的同時,還可以接收UI除此之外,之后生成的線程稱為次線程(secondarythread)或子線程(subthread。的處理,但父線程可以等到子線程執行終止后與其會合(on。而另一方面,程被創建后,也(deacNhad由于被創建的線程共享進程的地址空間,所以能夠自由進程的空間變量。多線程的變量variable如果多線程胡亂共享變量,那么就不能保證變量值的正確性。所以有時就需要按照一定的規則使多線程可以協調動作。此時就必須執行線程間互斥(或者排他控制,mutualexclusion)(見19.2節使用計數管理方式時,為了使對象之間解耦合,子線程方需要創建與父線程不同的自動釋.2線程安需要注C語言的函數。就現狀來看,BSD函數的大部分,例如printf(等,都不是線程安多線
換、共享資源的互斥、與GUI的交互及動畫顯示等,在使用時都要特別。多線程便不能發揮效果,甚至還會導致未知原因的釋放或異常終止。使用19.3節中介紹的而且,很多多線遇見的問題都可以通過NSTimer類或延遲消息發送(參考15.1節)來解決。19.1.419.1.4使用NSThread建線Foundation框架中提NSThread類來創建并控制線程。該類Foundation/NSThread+(void)detachNewThreadSelector:(SEL)aSelectotoTarge (id)aTargewithObjec (id)anArgumen對對象aarget調用方法創建新線程并執行。選擇器aSelector必須是僅獲取一個id類型參數且返回值為void(參考8.2節。使用計數管理(手動及ARC)時,有時需要執行的方法自身來管理自動釋放池。此外,參數aTarget和anArgument中指定的對象也與線程同時存在,即在創建線程時被保存,程終止時使用下述的NSApplication類中的方法也能創建線程。該方法使用上面的方法,而且在使用+(void)detachDrawingThread selectotoTarge (id targewithObjec (id)argumen創建新線程并執行的方法除了上述方法還有很多,本書中不再一一介紹。其他方法請參 19章并行編以調用+(BOOL isMulti多個線程并行執行時或者只有主線執行時,只要在此之前已經創建了線程,則返回YES19.1.519.1.5當前線子線程將創建時指定的方法執行完后也會隨之終止,但也可以中途終止。為此,可以使用當前(線程自身來執行下一個Nhad方法但,使用計數理時終止一定要放+(void)exi使用下述方法獲得表示線程的NSThread+(NSThread*)currentThre獲得表示當前線程的NSThread實例+(NSThread*)mainThre獲得表示主線程的NSThread實例。查看當前線程是否為主線程時,可以使用類方法isMainThread每個線可以持有一個該線程固有的NSMutableDictionary類型的字典。向NSThread實例發-(NSMutableDictionary* threadDictionar+(void sleepForTimeInterval (NSTimeInterval +(void)sleepUntilDate:(NSDate*)aDat19.1.619.1.6GUI在使用GUI的應用中,事件處理和繪圖等大部分處理中線發揮了重要作用。也可以在子線GUI應用中有較容易的方法來使用線程,即將GUI相關的時間處理或繪圖集中在主線進行。使用下面的方法,就可以從子線程依賴主線的方法處理。該方法為NSOjbect的范疇,在頭文件Foundation/NSThreadh中。互斥
-(void)performSelectorOnMainThread:(SEL)aSelectowithObjec (id)arwaitUntilDone:(BOOL)wa選擇器aSelectr和參數arg中指定的方法的執行依賴于主線程。ait為S時,當前線程會一直等待(運行回路。19.2互斥19.2互斥19.2.1需要互斥的例例如,使用整數totalNumber來累加所處理的數據的個數。為了執行下面的加法計算,--(void)addNumber:(NSIngeger){totalNumber+=n}在OS功能支持下,線運行的過會時而得到CPU的執行權,時而被掛起執行權,2個方法的執行情況如圖19-1中所示。在該圖中,線程1將新計算的值保存在寄存器時掛起CPU執行權,同時線程2開始執行方法。即使CPU的執行權被掛起,寄存器的值也仍然可以被保存,所以各線能正常處理。但是,由于線程2寫入的值了,因此整體上看,這偏離了我們期待的結果。19-1沒有互斥的例子<<???>?<???>?UPUBM/VNCFS?<???>UPUBM/VNCFS?<??? 19章并行編在圖19-1的例子中,同時只可以由一個線程占有并執行的代碼部分稱為臨界區(critical.2鎖為了使多個線程間可以相互排斥地使用全局變量等共享資源,可以使用NSLock類。該類的實例Cocoa環境中也稱為鎖(lock。鎖和普通的實例一樣,使用類方法alloc和初始化器init來創建并初始化。但是,鎖應該在程NSLoNSLock*countLock=[[NSLockalloc]init](void lo如果鎖正被使用,則線程進入休眠狀如果鎖沒有被使用,則將鎖的狀態變為正被使用,線程繼續執行(void)unlo將鎖置為沒有在被使用,此時如果有等待該鎖資源的正在休眠的線程,則將其喚在上例中,使用鎖后會產生如下效果。但需要預先創建NSLock的實例aLock。在該代碼中,從某線程執行A取得鎖到該線程執行B釋放鎖期間,其他線執行A時將進入休眠狀態,不能執行臨界區代碼。鎖被釋放后,在執行A時休眠的線選擇一個線程,該線取得鎖后進入臨界--(void)addNumber:(NSIngeger){[aLocklock];─────────────────────────────────────────totalNumber+=n //臨界[aLockunlock];}某個鎖被lock后,必須執行一次unlock。而且lock和unlock必須在同一個線程執行A。時theCount若想正確地自增,就需要使用鎖countLock來管理。Alock和unlock必須在同一個線執行,因為NSLock是基于POSIX線程實現的 互
--(int)in{[countLocklock]++theCoun[countLockunlock];returntheCount;}--(int)in{inttmp[countLocklock];tmp=++theCoun[countLockunlock];returntmp;}各線程持有獨立的棧,自動變量tmp可以在整個線局部利用,而且無需擔心被其他線程訪問。如果按照這樣的方式執行,就可以得到臨界區之后的正確值。19.2.319.2.3死鎖[lockForAl[lockForAlock].../***[lockForAunlock]/[lockForBlock].../*[lockForBunlock][lockForBlock].../***[lockForBunlock]/[lockForAlock].../*[lockForAunlock] 線程1占有文件A并正在進行處理,途中又需要占有文件B。而另一方面,線程2占有著文件B,途中又需要占有文件A。大家不妨設想一下,如果線程1和線程2同時執行到了圖中的箭頭位置會怎么樣呢?線程1為了處理文件B想要獲得鎖lockForB,但是它已經被線程2獲得。同樣,線程2想要獲得的鎖lockForA也被線程1占有著。這種情況下,線12就會同時進入休眠狀態,而且 19章并行編預,有時則是一個線程因為自己需要獲得鎖而進入休眠狀態。此外,由于多數情況下各個線程本身并沒錯處理而死鎖隨可發生因因就常,不排除致序bg可能。19.2.419.2.4嘗試獲得NSLock類不僅能獲得鎖和釋放鎖,還有檢查是否能獲得鎖的功能。利用這些功能,就可以在不(BOOL)tryLo用嘗試獲得某個鎖,如果可以取得該鎖則返回YS。不能獲得時,與lock處理不同,線程沒有進入休眠狀態,而是直接返回NO并繼續執行。19.2.519.2.5條件鎖NSConditionLock稱為條件鎖(conditionlock)。該鎖持有整數值,根據該值可以獲得鎖或者(id initWithCondition (NSIntege c
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 工業廢水處理與環境友好型技術
- 工業廢水處理技術及設備質量控制
- 工業污染源的環境監測技術
- 工業機器人技術的發展與應用案例分享
- 工業機器人的維修技術及發展
- 工業綠色發展的技術路徑與政策支持
- 工業物聯網IIoT的崛起與影響
- 工業遺址改造中的環保理念與可持續發展
- 工業自動化技術的新進展與趨勢
- 工業設計在現代產業中的地位和作用
- 預制混凝土板防滲渠道施工工藝及質量控制
- 公路水運工程土工試驗講義二
- 大學《管理經濟學》期末復習核心知識點及考試真題解析
- 第五章-不規則三角網TIN的建立課件
- 《刑法》講座-課件
- 中級養老護理人員技能培訓
- 第二單元第1課時《線的認識》示范課教學課件【北師大版四年級數學上冊】
- 重慶市建設工程施工項目每日“防高墜三檢”檢查記錄表
- 國開電大本科《人文英語4》機考總題庫
- JJF 1059.1-2012測量不確定度評定與表示
- GB/T 6070-1995真空法蘭
評論
0/150
提交評論