美文网首页QiShare文章汇总
iOS App中可拆卸一个framework的两种方式

iOS App中可拆卸一个framework的两种方式

作者: QiShare | 来源:发表于2019-11-11 18:45 被阅读0次

    级别: ★☆☆☆☆
    标签:「iOS」「framework」
    作者: dac_1033
    审校: QiShare团队


    此处说的可拆卸,意思就是业务App的工程是否导入这个framework都不影响编译。如果业务导入了这个framework,就可以使用其中功能,如果没导入,也能编译通过。

    1. 应用场景

    在我们开发项目的过程中,会导入很多的三方库,比如:会导入公司内部业务封装的、微信、微博和支付宝等相关的framework等。在稍微复杂一点的业务中,如下图:

    其中,A.framework和B.framework都是静态库,A.framework使用了B.framework中的方法,那么,一般情况下在APP中想要使用A.framework中的方法,必须要同时将A.framework和B.framework导入到APP工程中,否则编译时会报错。但是在现实情况中,可能业务不需要A包中涉及到B包的功能,因此只想导入A.framework且不想导入B.framework。

    我们新建了一个下面的工程,工程中有两个framework,示例中APP直接使用TestDynamicSdk的方法,TestDynamicSdk使用TestStaticSdk的方法。

    2. 使用相应的宏

    以下代码工作在APP层代码中:

    #import "Test.h"
    
    //// __has_include() 宏在导入三方库 .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层实现自由拆卸TestStaticSdk.framework。

    3. 使用运行时相关方法

    #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:方法没有实现");
            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
    

    这样也能实现APP在使用TestDynamicSdk时自由拆卸TestStaticSdk.framework。

    注意:

    1. 在用宏定义实现时编译可能会报错,开发TestDynamicSdk时需要在其工程配置中添加TestStaticSdk.framework;
    2. 使用运行时相关方法实现时,需要在APP的工程配置中设置-all_load。

    GitHub源码https://github.com/QiShare/QiTestFramework.git)


    推荐文章:
    自定义WKWebView显示内容(一)
    Swift 5.1 (6) - 函数
    Swift 5.1 (5) - 控制流
    Xcode11 新建工程中的SceneDelegate
    iOS App启动优化(二)—— 使用“Time Profiler”工具监控App的启动耗时
    iOS App启动优化(一)—— 了解App的启动流程
    iOS WKWebView的基本使用
    Swift 5.1 (4) - 集合类型
    奇舞周刊

    相关文章

      网友评论

        本文标题:iOS App中可拆卸一个framework的两种方式

        本文链接:https://www.haomeiwen.com/subject/kgrovctx.html