IOS - SDK开发

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"];

 
posted @ 2017-06-08 14:44  Niki~  Views(306)  Comments(0Edit  收藏  举报