成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

iPhone開發(fā)應(yīng)用之Archiving NSCoder教程

移動開發(fā) iOS
iPhone開發(fā)應(yīng)用中的Archiving NSCoder是本文要介紹的內(nèi)容,舉例我們創(chuàng)建保存一個(gè)nib文件,Interface Builder把對象寫入到nib文件就是這樣的arching過程,來看內(nèi)容。

iPhone開發(fā)應(yīng)用之Archiving NSCoder教程是本文要介紹的內(nèi)容,一個(gè)面向?qū)ο蟪绦蛟谶\(yùn)行的時(shí)候,一般都創(chuàng)建了一個(gè)復(fù)雜的對象關(guān)系圖,經(jīng)常需要把這樣一個(gè)復(fù)雜的對象關(guān)系圖表示成字節(jié)流.這樣的過程我們叫做Archiving 如圖10.1,

這個(gè)字節(jié)流可以在網(wǎng)絡(luò)中傳送,也可以寫入到文件中. 例如,我們創(chuàng)建保存一個(gè)nib文件,Interface Builder把對象寫入到nib文件就是這樣的arching過程(對于Java,這個(gè)過程叫serialization)。

iPhone開發(fā)應(yīng)用之Archiving NSCoder教程

而當(dāng)從字節(jié)流中重新恢復(fù)對象關(guān)系圖的過程叫做unarchive. 例如,當(dāng)程序啟動是,將會從nib文件中unarchive對象雖然對象包含成員變量和方法.但是只有成員變量和類名會被archive. 換句話說,data會被archive,而code不會. 所以,如果程序A archive對象,而程序B unarchive對象.那么程序A和B都要保證包含了class所連接的code. 舉個(gè)例子,在nib文件中,你使用到了Appkit framework 的NSWindow和NSButton對象.那么如果我們的程序沒有連接Appkit framework,那么我們就沒有辦法生成NSWindow和NSButton對象,因?yàn)閍rchive中只包含了data,而沒有code

有一個(gè)洗發(fā)水的廣告是這樣說得:"我告訴了我的兩個(gè)朋友,而他們各自又告訴了自己的兩個(gè)朋友,這樣一傳十,十傳百.."寓意就是,你告訴了你的朋友,最后所有的人都開始使用這個(gè)洗發(fā)水了. 對象archiving的工作方式和這差不多. 你archiving一個(gè)root對象. 它archiving自己相關(guān)聯(lián)的對象,那些相關(guān)聯(lián)的對象也會archiving自己相關(guān)聯(lián)的對象,依次類推,所有相關(guān)的對象都被archiving了

archiving由2步來完成. 1,我們需要告知我們的對象要怎么樣來archive. 2. 我們需要激發(fā)archiving動作發(fā)生

Objective-C語言有一個(gè)機(jī)制叫protocol, 就像java中的interface一樣. 一個(gè)protocol聲明了一系列方法.但你的類實(shí)現(xiàn)一個(gè)protocol,那么就預(yù)定了,你的類需要實(shí)現(xiàn)protocol中聲明的所有方法

NSCoder 和NSCoding

NSCoding是一個(gè)protocol. 如果你的類實(shí)現(xiàn)了NSCoding.那么就要實(shí)現(xiàn)這些方法

  1. - (id)initWithCoder:(NSCoder *)coder;  
  2. - (void)encodeWithCoder:(NSCoder *)coder; 

NSCoder是archivie 字節(jié)流的抽象類.我們可以實(shí)現(xiàn)把數(shù)據(jù)寫入一個(gè)coder,也可以從coder中讀取我們寫入的數(shù)據(jù). 我們對象的方法initWithCoder:就是從一個(gè)coder從讀取數(shù)據(jù),然后把數(shù)據(jù)賦給成員變量. 方法encodeWithCoder: 則是把成員變量的值寫入到coder中. 在這一章中,我們會在Person類中實(shí)現(xiàn)這兩個(gè)方法

NSCoder是一個(gè)抽象類,我們不會直接使用它來創(chuàng)建對象. 相反,我們會使用從它繼承來的子類. 也就是我們使用 NSKeyedUnarchiver類來從字節(jié)流中讀取數(shù)據(jù),而使用NSKeyedArchiver類來把對象寫入到字節(jié)流

