zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    2017 ACM-ICPC, Universidad Nacional de Colombia Programming Contest gym101466 题解
    Codeforces Round #634 (Div. 3)题解
    AtCoder Beginner Contest 162 题解
    2018-2019 ACM-ICPC, Asia Nakhon Pathom Regional Contest-gym 102091 题解
    多线程资料
    文件自动导入
    GWT+CodeTemplate+TableCreate快速开发
    阅读大神博客笔记
    Java数据类型
    Java断言assert
  • 原文地址:https://www.cnblogs.com/SimonGao/p/5004686.html
Copyright © 2011-2022 走看看