了解Objective-C 源文件組織
了解Objective-C 源文件組織是本文要介紹的內(nèi)容,不多說(shuō),我們直接進(jìn)入文章。最簡(jiǎn)單的Objective-C程序,你都可以這樣寫:
- #import <Foundation/Foundation.h>
- @interface Book : NSObject{
- }
- -(NSString *) getPrice;
- @end
- @implementation Book
- -(NSString *) getPrice{
- return @"$17";
- }
- @end
- int main (int argc, const char * argv[]) {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- Book *book=[[Book alloc] init];
- NSLog(@"Book price: %@",[book getPrice]);
- [pool drain];
- return 0;
- }
理論上講,按照上面的寫法,你可以把所有的代碼都寫在一個(gè)文件里。
但是問(wèn)題是,你不便于維護(hù)這個(gè)代碼。代碼很長(zhǎng),很亂。
所以,一般有以下幾種形式來(lái)拆分和組織代碼:
類文件拆分為頭文件和m文件
使用組的概念來(lái)管理文件
拆分接口和實(shí)現(xiàn)部分
拆分h文件和m文件很好理解。只要使用Xcode做開發(fā),通過(guò)向?qū)ы?yè)面創(chuàng)建類,文件默認(rèn)情況下就是強(qiáng)制分開的:
使用組的概念管理文件
使用組的概念。在Xcode下面,程序源文件都是放在Source目錄下的,在該目錄下,可以進(jìn)一步創(chuàng)建“目錄”,把不同用途的源文件分類放置。這樣就如同桌上凌亂的書歸置到書架里一樣。很好查找和查閱。
可以看到,下面是把Book相關(guān)的一些類放在book組中了。
這個(gè)組看起來(lái)是目錄,但如果你打開finder,查看目錄結(jié)構(gòu),發(fā)現(xiàn)并不存在這樣的目錄:
拆分文件帶來(lái)的問(wèn)題及解決辦法
拆分文件帶來(lái)很多好處。不只是自己看著方便了,還能方便多人合作開發(fā)。如果多人修改一個(gè)文件,很容易出現(xiàn)各種問(wèn)題。每個(gè)人負(fù)責(zé)自己的代碼文件,這些文件組成一個(gè)項(xiàng)目,這樣就不容易造成文件版本上的沖突。
但是,這也帶來(lái)了新的問(wèn)題。一個(gè)文件依賴另外一個(gè)文件的時(shí)候,需要通過(guò)import來(lái)導(dǎo)入。比如:
- #import <Foundation/Foundation.h>
- #import "CategoryDemo.h"
- #import "Book.h"
- #import "MusicBook.h"
- #import "PlayMusic.h"
- @class Author;
- int main (int argc, const char * argv[]) {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- NSString *message=@"你好,世界!";
- NSLog(@"%@, 長(zhǎng)度為: %i",message,[message length]);
- [message printHelloInfo];
- Book *book=[[Book alloc] init];
這里main方法中使用了Book類,那么,就需要通過(guò)import把它引進(jìn)來(lái),否則,編譯器不知道Book類在哪里。
另外,如果我這樣:
- #import <Foundation/Foundation.h>
- #import "CategoryDemo.h"
- //#import "Book.h"
- #import "MusicBook.h"
- #import "PlayMusic.h"
- @class Author;
- int main (int argc, const char * argv[]) {
注釋了對(duì)Book頭文件的導(dǎo)入,系統(tǒng)一樣編譯通過(guò),而且運(yùn)行正常。這是怎么回事兒呢?
這是因?yàn)榫幾g器很聰明。它發(fā)現(xiàn)MusicBook頭文件里面已經(jīng)導(dǎo)入了Book頭文件:
- #import <Cocoa/Cocoa.h>
- #import "Book.h"
- #import "PlayMusic.h"
- @interface MusicBook : Book <PlayMusic>{
在上面代碼中有一個(gè)奇怪的代碼:
- @class Author;
有了這句話,該代碼中的:
- book.author=[[Author alloc]init];
就不會(huì)報(bào)錯(cuò)了。
可以用下面的語(yǔ)句替代@class的代碼:
- #import "Author.h"
- //@class Author
;
系統(tǒng)一樣會(huì)很好的工作。那么,@class和#import有什么區(qū)別呢?
這里要說(shuō)一下頭文件依賴關(guān)系。如果有100個(gè)m文件都導(dǎo)入了某個(gè)頭文件,那么,當(dāng)這個(gè)頭文件改變了內(nèi)容,則編譯器會(huì)強(qiáng)制重新編譯這100個(gè)m文件的。編譯的速度可想而知。
@class就是為了避免這樣的事情發(fā)生的。當(dāng)編譯器看到比如類文件B是通過(guò)@class的方式引入一個(gè)類文件A,就不會(huì)在該類文件A的頭文件改動(dòng)后重新編譯B了。
那如果這樣,都用@class替代#import吧。問(wèn)題是,有些情況,只能使用#import。因?yàn)橛袝r(shí)候編譯器不只是需要知道類B引用到類A,還需要知道類A的內(nèi)部信息,而這些信息是類B需要的。比如類B繼承自類A,這時(shí)就不能用@class,而只能用#import。
小結(jié):關(guān)于了解Objective-C 源文件組織的內(nèi)容介紹完了,希望本文對(duì)你有所幫助!