Encoding

NSCoder包含了很多方法, 不過大部分人會發(fā)現(xiàn)只會使用到其中很少的一部分. 下面是當(dāng)要archivie數(shù)據(jù)時(shí)用到的一些常用方法

  1. - (void)encodeObject:(id)anObject forKey:(NSString *)aKey 

這個(gè)方法把a(bǔ)nObject對象寫入到coder中,并把它和aKey關(guān)聯(lián)起來[下次使用aKey從coder中可以再把a(bǔ)nObject讀取出來] 這會是anObject的方法encodeWithCodr得到調(diào)用(還記得上面那個(gè)洗發(fā)水廣告把.就是這樣傳下去的)

對于C的基本類型(如int float).NSCoder使用下面方法

  1. - (void)encodeBool:(BOOL)boolv forKey:(NSString *)key  
  2. - (void)encodeDouble:(double)realv forKey:(NSString *)key  
  3. - (void)encodeFloat:(float)realv forKey:(NSString *)key  
  4. - (void)encodeInt:(int)intv forKey:(NSString *)key 

添加encoing方法到Person類中.

  1. - (void)encodeWithCoder:(NSCoder *)coder  
  2. {  
  3.     [super encodeWithCoder:coder];  
  4.     [coder encodeObject:personName forKey:@"personName"];  
  5.     [coder encodeFloat:expectedRaise forKey:@"expectedRaise"];  

這里調(diào)用了父類的encodeWithCoder,使得父類有機(jī)會把自己的變量寫入到coder中. 因此,類繼承樹中的類只會把自己的成員變量寫入到coder-不會包含父類的成員變量

Decoding

從coder中decoding數(shù)據(jù),我們使用這些方法

  1. - (id)decodeObjectForKey:(NSString *)aKey  
  2. - (BOOL)decodeBoolForKey:(NSString *)key  
  3. - (double)decodeDoubleForKey:(NSString *)key  
  4. - (float)decodeFloatForKey:(NSString *)key  
  5. - (int)decodeIntForKey:(NSString *)key 

如果因?yàn)槟承┰? 字節(jié)流中沒有和aKey關(guān)聯(lián)的數(shù)據(jù),那么我們會得到0值. 例如,對象沒有把key foo 關(guān)聯(lián)一個(gè)float數(shù)據(jù)寫入coder,那么在使用foo key來讀取這個(gè)float數(shù)據(jù),coder會返回0.0 . 如果key foo關(guān)聯(lián)的是一個(gè)對象數(shù)據(jù)[使用方法encodeWithCoder 寫入],那么讀取時(shí)coder返回nil

