iOS 开发新版 动态库framework

0. 参考

  http://www.cocoachina.com/industry/20140613/8810.html

  framework+xib参考 : http://blog.csdn.net/xyxjn/article/details/42527341

1. 设置主头文件

  系统已经自动生成好了。

2. 设置公开的头文件

  工程导航栏>"工程名">Build Phases>菜单栏Editor>Add Build Phases>Add Headers Build Phase。

  如果该项不能选择,则点击下方的Build Phases的区域获取焦点。其它需要公开的头文件就放到Public下面。

3. 编译后就生成了framework

4. 合并模拟器framework和真机framework

  iOS默认生成两个framework,一个用于模拟器,一个用于真机。这样的话,用起来模拟器和真机可能会表现不一定。所以,合并成通用的framework是很好的方案。并且这是可行的。合并完了之后呢,顺便要把生成的framework放到工程的制定Products目录下。因为Products名称是生成的默认目录名称。

  怎么进行合并呢?

4.1. 创建Aggregate Target 

4.1.0. 参考

     iOS 之 Aggregate Target,在这里我取名为:aggregateTest

4.1.1. 设置Target Dependencies

  TARGETS-->选中“aggregateTest”-->Build Phases-->Target Dependencies  ,将真正的动态库添加到其中。

4.2. 脚本

4.2.1. 目的

  • 分别编译生成真机和模拟器使用的framework;
  • 使用lipo命令将其合并成一个通用framework;
  • 最后将生成的通用framework放置在工程根目录下新建的Products目录下。

4.2.2. 路径

   TARGETS-->选中“aggregateTest”-->Build Phases-->Run Script-->左上角+-->New Run Script Phase

4.2.3. 内容

# Sets the target folders and the final framework product. 
FMK_NAME=${PROJECT_NAME} 
 
# Install dir will be the final output to the framework. 
# The following line create it in the root folder of the current project. 
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework 
 
# Working dir will be deleted after the framework creation. 
WRK_DIR=build 
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework 
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework 
 
# -configuration ${CONFIGURATION}  
# Clean and Building both architectures. 
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build 
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build 
 
# Cleaning the oldest. 
if [ -d "${INSTALL_DIR}" ] 
then 
rm -rf "${INSTALL_DIR}" 
fi 
 
mkdir -p "${INSTALL_DIR}" 
 
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/" 
 
# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product. 
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}" 
 
rm -r "${WRK_DIR}" 

open "
${SRCROOT}/Products/"

4.2.4. 生成

  在Xcode的左上角选中刚生成的Aggregate>Generic iOS Device ,编译。如果,编译很快,则表示没有成功,因为输入的脚本没有执行。则切换文件失去焦点,让脚本有效,或者重新打开工程。

4.3. 使用动态库

4.3.1. 添加动态库到工程

4.3.1.1. Link Binary with Libraries

  项目导航栏-->选中项目-->Targets-->选中项目-->Build Phases-->Link Binary with Libraries

4.3.1.2. Copy Bundle Resources

  项目导航栏-->选中项目-->Targets-->选中项目-->Build Phases-->Copy Bundle Resources

 

  如果还不行,就需要:

  项目导航栏-->选中项目-->Targets-->选中项目-->General --> embeded Binaries

4.3.1.3. 为动态库添加链接依赖
4.3.1.3.1. 自动链接依赖

  启动时自动链接:项目导航栏-->选中项目-->Targets-->选中项目-->Build Setting-->Runpath Search Paths,添加@executable_path/

  由于Copy Bundle Resources有动态库,即在main bundle(即沙盒中的.app目录)里面有动态库,所以,添加@executable_path/,表示可执行文件所在目录。

4.3.1.3.1. 需要时链接依赖

  即插即用,需要时再加载动态库。如果是这种方式,那么需要把Targets-->Build Phases-->Link Binary With Libraries中的动态库的Status由Required设置为Optional,或者直接删除也行。

4.3.1.4. 加载动态库
4.3.1.4.1. dlopen 加载
- (IBAction)onDlopenLoadAtPathAction1:(id)sender 
{ 
    NSString *documentsPath = [NSString stringWithFormat:@"%@/Documents/xxx.framework/Dylib",NSHomeDirectory()]; 
    [self dlopenLoadDylibWithPath:documentsPath]; 
} 
 
- (void)dlopenLoadDylibWithPath:(NSString *)path 
{ 
    libHandle = NULL; 
    libHandle = dlopen([path cStringUsingEncoding:NSUTF8StringEncoding], RTLD_NOW); 
    if (libHandle == NULL) { 
        char *error = dlerror(); 
        NSLog(@"dlopen error: %s", error); 
    } else { 
        NSLog(@"dlopen load framework success."); 
    } 
} 

  该方式不知道会否通过苹果审核,建议不要使用。

4.3.1.4.1. NSBundle 加载
- (IBAction)onBundleLoadAtPathAction1:(id)sender 
{ 
    NSString *documentsPath = [NSString stringWithFormat:@"%@/Documents/Dylib.framework",NSHomeDirectory()]; 
    [self bundleLoadDylibWithPath:documentsPath]; 
} 
 
- (void)bundleLoadDylibWithPath:(NSString *)path 
{ 
    _libPath = path; 
    NSError *err = nil; 
    NSBundle *bundle = [NSBundle bundleWithPath:path]; 
    if ([bundle loadAndReturnError:&err]) { 
        NSLog(@"bundle load framework success."); 
    } else { 
        NSLog(@"bundle load framework err:%@",err); 
    } 
} 

 

4.3.1.4. 使用动态库的功能

  加载完成后声明类就可以使用了,操作示例如下:

Class rootClass = NSClassFromString(@"Person"); 
    
if (rootClass) { 
     id object = [[rootClass alloc] init]; 
     [(Person *)object run]; 
} 

4.3. 监控动态库的加载和移除

_dyld_register_func_for_add_image(&image_added); 
_dyld_register_func_for_remove_image(&image_removed); 

5. 其它

5.1. framework 里面的资源

资源放置在 Aggregate->Build Phases ->Target Dependencies

引用资源类似这样:VoogolfZxing.framework/CodeScan.bundle/qrcode_Scan_weixin_Line

posted on 2015-11-29 13:45  大木哥  阅读(1865)  评论(0编辑  收藏  举报

导航