動態(tài)庫制作
dlopen 動態(tài)加載Frameworks
使用dlopen和dlsym方法動態(tài)加載庫和調(diào)用函數(shù)
動態(tài)庫使用
鏈接器:符號是怎么綁定到地址上的
問題:在APP運行時通過dlopen和dlsym鏈接加載bundle里面的動態(tài)庫
dlopen:以指定模式打開指定的動態(tài)鏈接庫文件,并返回一個句柄給調(diào)用進程。
void * dlopen( const char * pathname, int mode );
mode:(可多選的)
// 表示動態(tài)庫中的symbol什么時候被加載
RTLD_LAZY 暫緩決定,等有需要的時候再解析符號
RTLD_NOW 立即決定,返回前解除所有未決定的符號
// 表示symbol的可見性
RTLD_GLOBLE 允許導出符號
RTLD_LOCAL
使用系統(tǒng)framework
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"sound" ofType:@"mp3"];
void *lib = dlopen("/System/Library/Frameworks/AVFoundation.framework/AVFoundation", RTLD_LAZY);
if (lib) {
Class playerClass = NSClassFromString(@"AVAudioPlayer");
SEL selector = NSSelectorFromString(@"initWithData:error:");
_runtime_Player = [[playerClass alloc] performSelector:selector withObject:[NSData dataWithContentsOfFile:resourcePath] withObject:nil];
selector = NSSelectorFromString(@"play");
[_runtime_Player performSelector:selector];
NSLog(@"動態(tài)加載播放");
dlclose(lib);
}
使用第三方動態(tài)庫
使用動態(tài)庫有兩種方式,一種是將動態(tài)庫添加未依賴庫,這樣會在工程啟動時加載動態(tài)庫,一種是使用dlopen在運行時加載動態(tài)庫,這兩種方式的區(qū)別在于加載動態(tài)庫的時機。
在iOS上如果使用了方式二,是不能上架到App Store的。
1、將動態(tài)庫的頭文件添加到項目中
2、編譯工程文件。生成APP的包文件,在項目Products文件夾下
3、將framework添加到APP的包文件(鼠標右鍵顯示包內(nèi)容)中
這樣基本就可以運行成功了
// 1.獲取動態(tài)庫路徑
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"MangoSDK" ofType:nil];
// 2.打開動態(tài)庫
void *lib = dlopen([resourcePath UTF8String], RTLD_LAZY);
if (lib == NULL) {
// 打開動態(tài)庫出錯
fprintf(stderr, "%s", dlerror());
exit(EXIT_FAILURE);
} else {
// 獲取類
Class util = NSClassFromString(@"MGUtils");
// 獲取方法
SEL selector = NSSelectorFromString(@"getMessage");
id obj = [[util alloc] init];
// 執(zhí)行
NSString *message = [obj performSelector:selector];
dlclose(lib);
return message;
}
return nil;