iOS ----- SDK开发

作者: 71150ce14a00 | 来源:发表于2016-10-17 11:34 被阅读6491次

    1. 创建一个静态库 名字为   MySDK

    删除没用的.m 文件

    删除.h中内容 添加 #import<UIkit/UIkit.h>

    导入uikit 框架

    依然是在Xcode的Build Phases界面,选择Editor\Add Build Phase\Add Copy Headers Build Phase。

    Note:如果你发现按上面找到的菜单项是灰色的(不可点击的),点击下方Build Phases界面的白色区域来获取Xcode的应用焦点,然后重新试一下。

    把MySDK.h从项目导航栏中拖到中央面板的Copy Headers下的Public部分。这一步确保任何使用你的库的用户均可以获取该头文件。

    Note:显然,所有包含在你的公共头文件中的头文件必须是对外公开的,这一点非常重要。否则,开发者在使用你的库时会得到编译错误。如果Xcode在读取公共头文件时不能读到你忘记设为public的头文件,这实在是太令人沮丧了。

    创建一个UI页面拖入工程

    Note:在你弄清楚之前,这三个组的名称可能会让你迷惑,Public是你期望的,Private下的头文件依然是可以暴露出来的,因此名字可能有些误导。讽刺的是,在Project下的头文件对你的工程来说才是“私有”的,因此,你将会更多地希望你的头文件或者在Public下,或者在Project下。

    现在,你需要将控件的头文件Myview.h分享出来,有几种方式可以实现这一点,首先是在Copy Headers面板中将这个头文件从Project栏拖到Public栏。

    配置Build Settings

    然后选择MySDK静态库目标,选择Build Setting栏,然后搜索public header,双击Public Headers Folder Path,在弹出视图中键入如图所示内容:

    输入 include/$(PROJECT_NAME)

    因为你正在创建framework供他人使用,最好禁掉这些功能(无效代码和debug用符号),让用户自己选择对自己的项目有利的部分使用。和之前一样,使用搜索框,改变下述设置:

    Dead Code Stripping设置为NO

    Strip Debug Symbol During Copy 全部设置为NO

    Strip Style设置为Non-Global Symbols

    编译然后运行,到目前为止没什么可看的,不过确保项目可以成功构建,没有错误和警报是非常好的。

    选择目标为iOS Device,按下command + B进行编译,一旦成功,工程导航栏中Product目录下libMySDK.a文件将从红色变为黑色,表明现在该文件已经存在了。右键单击libMySDK.a,选择Show in Finder。

    第二大部分

    常见一个新的工程(Single View Application 类型)位置和MySDK位置在同一目录下

    把MySDK工程关掉 将MySDK.xcodeproj拖入MyTestSDK中的工程

    Note:你无法将同一工程在两个Xcode窗口中同时打开,如果你发现你无法在你的工程中导航到库工程的话,检查一下是否库工程在其他Xcode窗口中打开了。

    为了连接到静态库本身,展开Link Binary With Libraries面板和TargetDependencies,再次点击+按钮,从Workspace组中选择libMySDK.a然后点击Add。

    然后在MyTestSDK的viewController 中导入头文件#import<MySDK/Myview.h>

    Myview *myview = [[Myview alloc] init];

    [self.view addSubview:myview];

    添加view,运行我只设置了View的北京颜色 

    第三大部分   创建framework

    到现在,你可能迫不及待地点着脚趾头,想着什么时候framework可以出来。可以理解,因为到现在为止你已经做了许多工作,然而却没有看到过framework的身影。

    现在你需要在静态库构建过程中添加脚本来创建这种结构,在项目导航栏中选择MySDK.xcodeproj,然后选择MySDK静态库目标,选择Build Phases栏,然后选择Editor/Add Build Phase/Add Run Script Build Phase来添加一个新的脚本。

    none: 如果是灰色的请点击build phases 页面 聚集焦点

    添加脚本信息

    set -e

    export FRAMEWORK_LOCN="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework"

    # Create the path to the real Headers dir

    mkdir -p "${FRAMEWORK_LOCN}/Versions/A/Headers"

    # Create the required symlinks

    /bin/ln -sfh A "${FRAMEWORK_LOCN}/Versions/Current"

    /bin/ln -sfh Versions/Current/Headers "${FRAMEWORK_LOCN}/Headers"

    /bin/ln -sfh "Versions/Current/${PRODUCT_NAME}" \

    "${FRAMEWORK_LOCN}/${PRODUCT_NAME}"

    # Copy the public headers into the framework

    /bin/cp -a "${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/" \

    "${FRAMEWORK_LOCN}/Versions/A/Headers"

    这个脚本首先创建了MySDK.framework/Versions/A/Headers目录,然后创建了一个framework所需要的三个连接符号(symbolic links)。

    Versions/Current => A

    Headers => Versions/Current/Headers

    MySDK => Versions/Current/MySDK

    最后,将公共头文件从你之前定义的公共头文件路径拷贝到Versions/A/Headers目录下,-a参数确保修饰次数作为拷贝的一部分不会改变,防止不必要的重新编译。

    现在,选择MySDK静态库,然后选择iOS Device构建目标,然后使用cmd+B构建。

    创建Aggregate  

    点击Next 命名为Framework----> finish

    在Build Phases中添加一个依赖。展开Target Dependencies面板,点击 + 按钮选择MySDK静态库。

    这个目标的主要编译部分是多平台编译,你将使用一个脚本来做到这一点。和你之前做的一样,在Framework目标下,选择Build Phases栏,点击Editor/Add Build Phase/Add Run Script Build Phase,创建一个新的Run Script Build Phase。

    添加脚本信息

    ----------------------------------------------------------------------------------------------------------

    set -e

    # If we're already inside this script then die

    if [ -n "$RW_MULTIPLATFORM_BUILD_IN_PROGRESS" ]; then

    exit 0

    fi

    export RW_MULTIPLATFORM_BUILD_IN_PROGRESS=1

    RW_FRAMEWORK_NAME=${PROJECT_NAME}

    RW_INPUT_STATIC_LIB="lib${PROJECT_NAME}.a"

    RW_FRAMEWORK_LOCATION="${BUILT_PRODUCTS_DIR}/${RW_FRAMEWORK_NAME}.framework"

    function build_static_library {

    # Will rebuild the static library as specified

    #    build_static_library sdk

    xcrun xcodebuild -project "${PROJECT_FILE_PATH}" \

    -target "${TARGET_NAME}" \

    -configuration "${CONFIGURATION}" \

    -sdk "${1}" \

    ONLY_ACTIVE_ARCH=NO \

    BUILD_DIR="${BUILD_DIR}" \

    OBJROOT="${OBJROOT}" \

    BUILD_ROOT="${BUILD_ROOT}" \

    SYMROOT="${SYMROOT}" $ACTION

    }

    function make_fat_library {

    # Will smash 2 static libs together

    #    make_fat_library in1 in2 out

    xcrun lipo -create "${1}" "${2}" -output "${3}"

    }

    # 1 - Extract the platform (iphoneos/iphonesimulator) from the SDK name

    if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]; then

    RW_SDK_PLATFORM=${BASH_REMATCH[1]}

    else

    echo "Could not find platform name from SDK_NAME: $SDK_NAME"

    exit 1

    fi

    # 2 - Extract the version from the SDK

    if [[ "$SDK_NAME" =~ ([0-9]+.*$) ]]; then

    RW_SDK_VERSION=${BASH_REMATCH[1]}

    else

    echo "Could not find sdk version from SDK_NAME: $SDK_NAME"

    exit 1

    fi

    # 3 - Determine the other platform

    if [ "$RW_SDK_PLATFORM" == "iphoneos" ]; then

    RW_OTHER_PLATFORM=iphonesimulator

    else

    RW_OTHER_PLATFORM=iphoneos

    fi

    # 4 - Find the build directory

    if [[ "$BUILT_PRODUCTS_DIR" =~ (.*)$RW_SDK_PLATFORM$ ]]; then

    RW_OTHER_BUILT_PRODUCTS_DIR="${BASH_REMATCH[1]}${RW_OTHER_PLATFORM}"

    else

    echo "Could not find other platform build directory."

    exit 1

    fi

    # Build the other platform.

    build_static_library "${RW_OTHER_PLATFORM}${RW_SDK_VERSION}"

    # If we're currently building for iphonesimulator, then need to rebuild

    #  to ensure that we get both i386 and x86_64

    if [ "$RW_SDK_PLATFORM" == "iphonesimulator" ]; then

    build_static_library "${SDK_NAME}"

    fi

    # Join the 2 static libs into 1 and push into the .framework

    make_fat_library "${BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}" \

    "${RW_OTHER_BUILT_PRODUCTS_DIR}/${RW_INPUT_STATIC_LIB}" \

    "${RW_FRAMEWORK_LOCATION}/Versions/A/${RW_FRAMEWORK_NAME}"

    # Ensure that the framework is present in both platform's build directories

    cp -a "${RW_FRAMEWORK_LOCATION}/Versions/A/${RW_FRAMEWORK_NAME}" \

    "${RW_OTHER_BUILT_PRODUCTS_DIR}/${RW_FRAMEWORK_NAME}.framework/Versions/A/${RW_FRAMEWORK_NAME}"

    # Copy the framework to the user's desktop

    ditto "${RW_FRAMEWORK_LOCATION}" "${HOME}/Desktop/${RW_FRAMEWORK_NAME}.framework"

    ----------------------------------------------------------------------------------------------------------

    选择Framework集合方案(aggregate scheme),按下cmd+B编译该MySDK。

    如果编译成功, 在桌面上将生成一个MySDK.framework 

    为了检查一下我们的多平台编译真的成功了,启动终端,导航到桌面上的framework,像下面一样:

    $ cd ~/Desktop/MySDK.framework

    $  xcrun lipo -info MySDK

    这里你可以看到,一共有五种片段:i386, x86_64, arm7, arm7s 和 arm64,正如你在编译时设定的那样。如果你之前使用lipo –info指令,你可以看到这些片段的一个分组。

    打包(Bundle)资源

    你有没有注意到MySDK的framework只包含了代码和头文件,其他的文件却没有被包含。例如,你没有使用其他任何资源,比如图片。这是iOS的一个限制,framework只能包含头文件和静态库。

    下面我们就来创建一个包含图片的资源方法、

    选择MySDK.xcodeproj   点击Add Target按钮

    导航到macOS /Framework and Library/Bundle。将新的Bundle命名为MySDKResources,然后从framework选择框中选择Core Foundation。

    这里需要配置几个编译设置,因为你正在创建一个在iOS上使用的bundle,这与默认的OS X不同。选择MySDKResources目标,然后点击Build Settings栏,搜索base sdk,选择Base SDK这一行,按下delete键,这一步将OS X切换为iOS。

    同时你需要将工程名称改为MySDK。搜索product name,双击进入编辑模式,将${TARGET_NAME}替换为MySDK。

    默认情况下,有两种resolutions的图片可以产生一些有趣的现象。例如,当你导入一个retina @2x版本的图片时,普通版的和Retina版的将会合并成一个多resolution的TIFF(标签图像文件格式,Tagged Image File Format)。这不是一件好事。搜索hidpi将COMBINE_HIDPI_IMAGES设置为NO。

    现在,你将确保当你编译framework时,bundle也能被编译并将framework作为依赖添加到集体目标中。选中Framework目标,选择Build Phases栏,展开Target Dependencies面板,点击 + 按钮,选择MySDKResources目标将其添加为依赖。

    现在,在Framework目标的Build Phases中,打开Run Script面板,在脚本的最后添加下述代码:

    # Copy the resources bundle to the user's desktop

    ditto "${BUILT_PRODUCTS_DIR}/${RW_FRAMEWORK_NAME}.bundle" \

    "${HOME}/Desktop/${RW_FRAMEWORK_NAME}.bundle"

    这条指令将拷贝构建好的bundle到用户的桌面上。现在,编译framework scheme,你会发现bundle在桌面上出现。

    导入Bundle

    在项目导航栏中,选择MyTestSDK工程,点击MySDK目标,展开MySDK工程的Product组,把MySDKResources.bundle拖到Copy Bundle Resources面板中的 Build Phases栏。

    在Target Dependencies面板中,点击+按钮,添加新的依赖,然后选择MySDKResources.bundle。

    接下来拖入一张图片然后设置属于的目标

    导入头文件#import<MySDK/DownViewcontroller.h>到MySDK.h中

    还记得我们说过要确保framework可以被访问吗?现在,你需要导出头文件DownViewController.h,在Target Membership面板中选择该文件,然后从弹出视图中选择Public。

    调用bound中的图片方法

    self.headerImg.image = [UIImage imageNamed:@"MySDK.bundle/header"];

    相关文章

      网友评论

      • 蜗牛1992:然后在MyTestSDK的viewController 中导入头文件#import<MySDK/Myview.h>

        Myview *myview = [[Myview alloc] init];

        [self.view addSubview:myview];
        导入时爆红,提示找不到MySDK
      • f886718d8e26:楼主你好 我在第二部分时 把mySDK.xcodeproj拖入了项目工程中 但是libMySDKDemo.a还是红色的 然后我按照你说的在bulid phrase加了之后 在viewcontroller引用不到mySDK的东西( 在第一部分里 libMySDKDemo.a是生成好了的是黑色)
        蜗牛1992:我也是,第一部分就是红色,showinFind里面是有的。后面拖入工程引用不到
      • 买了否冷_:跑完第一个脚本 编译成功 没有找到下面说的三个标签???

        这个脚本首先创建了MySDK.framework/Versions/A/Headers目录,然后创建了一个framework所需要的三个连接符号(symbolic links)。

        Versions/Current => A

        Headers => Versions/Current/Headers

        MySDK => Versions/Current/MySDK
      • markfrain:你好,请问在编译的时候报错 -target: command not found 这个命令找不到是因为什么原因呢
        ?
      • 这一颗心:Demo里怎么没MySDK项目啊,楼主大大在发一下
        71150ce14a00: https://github.com/dljike/MyTestSDK
      • 神魔狼:创建Aggregate 前添加脚本 编译出错 楼主大大 知道怎么回事吗?:joy_cat:
        biny_ios:下载楼主Demo,复制里面的脚本就不会报错了
        71150ce14a00:@神魔狼 看看demo,应该可以的,时间长了,我也忘了,哈哈
      • DamonLu: framewokr那一步,能编译成功,但是桌面并没有
        DamonLu:@辉109 没仔细研究
        c66413f9ba79:@DamonLu 你解决了吗 我也是 根本没有啊
        DamonLu:请问是为啥呢?难道是脚本语句我写错了?(我可是复制的)
      • 水丿果糖:在创建Aggregate 前的那个添加脚本,com+B就报错了,是什么原因呀
      • 醉叶惜秋: http://code.cocoachina.com/view/133322 这个代码貌似下载了无法解压啊
        71150ce14a00:@醉叶惜秋 https://github.com/dljike/MyTestSDK 试试这个
      • 骑猪兜风_3355:请问一下,我做的sdk,给别人用,我需要打包签名吗
      • KuKuMan:你这个红线框是用什么软件编辑的

        71150ce14a00:@KM赵 扣扣截图:joy:
      • 偶识君乎:写得很细致,学习了
      • 生活沒有如果只有後果:同问 前面的 都 成功了 卡在这一步 完全没有头绪
        最后,将公共头文件从你之前定义的公共头文件路径拷贝到Versions/A/Headers目录下,-a参数确保修饰次数作为拷贝的一部分不会改变,防止不必要的重新编译。
        生活沒有如果只有後果:@YifBo 感谢 是我看叉了 以为 那个是 需要我去操作的的 后来想明白是对脚本的说明 估计 看不懂的那几个 都以为 那段话是 需要 去操作的东西 可以在那里 加个 注释 告诉是 解释 就好没啥问题了 感谢!!!
        71150ce14a00:http://code.cocoachina.com/view/133322 可能对你有帮助
      • 有梦想的咸鱼宁:最后,将公共头文件从你之前定义的公共头文件路径拷贝到Versions/A/Headers目录下,-a参数确保修饰次数作为拷贝的一部分不会改变,防止不必要的重新编译。


        这一步怎么操作 新手 求解答
        71150ce14a00:http://code.cocoachina.com/view/133322可能会对你有帮助

      本文标题:iOS ----- SDK开发

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