了解Objective-C 源文件組織
了解Objective-C 源文件組織是本文要介紹的內容,不多說,我們直接進入文章。最簡單的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;
- }
理論上講,按照上面的寫法,你可以把所有的代碼都寫在一個文件里。
但是問題是,你不便于維護這個代碼。代碼很長,很亂。
所以,一般有以下幾種形式來拆分和組織代碼:
類文件拆分為頭文件和m文件
使用組的概念來管理文件
拆分接口和實現部分
拆分h文件和m文件很好理解。只要使用Xcode做開發,通過向導頁面創建類,文件默認情況下就是強制分開的:
使用組的概念管理文件
使用組的概念。在Xcode下面,程序源文件都是放在Source目錄下的,在該目錄下,可以進一步創建“目錄”,把不同用途的源文件分類放置。這樣就如同桌上凌亂的書歸置到書架里一樣。很好查找和查閱。
可以看到,下面是把Book相關的一些類放在book組中了。
這個組看起來是目錄,但如果你打開finder,查看目錄結構,發現并不存在這樣的目錄:
拆分文件帶來的問題及解決辦法
拆分文件帶來很多好處。不只是自己看著方便了,還能方便多人合作開發。如果多人修改一個文件,很容易出現各種問題。每個人負責自己的代碼文件,這些文件組成一個項目,這樣就不容易造成文件版本上的沖突。
但是,這也帶來了新的問題。一個文件依賴另外一個文件的時候,需要通過import來導入。比如:
- #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(@"%@, 長度為: %i",message,[message length]);
- [message printHelloInfo];
- Book *book=[[Book alloc] init];
這里main方法中使用了Book類,那么,就需要通過import把它引進來,否則,編譯器不知道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[]) {
注釋了對Book頭文件的導入,系統一樣編譯通過,而且運行正常。這是怎么回事兒呢?
這是因為編譯器很聰明。它發現MusicBook頭文件里面已經導入了Book頭文件:
- #import <Cocoa/Cocoa.h>
- #import "Book.h"
- #import "PlayMusic.h"
- @interface MusicBook : Book <PlayMusic>{
在上面代碼中有一個奇怪的代碼:
- @class Author;
有了這句話,該代碼中的:
- book.author=[[Author alloc]init];
就不會報錯了。
可以用下面的語句替代@class的代碼:
- #import "Author.h"
- //@class Author
;
系統一樣會很好的工作。那么,@class和#import有什么區別呢?
這里要說一下頭文件依賴關系。如果有100個m文件都導入了某個頭文件,那么,當這個頭文件改變了內容,則編譯器會強制重新編譯這100個m文件的。編譯的速度可想而知。
@class就是為了避免這樣的事情發生的。當編譯器看到比如類文件B是通過@class的方式引入一個類文件A,就不會在該類文件A的頭文件改動后重新編譯B了。
那如果這樣,都用@class替代#import吧。問題是,有些情況,只能使用#import。因為有時候編譯器不只是需要知道類B引用到類A,還需要知道類A的內部信息,而這些信息是類B需要的。比如類B繼承自類A,這時就不能用@class,而只能用#import。
小結:關于了解Objective-C 源文件組織的內容介紹完了,希望本文對你有所幫助!