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"];
网友评论
Myview *myview = [[Myview alloc] init];
[self.view addSubview:myview];
导入时爆红,提示找不到MySDK
这个脚本首先创建了MySDK.framework/Versions/A/Headers目录,然后创建了一个framework所需要的三个连接符号(symbolic links)。
Versions/Current => A
Headers => Versions/Current/Headers
MySDK => Versions/Current/MySDK
?
最后,将公共头文件从你之前定义的公共头文件路径拷贝到Versions/A/Headers目录下,-a参数确保修饰次数作为拷贝的一部分不会改变,防止不必要的重新编译。
这一步怎么操作 新手 求解答