添加decoding到Person類中

  1. - (id)initWithCoder:(NSCoder *)coder  
  2. {  
  3.    [super init];  
  4.    personName = [[coder decodeObjectForKey:@"personName"] retain];  
  5.    expectedRaise = [coder decodeFloatForKey:@"expectedRaise"];  
  6.    return self;  

我們沒有調(diào)用父類的initWithCoder, 那是因?yàn)镹SObject沒有實(shí)現(xiàn)它. 如過Person類的父類實(shí)現(xiàn)了NSCoding協(xié)議,那么這個(gè)方法應(yīng)該這樣寫

  1. - (id)initWithCoder:(NSCoder *)coder  
  2. {  
  3.   [super initWithCoder:coder];  
  4.   personName = [[coder decodeObjectForKey:@"personName"] retain];  
  5.   expectedRaise = [coder decodeFloatForKey:@"expectedRaise"];  
  6.   return self;  

你可以會說"在第3章中, designated initializer會完成所有的init工作然后在調(diào)用父類的 designated initializer, 也就是說類的其他initializer 方法都會調(diào)用designated initializer,Person類有designated initializer- init. 可以這個(gè)新加入的initializer方法并沒有調(diào)用init方法阿?" 不錯(cuò), 你是對的, initWithCoer: 是這個(gè)規(guī)則的一個(gè)特例.

好了.我們實(shí)現(xiàn)了NSCoding協(xié)議的方法.現(xiàn)在讓Person類實(shí)現(xiàn)NSCoding protocol. 我們來編輯Person.h文件.

  1. @interface Person : NSObject <NSCoding> { 

現(xiàn)在編譯我們的工程. 你也可以運(yùn)行程序看看.雖然Person類可以encode自己了.不過我們沒有地方讓它這么做.所以程序看上去沒什么變化.

#p#

Document Architecture

多文檔程序有很多的共同性. 比如都可以創(chuàng)建新的document, 打開document,保存或打印打開的document, 當(dāng)關(guān)閉document窗口或退出程序時(shí)提醒用戶保存編輯好得document. Apple提供3個(gè)類- NSDocumentController,NSDocument,NSWindowController-來完成這些工作. 它們一起組成了document architecture

創(chuàng)建document architecture的意圖是和我們第8章討論的Model-View-Controller設(shè)計(jì)模式相關(guān)的. 在RaiseMan工程中. 我們的NSDocument子類-使用了NSArrayController類-就是其中的Controller. 它包含了指向model對象的指針. 負(fù)責(zé)下面所列的職責(zé) [這里的model 數(shù)據(jù)就是值employyess-person 對象]

將model 數(shù)據(jù)保存為一個(gè)文件

從一個(gè)文件中加載model數(shù)據(jù)

在view中顯示model數(shù)據(jù)

響應(yīng)用戶通過view的輸入,并更新model

Info.plist 和 NSDocumentController

XCode在編譯創(chuàng)建一個(gè)程序時(shí)會使用到一個(gè)文件 Info.plist(本章后面,我們會修改這個(gè)文件). 當(dāng)程序啟動時(shí),它會讀取Info.plisst的信息. 告知工作的文件類型是什么. 如果它發(fā)現(xiàn)是一個(gè)document-base 程序. 那么會創(chuàng)建一個(gè)NSDocumentController對象(圖10.2). 我們很少去直接使用這個(gè)document controller. NSDocumentController對象在后面會為我們做一些工作.例如,當(dāng)選擇New 或是 Save All菜單時(shí), document controller會處理這些請求. 如果你有給document controller發(fā)送消息,你可以這樣做

  1. NSDocumentController *dc;  
  2. dc = [NSDocumentController sharedDocumentController]; 

 

iPhone開發(fā)應(yīng)用之Archiving NSCoder教程

document controller保存了一個(gè)document 對象的array - 每一個(gè)document對象就是一個(gè)打開的document.

NSDocument

document對象是NSDocument子類的一個(gè)實(shí)例. 在我們的RaiseMan程序中,它就是MyDocument的實(shí)例. 對于大部分程序,一般我們只有簡單的擴(kuò)展NSDocument來完成想要的功能而不需要過多關(guān)系NSDocumentcontroller或是NSWindowController

saving

菜單項(xiàng)Save,Save As...,Save All,和Close雖然不相同.但是它們都面向同一個(gè)問題:把mdoel保存為一個(gè)文件或是文件包(文件包是一個(gè)文件目錄,不過對于用戶就象是一個(gè)文件一樣). 對于這些菜單項(xiàng). 我們的NSDocument子類需要實(shí)現(xiàn)下面3個(gè)方法中的一個(gè)

  1. - (NSData *)dataOfType:(NSString *)aType  
  2.                  error:(NSError *)e 

你的document對象將model生成一個(gè)NSData寫入文件.[這個(gè)方法中,我們只有把model壓成一個(gè)NSData返回,然后Cocoa會把NSData在寫入文件了] NSData就是字節(jié)buffer. 是簡單也是通用的實(shí)現(xiàn)saving的方法.如果不能生成一個(gè)NSData 對象,那么就返回nil,而用戶會得到一個(gè)alert提示save失敗. 注意到參數(shù)aType, 它可以容許你將document保存為一個(gè)或多個(gè)類型格式. 例如,你編寫了一個(gè)圖像程序,你可能容許用戶將圖像保存為gif或是jpg格式.所以當(dāng)你生成data對象時(shí), aType就指定了用戶請求保存的格式.如果你的程序只處理單一類型,那么可以忽略aType. 為了說明你不能保存,可以返回nil并創(chuàng)建一個(gè)NSError對象來說明出來什么樣得錯(cuò)誤

  1. - (NSFileWrapper *)fileWrapperOfType:(NSString *)aType  
  2.                                error:(NSError *)e 

你的document對象生成一個(gè)文件包返回. 文件包將被創(chuàng)建在用戶指定的位置

  1. - (BOOL)writeToURL:(NSURL *)absoluteURL  
  2.             ofType:(NSString *)typeName  
  3.              error:(NSError **)outError; 

你的docuemnt對象以指定的type把model數(shù)據(jù)保存在指定的URL(URL就是文件系統(tǒng)上的文件路徑)[這個(gè)方法應(yīng)該在NSDocument類中實(shí)現(xiàn)了,里面估計(jì)就是調(diào)用了dataOfType:error: . 得到NSData后將其寫入指定URL. 當(dāng)然你也可以從中這個(gè)方法] 如果能夠保存成功返回YES,否則返回NO. 如果返回NO,那么你你應(yīng)該生成一個(gè)NSError對象來描述錯(cuò)誤是什么

來解釋下NSError.它的觀念是,因?yàn)槟承┰?某個(gè)方法沒有辦法完成這個(gè)功能.那么它就會生成一個(gè)NSError對象,并把NSError對象的指針放到指定的位置. 例如,如果我希望從一個(gè)文件中讀取到一個(gè)NSData,那么我會提供一個(gè)地址,當(dāng)出錯(cuò)時(shí),我可以從這個(gè)地址中得到錯(cuò)誤信息
NSError *e;

  1. NSData *d = [NSData dataWithContentsOfFile:@"/tmp/x.txt"  
  2.                                    options:0  
  3.                                      error:&error];  
  4. // Did the read fail?  
  5. if (d == nil) {  
  6.       NSLog(@"Read failed: %@", [error localizedDescription];  

所以NSData類即會返回一個(gè)data對象,同時(shí)可能會創(chuàng)建一個(gè)error對象

在save和load方法中,我們將有負(fù)責(zé)在失敗的時(shí)候創(chuàng)建NSError對象

Loading

Open...,Open Recent,和Revert To Saved 菜單項(xiàng)也是一樣,它們都面向同一個(gè)問題:從一個(gè)文件或是文件包中得到model. 為了響應(yīng)它們,NSDocuement子類需要實(shí)現(xiàn)下面3個(gè)方法中的一個(gè)

  1. - (BOOL)readFromData:(NSData *)data  
  2.               ofType:(NSString *)typeName  
  3.                error:(NSError **)outError 

包含了用戶要打開的文件內(nèi)容的NSData對象被傳進(jìn)來. 如果能夠從這個(gè)NSData對象中生成model那么就返回YES. 如果返回NO,那么用戶會得到一個(gè)Alert提示為什么個(gè)不能成功打開文件. Alert的內(nèi)容由這個(gè)方法生成的NSError對象來指定

  1. - (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper  
  2.                      ofType:(NSString *)typeName  
  3.                       error:(NSError **)outError; 

從一個(gè)NSFileWrapper對象讀取model數(shù)據(jù)

  1. - (BOOL)readFromURL:(NSURL *)absoluteURL  
  2.              ofType:(NSString *)typeName  
  3.               error:(NSError **)outError; 

#p#

從指定文件中讀取model數(shù)據(jù)

在實(shí)現(xiàn)了一個(gè)save和一個(gè)load方法后,我們的程序就知道怎么樣讀寫文件了.在打開一個(gè)文件時(shí), document對象會在讀取nib文件前讀取document文件[你需要讀取nib文件來顯示一個(gè)document阿] . 這樣的結(jié)果是,我們不能在loading一個(gè)document文件后馬上去給用戶界面發(fā)送消息(它們還不存在)[注意load nib文件是document 架構(gòu)為我們做的,這里說的立馬調(diào)用是指在 load方法中-這個(gè)是我們在NSDocument子類中實(shí)現(xiàn)的調(diào)用-給UI發(fā)送消息]. [那如果我們想要馬上給UI發(fā)送消息怎么辦?]-為了解決這個(gè)問題,我們可以實(shí)現(xiàn)一個(gè)方法-它會在nib文件被調(diào)用UI創(chuàng)建好了后發(fā)送

  1. - (void)windowControllerDidLoadNib:(NSWindowController *)x; 

[想想 當(dāng)點(diǎn)擊Open菜單,代碼執(zhí)行的過程是怎么樣 - 有些代碼是cocoa里面實(shí)現(xiàn)的,有些是我們自己實(shí)現(xiàn)的]

在我們的NSDocuemnt 子類中,實(shí)現(xiàn)這個(gè)方法刷新UI

NSWindowController

在document architecture中最后要介紹的一個(gè)類是NSWindowcontroller .每打開一個(gè)Document都會產(chǎn)生一個(gè)窗口-生成一個(gè)NSWindowController實(shí)例. 對于大部分程序,每一個(gè)document對于一個(gè)window, window controller的默認(rèn)實(shí)現(xiàn)已經(jīng)夠用了.所以一般我們只有在下面幾種情況下才會生成一個(gè)NSWindowController的子類

對于同一個(gè)document,需要使用多個(gè)window. 例如,CAD程序, 你可能需要一個(gè)text窗口來描述一個(gè)立體,而另外一個(gè)窗口來顯示這個(gè)立體

你需要把UI controller 和 model controller 放到不同的類中

你需要創(chuàng)建不和NSDocument 對象對應(yīng)的窗口.我們會在12章來做這樣的事

Saving 和 NSKeyedArchiver

現(xiàn)在我們知道了怎樣encode和decode我們自己的類,現(xiàn)在開始給我們的程序添加saving和loading功能了. 當(dāng)我們要保存person到一個(gè)文件,MyDocument類會被請求生成一個(gè)NSData實(shí)例. 一旦創(chuàng)建了NSData實(shí)例并返回,它會自動保存到文件中

為了生成一個(gè)NSData實(shí)例[encode了model數(shù)據(jù)] , 我們使用NSKeyedArchiver類. 它有這樣一個(gè)方法

  1. + (NSData *)archivedDataWithRootObject:(id)rootObject 

這個(gè)方法將對象archive成NSData對象的字節(jié)buffer [字節(jié)buffe-看看NSData的說明吧]

再一次回到那個(gè)廣告"我告訴了兩朋友,他們也告訴了自己的朋友...."當(dāng)你encode一個(gè)對象是, 這個(gè)對象會encode它自己連接的對象,那些對象也會encode它們連接的對象..等等. 這里我們要encode那個(gè)對象呢?就是array employees了. 它又會encode所有包含的Person對象. 而我們在Peron類中實(shí)現(xiàn)了encodeWithCoder:,所以每個(gè)Perosn對象開始encode自己了-encode personName字串和expectedRaise float

編輯方法dataOfType:error:. 添加saving功能

  1. - (NSData *)dataOfType:(NSString *)aType  
  2.                  error:(NSError **)outError  
  3. {  
  4.     // End editing  
  5.     [[tableView window] endEditingFor:nil];  
  6.  
  7.     // Create an NSData object from the employees array  
  8.     return [NSKeyedArchiver archivedDataWithRootObject:employees];  

這里我們忽略了error參數(shù).將沒有error產(chǎn)生

  1. Loading和NSKeyedUnarchiver 

現(xiàn)在開始添加load文件功能, 再一次說明,NSDocument已經(jīng)大部分細(xì)節(jié)

我們會使用到NSKeyedUnarchiver類方法

  1. + (id)unarchiveObjectWithData:(NSData *)data 

編輯MyDocument類的readFromData:ofType:error:方法

  1.               ofType:(NSString *)typeName  
  2.                error:(NSError **)outError  
  3. {  
  4.    NSLog(@"About to read data of type %@", typeName);  
  5.    NSMutableArray *newArray = nil;  
  6.    @try {  
  7.       newArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];  
  8.    }  
  9.    @catch (NSException *e) {  
  10.       if (outError) {  
  11.          NSDictionary *d = [NSDictionary  
  12.               dictionaryWithObject:@"The data is corrupted."  
  13.                             forKey:NSLocalizedFailureReasonErrorKey];  
  14.          *outError = [NSError errorWithDomain:NSOSStatusErrorDomain  
  15.                                          code:unimpErr  
  16.                                      userInfo:d];  
  17.       }  
  18.       return NO;  
  19. }  
  20.    [self setEmployees:newArray];  
  21.    return YES;  

在nib文件加載后,你需要刷新UI.不過NSArrayController為你完成了這個(gè)功能.我們不需要在windowControllerDidLoadNib:方法中多做什么. 我們在13章將會修改這個(gè)方法

  1. - (void)windowControllerDidLoadNib:(NSWindowController *)aController  
  2. {  
  3.     [super windowControllerDidLoadNib:aController];  

注意,在打開或創(chuàng)建一個(gè)document時(shí),會詢問我們的document類:需要load那個(gè)nib文件.現(xiàn)在我們也不需要修改這個(gè)方法

  1. - (NSString *)windowNibName  
  2. {  
  3.     return @"MyDocument";  

因?yàn)槲覀兗せ盍藆ndo 機(jī)制,所以在編輯了document后, window會自動標(biāo)注為編輯過.

現(xiàn)在,我們的程序能夠讀寫文件了.編譯運(yùn)行程序,試試看吧,看上去都能工作正常. 不過我們保存的文件的后綴名為.???? ,我們需要在Info.plist中給它定義一個(gè)后綴名

#p#

設(shè)置后綴名和圖標(biāo)

我們將為RaiseMan 文件添加后綴.rsmn 和一個(gè)圖標(biāo). 首先找到一個(gè).icns文件并拷貝到我們的工程中. 就使用

  1. /Developer/Examples/Appkit/CompositeLab/BBall.icns 

吧.把他從Finder中拖到XCode的Resources組中.如圖10.3

iPhone開發(fā)應(yīng)用之Archiving NSCoder教程

XCode會彈出一個(gè)頁面,確保勾選Copy items into destination group's folder 如圖10.4.這樣將會包icon文件拷貝到我們的工程目錄中

iPhone開發(fā)應(yīng)用之Archiving NSCoder教程

在XCode中選定RaiseMan Target, 從File菜單中選擇Get Info, 來設(shè)置document-type屬性. 在Properties頁中,設(shè)置identifier為com.bignerdranch.RaiseMan. 設(shè)置Icon file 為BBall. 在document-types中,設(shè)置name為RaiseMan Doc. Extensions為rsmn. icon file為BBall.參考圖10.5

iPhone開發(fā)應(yīng)用之Archiving NSCoder教程

編譯運(yùn)行程序.我們再次試試保存和打開功能. 在Finder中, 我們的.rsmn文件的圖標(biāo)變成了BBall.icns

一個(gè)程序其實(shí)是一個(gè)目錄. 包含了程序用到的nib 文件, 圖像,聲音和可執(zhí)行代碼. 在Terminal,試試輸入

  1. cd /Applications/TextEdit.app/Contents  
  2. ls 

可以看到3個(gè)有趣的東西

Info.plist文件. 包含了該程序的信息, 文件類型和相關(guān)的圖標(biāo). Finder會使用這些信息

MacOS/目錄. 這里包含了可執(zhí)行代碼

Resources/目錄. 這里包含了程序用到的圖像,聲音和nib文件,你還可以看到不同語言的本地化資源

#p#

思考:避免死循環(huán)

聰明的讀者可能會懷疑:""如果對象A使對象B進(jìn)行encode,對象B使對象C進(jìn)行encode,而對象C又使得對象A進(jìn)行encode. 這樣不是會產(chǎn)生無窮循環(huán)嗎?"" 沒錯(cuò),確實(shí)會發(fā)生這種情況,好在NSKeyedArchiver類設(shè)計(jì)好了避免這種情況發(fā)送.

當(dāng)encode一個(gè)對象的時(shí)候,會將一個(gè)唯一標(biāo)識同時(shí)放到流中.并建立一個(gè)表,一旦archive對象,就會把該對象和它的唯一標(biāo)識聯(lián)系起來. 如果下次又要encode同一個(gè)對象,NSKeyedArchiver會先瀏覽這個(gè)表,看是否已經(jīng)encode過,并只會把唯一標(biāo)識放置到流中.

當(dāng)從流中decode出對象時(shí), NSKeyedUnarchiver同樣會生成一個(gè)表,把encode對象和唯一標(biāo)識關(guān)聯(lián)起來.如果發(fā)現(xiàn)流中只有唯一標(biāo)識[說明之前有encode這個(gè)對象],unarchiver就會在表中來查找這個(gè)對象,而不是再生成一個(gè)新的對象.

NSCoder有一個(gè)方法容易使讀者和上面的思想產(chǎn)生混淆

  1. - (void)encodeConditionalObject:(id)anObject forKey:(NSString *)aKey 

當(dāng)對象A有一個(gè)指針指向?qū)ο驜, 但是對象A不需要知道對象B是否被archive[是否存在]. 不過如果另外一個(gè)對象已經(jīng)archive了B,對象A又希望將對象B的唯一標(biāo)識在encode的時(shí)候能夠放置到流中.  [也就是說對象A不會主動encode B, 如果存在對象B ,那么就指向它,否則就指向空]

舉個(gè)例子,我們需要給Engine對象編寫它的encodeWithCoder:方法. 它有一個(gè)成員變量為car,是一個(gè)指向Car對象的指針(發(fā)動機(jī)是汽車的一部分). 我們在archiving Engine對象時(shí),不希望整個(gè)Car對象被archived. 不過如果該Car對象之前在其他地方archived過, 我們又希望 Engine對象的car指針指向它. 在這種情況下,我們就要要求Engine對象有條件的來encode car指針指向的對象了. 如圖10.6

iPhone開發(fā)應(yīng)用之Archiving NSCoder教程

思考: 創(chuàng)建Protocol

創(chuàng)建自己的Protocol非常簡單.下面的Protocol有兩個(gè)方法,它可能在Foo.h文件中

  1. @protocol Foo  
  2. - (void)fido:(int)x;  
  3. - (float)rex;  
  4. @end 

Objective-C 2.0中,新增了語法@optional. 可以用來指定那些方法是必須那些方法是可選的

  1. @protocol Foo  
  2. - (void)fido:(int)x;  
  3. - (float)rex;  
  4. @optional  
  5. - (int)rover;  
  6. - (void)spot:(int)x;  
  7. @end 

在這個(gè)例子中fido: 和rex方法是必須的,而rover和spot:方法是可選的

如果你有一個(gè)類要實(shí)現(xiàn)Foo protocol和NSCoding protocol. 應(yīng)該這樣做

  1. #import "Spunky.h"  
  2. #import "Foo.h"  
  3.  
  4. @interface ZsaZsa:Spunky <Foo, NSCoding> 
  5. ...etc...  
  6. @end 

我們不需要重新聲明父類和protocol中聲明過的方法.所以,在本例中, ZsaZsa類接口文件中不需要再次聲明Spunky和Foo,NSCoding中聲明過的方法

通用類型描述[UTI]

在使用計(jì)算機(jī)時(shí),一直有這樣一個(gè)問題:"數(shù)據(jù)是怎么樣展現(xiàn)出來的". 對于Mac, 這個(gè)問題在不同的幾個(gè)地方都會遇到:當(dāng)從Finder打開一個(gè)文件時(shí).當(dāng)通過剪貼板拷貝數(shù)據(jù)時(shí),當(dāng)通過Spotlight索引文件時(shí),當(dāng)使用Quicklook預(yù)覽文件時(shí).這個(gè)問題有一些答案: 文件擴(kuò)展名, creator codes,和MIME類型

Apple選擇的長期解決途徑是通用類型描述(UTIs). 一個(gè)UTI是一個(gè)描述了文件類型的字符串. UTIs按一定層次關(guān)系組織.

我們在Info.plist文件中定義程序可以讀寫的UTIs-包括新建的和自定義的UTIs. Info.plist文件是XML格式,包含了目錄以及key-value.  可以使用一個(gè)新key UTExporterTypeDeclarations來export新的UTIs. 例如,如果你想給RaiseMain Document添加一個(gè)UTI. 可以在Info.plist文件中添加如下描述:

  1. <array> 
  2.     <dict> 
  3.         <key>UTTypeIdentifier</key> 
  4.         <string>com.bignerdranch.raiseman-doc</string> 
  5.         <key>UTTypeDescription</key> 
  6.         <string>RaiseMan Document</string> 
  7.         <key>UTTypeConformsTo</key> 
  8.         <array> 
  9.               <string>public.data</string> 
  10.         </array> 
  11.         <key>UTTypeTagSpecification</key> 
  12.  
  13.         <dict> 
  14.               <key>com.apple.ostype</key> 
  15.               <string>rsmn</string> 
  16.               <key>public.filename-extension</key> 
  17.               <array> 
  18.                    <string>rsmn</string> 
  19.               </array> 
  20.         </dict> 
  21.      </dict> 
  22. </array> 

當(dāng)然,我們也通過properties inspector來使用UTI.如圖10.7

iPhone開發(fā)應(yīng)用之Archiving NSCoder教程

你可以在Apple的文檔中找到所有的系統(tǒng)定義的UTIs

小結(jié):iPhone開發(fā)應(yīng)用之Archiving NSCoder教程的內(nèi)容介紹完了,希望本文對你有所幫助!

責(zé)任編輯:zhaolei 來源: 新浪博客
相關(guān)推薦

2011-08-11 10:16:23

iPhoneUIView視圖

2011-08-11 10:27:37

iPhoneUIView視圖

2011-08-16 19:02:23

iPhone開發(fā)繪圖

2011-08-15 18:02:32

iPhone開發(fā)表視圖

2011-08-10 15:36:26

iPhone靜態(tài)庫控件

2011-07-08 14:58:16

iPhone Xcode iOS

2011-08-11 11:51:07

iPhone鍵盤

2011-08-12 11:31:46

iPhoneUIView動畫

2011-08-15 10:15:00

iPhone開發(fā)警告框

2011-08-09 13:10:32

iPhone地圖開發(fā)

2011-08-19 14:27:29

iPhone開發(fā)

2011-08-08 18:19:09

iPhone音頻播放

2011-08-11 17:32:51

iPhone視圖

2011-08-12 10:16:10

iPhone通訊錄聯(lián)系人

2011-08-15 13:44:07

iPhone開發(fā)UITableView

2011-08-10 15:48:10

iPhone網(wǎng)絡(luò)

2011-08-02 17:37:01

IPhone開發(fā) 環(huán)境搭建

2011-08-10 18:24:22

iPhone 圖形 繪圖

2011-07-08 16:02:24

iphone

2011-07-19 09:46:38

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 成年人在线视频 | 狠狠躁天天躁夜夜躁婷婷老牛影视 | 婷婷激情综合 | 激情五月激情综合网 | 欧美一级毛片久久99精品蜜桃 | 中文字幕日韩欧美一区二区三区 | 日本成人毛片 | 久久久免费在线观看 | 欧美日韩精品久久久免费观看 | 国产aⅴ爽av久久久久久久 | 亚洲欧美日韩在线不卡 | 欧美成人精品一区二区三区 | 中文字幕1区 | 欧美精品一区二区免费 | 国产午夜在线 | 欧美成人精品 | 91免费观看国产 | 国产成人精品一区二 | 国产第一区二区 | 免费黄色特级片 | 免费一区| 欧美久久视频 | 午夜一区二区三区在线观看 | 在线欧美一区 | 99久久精品国产毛片 | 在线观看国产精品视频 | 日韩欧美第一页 | 成人免费视频在线观看 | 久草成人网 | 国产精品一区二区无线 | 欧美男人天堂 | 伊人超碰 | 国外成人免费视频 | 中文字幕 在线观看 | 国产精品视频久久 | 黄网站在线播放 | 亚洲 欧美 另类 日韩 | 久久免费国产视频 | 亚洲一区二区精品视频 | 久久久久国产一区二区三区 | 国产精品视频一二三区 |