iOS 动态载入framework

        我们开发提供给iOS 开发者者使用的第三方iOS SDK,需要使用几个Apple的Framework,例如 QuartzCore.framework、CoreLocation.framework等。

        这样的话开发者集成我们SDK就需要在自己的Xcode工程引入这些系统Framework,为了方便开发者集成,简化集成步骤。

        我们用了动态加载framework的技术,开发者就不需要手动载入framework,我们在sdk代码中自动实现加载。

       

实现方法

         我们可以用下面的输出看到iOS 在运行时已经把很多Frameworks加载进来。

         NSLog(@"framePaths is %@",[NSBundle allFrameworks]);

        对已经加载进来的Frameworks,我们只需要指定framwork的路径既可以实现加载,例如:

       NSBundle *quartzCoreSupportBundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
        if (quartzCoreSupportBundle != nil) {
            [quartzCoreSupportBundle load];
        }

        可是对于有些framework,例如MessageUI和MapKit,他们加载的真机和模拟器上的路径不一样。如果要实现模拟器上的加载的话,需要根据已经加载的framework路径来得到将要加载framework路径。例如下面得到MessageUI的路径:

        NSString *messageUIPath = nil;
        for (NSBundle *bundle in framePaths) {
            NSRange range = [[bundle bundlePath] rangeOfString:@"/Foundation.framework" options:NSCaseInsensitiveSearch];
            if (range.length > 0) {
                NSString *bundlePath = [bundle bundlePath];
                NSString *lastComponent = [bundlePath lastPathComponent];
                messageUIPath = [bundlePath stringByReplacingOccurrencesOfString:lastComponent withString:@"MessageUI.framework"];
                break;
            }
        }

这样在运行时加载Framework,可是在编译阶段编译器并没有得到Framework,我们可以利用Objc的动态特性来解决编译器的检查。例如下面创建位置管理器:

locationManager = [[NSClassFromString(@"CLLocationManager") alloc] init];


遇到的问题

       上面创建一个类的成员变量或者局部变量,可是不能实现基于Framework的类的继承。例如定义一个类继承上面的CLLocationManager,则会出现编译错误。


另外的一种动态加载方法

载入的framework,如果是C的方法,需要用dlopen和dlsym来载入,例如需要用到SystemConfiguration.framework SCNetworkReachabilityRef方法,可以用下面的写法来载入:

    void *module = dlopen("/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration", RTLD_NOW);
    SCNetworkReachabilityRef (*SCNetworkReachabilityCreateWithName)(CFAllocatorRef,constchar *
                                                                    ) = dlsym(module, "SCNetworkReachabilityCreateWithName");


你可能感兴趣的:(iOS,开发)