級別: ★☆☆☆☆
標(biāo)簽:「iOS」「framework」
作者: dac_1033
審校: QiShare團(tuán)隊
此處說的可拆卸,意思就是業(yè)務(wù)App的工程是否導(dǎo)入這個framework都不影響編譯。如果業(yè)務(wù)導(dǎo)入了這個framework,就可以使用其中功能,如果沒導(dǎo)入,也能編譯通過。
1. 應(yīng)用場景
在我們開發(fā)項目的過程中,會導(dǎo)入很多的三方庫,比如:會導(dǎo)入公司內(nèi)部業(yè)務(wù)封裝的、微信、微博和支付寶等相關(guān)的framework等。在稍微復(fù)雜一點的業(yè)務(wù)中,如下圖:
其中,A.framework和B.framework都是靜態(tài)庫,A.framework使用了B.framework中的方法,那么,一般情況下在APP中想要使用A.framework中的方法,必須要同時將A.framework和B.framework導(dǎo)入到APP工程中,否則編譯時會報錯。但是在現(xiàn)實情況中,可能業(yè)務(wù)不需要A包中涉及到B包的功能,因此只想導(dǎo)入A.framework且不想導(dǎo)入B.framework。
我們新建了一個下面的工程,工程中有兩個framework,示例中APP直接使用TestDynamicSdk的方法,TestDynamicSdk使用TestStaticSdk的方法。
2. 使用相應(yīng)的宏
以下代碼工作在APP層代碼中:
#import "Test.h"
//// __has_include() 宏在導(dǎo)入三方庫 .h 過程中的使用
#if __has_include(<TestStaticSdk/TestStaticSdk.h>)
#import <TestStaticSdk/TestStaticSdk.h>
#ifndef HAS_IMPORT_DY
#define HAS_IMPORT_DY 1
#endif
#else
#ifndef HAS_IMPORT_DY
#define HAS_IMPORT_DY 0
#endif
#endif
@implementation Test
//// ??上面定義的宏HAS_IMPORT_DY的使用
- (NSString *)getCombineStrWithA:(NSString *)aStr B:(NSString *)bStr {
#if HAS_IMPORT_DY == 1
TestStaticSdk *staticSdk = [[TestStaticSdk alloc] init];
NSString *combinedStr = [staticSdk getCombineStrWithA:@"common_A_String" B:@"common_B_String"];
return combinedStr;
#else
return nil;
#endif
}
@end
這樣,使用__has_include宏可以在APP層實現(xiàn)自由拆卸TestStaticSdk.framework。
3. 使用運行時相關(guān)方法
#import "TestDynamicSdk.h"
@interface TestDynamicSdk ()
@property (nonatomic, strong) id staticSdkObject;
@end
@implementation TestDynamicSdk
- (id)init {
self = [super init];
if (self) {
Class class = NSClassFromString(@"TestStaticSdk");
if (!class) {
NSLog(@"TestStaticSdk沒有編譯");
return self;
}
SEL sel = NSSelectorFromString(@"new");
id (*imp)(id, SEL) = (id (*)(id, SEL))[class methodForSelector:sel];
self.staticSdkObject = imp(class, sel);
}
return self;
}
- (NSString *)getCombineStrWithA:(NSString *)aStr B:(NSString *)bStr {
if (!_staticSdkObject) {
NSLog(@"staticSdkObject為空");
return nil;
}
SEL sel = NSSelectorFromString(@"getCombineStrWithA:B:");
if (![_staticSdkObject respondsToSelector:sel]) {
NSLog(@"getCombineStrWithA:B:方法沒有實現(xiàn)");
return nil;
}
NSString * (*imp)(id, SEL, NSString *, NSString *) = (NSString * (*)(id, SEL, NSString *, NSString *))[_staticSdkObject methodForSelector:sel];
NSString *combinedStr = imp(_staticSdkObject, sel, aStr, bStr);
return combinedStr;
}
@end
這樣也能實現(xiàn)APP在使用TestDynamicSdk時自由拆卸TestStaticSdk.framework。
注意:
- 在用宏定義實現(xiàn)時編譯可能會報錯,開發(fā)TestDynamicSdk時需要在其工程配置中添加TestStaticSdk.framework;
- 使用運行時相關(guān)方法實現(xiàn)時,需要在APP的工程配置中設(shè)置-all_load。
GitHub源碼https://github.com/QiShare/QiTestFramework.git)
推薦文章:
自定義WKWebView顯示內(nèi)容(一)
Swift 5.1 (6) - 函數(shù)
Swift 5.1 (5) - 控制流
Xcode11 新建工程中的SceneDelegate
iOS App啟動優(yōu)化(二)—— 使用“Time Profiler”工具監(jiān)控App的啟動耗時
iOS App啟動優(yōu)化(一)—— 了解App的啟動流程
iOS WKWebView的基本使用
Swift 5.1 (4) - 集合類型
奇舞周刊