偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

iPhone開發(fā)應用之Archiving NSCoder教程是本文要介紹的內容,一個面向對象程序在運行的時候,一般都創(chuàng)建了一個復雜的對象關系圖,經常需要把這樣一個復雜的對象關系圖表示成字節(jié)流.這樣的過程我們叫做Archiving 如圖10.1,

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

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

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

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

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

Objective-C語言有一個機制叫protocol, 就像java中的interface一樣. 一個protocol聲明了一系列方法.但你的類實現一個protocol,那么就預定了,你的類需要實現protocol中聲明的所有方法

NSCoder 和NSCoding

NSCoding是一個protocol. 如果你的類實現了NSCoding.那么就要實現這些方法

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

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

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

Encoding

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

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

這個方法把anObject對象寫入到coder中,并把它和aKey關聯起來[下次使用aKey從coder中可以再把anObject讀取出來] 這會是anObject的方法encodeWithCodr得到調用(還記得上面那個洗發(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"];  

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

Decoding

從coder中decoding數據,我們使用這些方法

  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 

如果因為某些原因, 字節(jié)流中沒有和aKey關聯的數據,那么我們會得到0值. 例如,對象沒有把key foo 關聯一個float數據寫入coder,那么在使用foo key來讀取這個float數據,coder會返回0.0 . 如果key foo關聯的是一個對象數據[使用方法encodeWithCoder 寫入],那么讀取時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;  

我們沒有調用父類的initWithCoder, 那是因為NSObject沒有實現它. 如過Person類的父類實現了NSCoding協議,那么這個方法應該這樣寫

  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工作然后在調用父類的 designated initializer, 也就是說類的其他initializer 方法都會調用designated initializer,Person類有designated initializer- init. 可以這個新加入的initializer方法并沒有調用init方法阿?" 不錯, 你是對的, initWithCoer: 是這個規(guī)則的一個特例.

好了.我們實現了NSCoding協議的方法.現在讓Person類實現NSCoding protocol. 我們來編輯Person.h文件.

  1. @interface Person : NSObject <NSCoding> { 

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

#p#

Document Architecture

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

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

將model 數據保存為一個文件

從一個文件中加載model數據

在view中顯示model數據

響應用戶通過view的輸入,并更新model

Info.plist 和 NSDocumentController

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

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

 

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

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

NSDocument

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

saving

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

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

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

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

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

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

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

來解釋下NSError.它的觀念是,因為某些原因,某個方法沒有辦法完成這個功能.那么它就會生成一個NSError對象,并把NSError對象的指針放到指定的位置. 例如,如果我希望從一個文件中讀取到一個NSData,那么我會提供一個地址,當出錯時,我可以從這個地址中得到錯誤信息
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類即會返回一個data對象,同時可能會創(chuàng)建一個error對象

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

Loading

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

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

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

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

從一個NSFileWrapper對象讀取model數據

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

#p#

從指定文件中讀取model數據

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

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

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

在我們的NSDocuemnt 子類中,實現這個方法刷新UI

NSWindowController

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

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

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

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

Saving 和 NSKeyedArchiver

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

為了生成一個NSData實例[encode了model數據] , 我們使用NSKeyedArchiver類. 它有這樣一個方法

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

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

再一次回到那個廣告"我告訴了兩朋友,他們也告訴了自己的朋友...."當你encode一個對象是, 這個對象會encode它自己連接的對象,那些對象也會encode它們連接的對象..等等. 這里我們要encode那個對象呢?就是array employees了. 它又會encode所有包含的Person對象. 而我們在Peron類中實現了encodeWithCoder:,所以每個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參數.將沒有error產生

  1. Loading和NSKeyedUnarchiver 

現在開始添加load文件功能, 再一次說明,NSDocument已經大部分細節(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為你完成了這個功能.我們不需要在windowControllerDidLoadNib:方法中多做什么. 我們在13章將會修改這個方法

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

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

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

因為我們激活了undo 機制,所以在編輯了document后, window會自動標注為編輯過.

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

#p#

設置后綴名和圖標

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

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

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

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

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

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

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

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

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

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

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

可以看到3個有趣的東西

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

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

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

#p#

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

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

當encode一個對象的時候,會將一個唯一標識同時放到流中.并建立一個表,一旦archive對象,就會把該對象和它的唯一標識聯系起來. 如果下次又要encode同一個對象,NSKeyedArchiver會先瀏覽這個表,看是否已經encode過,并只會把唯一標識放置到流中.

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

NSCoder有一個方法容易使讀者和上面的思想產生混淆

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

當對象A有一個指針指向對象B, 但是對象A不需要知道對象B是否被archive[是否存在]. 不過如果另外一個對象已經archive了B,對象A又希望將對象B的唯一標識在encode的時候能夠放置到流中.  [也就是說對象A不會主動encode B, 如果存在對象B ,那么就指向它,否則就指向空]

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

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

思考: 創(chuàng)建Protocol

創(chuàng)建自己的Protocol非常簡單.下面的Protocol有兩個方法,它可能在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 

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

如果你有一個類要實現Foo protocol和NSCoding protocol. 應該這樣做

  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]

在使用計算機時,一直有這樣一個問題:"數據是怎么樣展現出來的". 對于Mac, 這個問題在不同的幾個地方都會遇到:當從Finder打開一個文件時.當通過剪貼板拷貝數據時,當通過Spotlight索引文件時,當使用Quicklook預覽文件時.這個問題有一些答案: 文件擴展名, creator codes,和MIME類型

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

我們在Info.plist文件中定義程序可以讀寫的UTIs-包括新建的和自定義的UTIs. Info.plist文件是XML格式,包含了目錄以及key-value.  可以使用一個新key UTExporterTypeDeclarations來export新的UTIs. 例如,如果你想給RaiseMain Document添加一個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> 

當然,我們也通過properties inspector來使用UTI.如圖10.7

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

你可以在Apple的文檔中找到所有的系統定義的UTIs

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

責任編輯:zhaolei 來源: 新浪博客
相關推薦

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通訊錄聯系人

2011-08-15 13:44:07

iPhone開發(fā)UITableView

2011-08-10 15:48:10

iPhone網絡

2011-08-10 18:24:22

iPhone 圖形 繪圖

2011-07-08 16:02:24

iphone

2011-08-02 17:37:01

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

2011-08-08 10:10:14

iPhone開發(fā) 圖片 方法
點贊
收藏

51CTO技術棧公眾號