深入了解iPhone靜态庫(手把手教你iphone開發 - 基礎篇)
在實際的程式設計過程中,通常會把一些公用函數制成函數庫,供其它程式使用,一則提搞了代碼的複用;二則提搞了核心技術的保密程度。是以在實際的項目開發中,經常會使用到函數庫,函數庫分為靜态庫和動态庫兩種。和多數人所熟悉的動态語言和靜态語言一樣,這裡的所謂靜态和動态是相對編譯期和運作期的:靜态庫在程式編譯時會被連結到目标代碼中,程式運作時将不再需要改靜态庫;而動态庫在程式編譯時并不會被連結到目标代碼中,隻是在程式運作時才被載入,因為在程式運作期間還需要動态庫的存在。
iPhone官方隻支援靜态庫聯編,本文就以靜态庫為例講解iPhone中靜态庫的具體用法。在實際的開發過程中,可能在項目設計階段把一些功能比如圖形界面引擎、網絡通訊引擎等都規劃到相應的函數庫中。
打開XCode建立一個項目,選擇Library下的“Cocoa Touch Static Library”并命名為“FirstLibrary”。這個建立的靜态庫項目下除了“FisrtLibrary_Prefix.pch”外沒有任何程式檔案,在Classes檔案夾上點右鍵選擇“New File…”,然後在“Cocoa Touch Class”下選擇“Objective-C class”,筆者在這裡先建立Objective-C風格的源檔案和頭檔案并命名為“function”,可以看到在Classes目錄下産生了function.h和function.m檔案。接着在頭檔案裡輸入以下内容:
#import <Foundation/Foundation.h>
@interface function : NSObject {
}
- (int)getMax:(int)a b:(int)b;
- (int)getMin:(int)a b:(int)b;
@end
實作檔案function.m内容如下:
#import "function.h"
@implementation function
- (int)getMax:(int)a b:(int)b
{
return a > a?a:b;
- (int)getMin:(int)a b:(int)b
return a < b?a:b;
可見,筆者的這個靜态函數庫的功能很簡單,就是提供了兩個擷取最大值和最小值的函數。但是可能大多數現存的函數庫的源碼都是C或者C++格式的,沒關系,iPhone對C/C++支援的也很好。在Classes檔案夾上點右鍵,選擇“New File…”,這次選擇Mac OS X下的“C and C++”,之後選擇“C File”并命名為“TestCFunction”,可以看到在Classes目錄下産生了兩個檔案“TestCFunction.h”和“TestCFunction.c”,TestCFunction.h如下:
#ifndef TestCFunction_H_
#define TestCFunction_H_
void swapValue(int* a,int* b)
int temp = 0;
temp = *a;
*a = *b;
*b = temp;
#endif
TestCFunction.c檔案内保持為原樣。
至此,這個靜态函數庫已經編寫完畢,盡管很簡單,但是包含了Objective-C風格和C風格的源代碼檔案在内,編譯這個程式會看到在Products目錄下産生了名為“libFirstLibrary.a”的靜态庫檔案。
建立一個“Window-based Application”項目并命名為“FirstLibraryTest”,下面筆者會示範如何在這個新項目裡利用前面生成的靜态庫libFristLibrary.a檔案。
¨ 首先,拖拉靜态庫裡的“FirstLibrary.xcodeproj”檔案到新項目的Frameworks目錄下(當然也可以通過右鍵點Frameworks->Add->Existing Files..添加),如下圖:
然後選擇“FristLibrary.xcodeproj”檔案,選擇右邊編輯視窗中的最後一項,這樣就将靜态庫添加到項目中了,如下圖:
在将靜态庫添加到項目中後,需要在項目和靜态庫之間建立“Direct Dependencies(所謂的依賴關系)”。在“Targets”目錄下選擇“FirstLibraryTest”,然後快捷鍵Cmd+i(或者右鍵選擇Get Info)可以看到項目的依賴資訊,如下圖:
點選“Direct Dependencies”下方的“+”按鈕,會出現下圖:
選擇“FirstLibrary”并點選“Add Target”,這樣就建立了項目和靜态庫之間的“依賴關系”,在項目編譯階段,程式會到靜态庫中查找相應的目标檔案。
¨ 接下來使用靜态庫中的函數,修改頭檔案FirstLibraryTestAppDelegate.h如下:
#import <UIKit/UIKit.h>
#include "TestCFunction.h"
@interface FirstLibraryTestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
function* iFunc;
@property (nonatomic, retain) IBOutlet UIWindow *window;
修改相應的實作檔案如下:
#import "FirstLibraryTestAppDelegate.h"
@implementation FirstLibraryTestAppDelegate
@synthesize window;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
iFunc = [[function alloc] init];
int a = 3,b = 6;
int max = 0,min = 0;
max = [iFunc getMax:a b:b];
min = [iFunc getMin:a b:b];
NSLog(@"max = %d,min = %d",max,min);
int c = 8,d = 22;
swapValue(&c, &d);
NSLog(@"after swapValue c = %d,d = %d",c,d);
// Override point for customization after application launch
[window makeKeyAndVisible];
- (void)dealloc {
[window release];
[super dealloc];
編譯下,會發現項目無法編譯通過,錯誤資訊如下:
error: function.h: No such file or directory
就是說,項目無法找到相應的靜态庫的頭檔案,進而也就無法在項目和靜态庫之間建立“依賴關系”,是以需要在項目的“依賴資訊選項”裡告訴項目它所依賴的靜态庫頭檔案的位置資訊,如下圖設定靜态庫頭檔案的位置資訊:
最後再編譯一下,順利通過,輸出資訊如下:
[Session started at 2009-11-20 10:52:22 +0800.]
2009-11-20 10:52:23.805 FirstLibraryTest[768:207] max = 6,min = 3
2009-11-20 10:52:23.807 FirstLibraryTest[768:207] after swapValue c = 22,d = 8
有時候程式會出現如下錯誤資訊:
這是因為在靜态庫裡使用了Objective-C風格的源檔案,需要在項目的“依賴關系資訊項”裡設定如下:
添加内容項為“-ObjC”。