iOS 自定义framework制作方法教程

 

动态库使用有如下好处:

1使用动态库,可以将最终可执行文件体积缩小

2使用动态库,多个应用程序共享内存中得同一份库文件,节省资源

3使用动态库,可以不重新编译连接可执行程序的前提下,更新动态库文件达到更新应用程序的目的。

4从1可以得出,将整个应用程序分模块,团队合作,进行分工,影响比较小。

但是,苹果禁止iOS开发中使用动态库。

从2可以看出,其实动态库应该叫共享库,那么从这个意义上来说,苹果禁止iOS开发中使用动态库就可以理解了:

因为在现在的iPhone,iPodTouch,iPad上面程序都是单进程的,也就是某一时刻只有一个进程在运行,那么你写个共享库,

1共享给谁?(你使用的时候只有你一个应用程序存在,其他的应该被挂起了,即便是可以同时多个进程运行,别人能使用你的共享库里的东西吗?你这个是给你自己的程序定制的。)

2目前苹果的AppStore不支持模块更新,无法更新某个单独文件(除非自己写一个更新机制:有自己的服务端放置最新动态库文件)

至于苹果为啥禁止ios开发使用动态库我就猜到上面俩原因

好了,那么就剩下静态库了,使用静态库也有好处

1,模块化,分工合作

2,避免少量改动经常导致大量的重复编译连接

3,也可以重用,注意不是共享使用

 

具体流程

接下来介绍自定义的framework的制作过程,他跟苹果官方的那些动态库(framework)不同,其实质算是一个bundle。

1 创建工程

可以创建一个空的工程,删除AppDelegate文件和main.m 文件,还有target里面的app,我们需要的target是.framework

2 创建framework class

比如hello.h hello.m

3 创建一个framework target

new-》new target-》mac ox >> framework >>bundle,这里为什么要创建bundle target,而不是我们想象中的cocoa framework,理由是A “Cocoa Framework” target can’t be compiled to armv6/armv7 and Xcode doesn’t allow us to use “Static Libraries” in a “Cocoa Framework”

 

4 设置bundle target

  • ArchitecturesStandard (armv6 armv7) (the values for this property depend on the value of the item bellow).
  • Base SDKLatest iOS (iOS X.X) (in the X.X will appear the number of the lastest iOS SDK installed on your machine).
  • Build Active Architecture OnlyNO  同时编译支持armv6 7的framework, if it’s YES then we can’t compile to armv6 and armv7 at the same time).
  • Supported Platformsiphonesimulator iphoneos.
  • Valid Architecture$(ARCHS_STANDARD_32_BIT) (it’s very important to be exactly this value, seems there is a bug in Xcode 4, once you set i386 as supported platforms to iOS, it can’t be removed anymore and it could generate errors in your project. So, to avoid any architectures error, use this value).
  • Installation Directory: framework生成以后的路径,可以使 $(BUILT_PRODUCTS_DIR),我喜欢在
  • Mac OS X Deployment TargetCompiler Default.
  • Dead Code StrippingNO.
  • Link With Standard LibrariesNO.
  • Mach-O TypeRelocatable Object File. This is the most important change. Here, we instruct the compiler to treat the Bundle as a relocatable file, by doing this, we can turn it into a framework with the wrapper setting.
  • Other Linker Flags: [optional change] -ObjC, 帮助编译器gcc识别需要编译的代码使用的语言
  • Info.plist File: 清空该字段
  • Wrapper Extensionframework. Here we change the Bundle to a Framework. To Xcode, frameworks 仅仅是以.framework为后缀的文件夹, 里面包含编译后的二进制代码,资源, 还有一个包含对外开放的头文件的文件夹Headers
  • Precompile Prefix HeaderNO.
  • Prefix Headerempty, remove any value from this field.
  • Generate Debug SymbolsNO (this is a very important setting, otherwise your framework will not work on another computer/profile).

上面的每一项最好按要求设置好,不然可能会出现编译问题。

 

5 添加代码和资源(.xib .png .plist等)到bundle target(framework)

在build setting 中,build phrase-》add phrase -》add copy headers

注意区别三种头文件:

public headers:对外开放的头文件

private headers:not neccessry ,visible to xcode but in framework folder

project headers: the other developers nor Xcode have access

Compile Source” 中添加所有的.m .mm .c .cpp

Copy Bundle Resources” .png .xib .plist

 

6 schemes setups

DEBUG mode 全部换成 Release mode

 

7 building the framework编译

分别选择ios device 和 simulator 将将编译出适用armv6 armv7 和 i386架构的release版框架

 

8 创建通用的framework target

方法1 使用lipo工具。在build phrase 中添加 run script:脚本

方法2 新建一个 aggregate 的target,在器build phrase中添加 run script: 脚本,脚本如下:
if [ "${ACTION}" = "build" ]
then
# Set the target folders and the final framework product.
    INSTALL_DIR=${SYMROOT}/FI.framework
    DEVICE_DIR=${SYMROOT}/Release-iphoneos
    SIMULATOR_DIR=${SYMROOT}/Release-iphonesimulator
# Create and renews the final product folder.
    mkdir -p "${INSTALL_DIR}"
    rm -rf "${INSTALL_DIR}"
    rm -rf "${INSTALL_DIR}/FI"
# Copy the header files to the final product folder.
    ditto "${DEVICE_DIR}/FI.framework/Headers" "${INSTALL_DIR}/Headers"
# Use the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
    lipo -create "${DEVICE_DIR}/FI.framework/FI" "${SIMULATOR_DIR}/FI.framework/FI" -output "${INSTALL_DIR}/FI"
fi

 

参考链接:http://db-in.com/blog/2011/05/creating-universal-framework-to-iphone-ios/#list_contents

 

 

扩展阅读

更多更详细的有关制作framework的方法,可以参考下面的一些文章。

iOS上如何制作自己的Framework呢?(不是静态库)

请看stackoverflow上的提问:

http://stackoverflow.com/questions/4065052/how-to-build-a-framework-or-library-for-other-developers-the-secure-way

 

解决办法

1,通过命令行脚本

http://www.cocoanetics.com/2010/04/making-your-own-iphone-frameworks/

由cocoa的Framework演变而来

2,通过hack  bundle

http://www.cocoanetics.com/2010/05/making-your-own-iphone-frameworks-in-xcode/

这种方法有热心的同学做了中文翻译

http://www.cocoachina.com/bbs/read.php?tid-75680.html

但是需要制作2个framework,分别对应于simulator和device

这种方法这里也有详细介绍 http://db-in.com/blog/2011/05/creating-universal-framework-to-iphone-ios/

 

3,使用别人的模板

https://github.com/kstenerud/iOS-Universal-Framework

这个算是集大成吧。当然作者有说明,这个也是假的,并不能象SDK自带的framework那样自如使用

 

而code google上的pldatabase framework是可以象SDK自己的framework一样,一个framework同时运行在模拟器和真机上的

http://code.google.com/p/pldatabase/

有待研究,以后再来补充

补充:

pldatabase framework 也只是产生2个静态库(.a)然后通过lipo合并起来,但是这已经很好了。

Lipo Binary 中的脚本如下:

FRAMEWORK=”${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.framework”

lipo \
“${BUILD_DIR}/${CONFIGURATION}-iphoneos/libPlausibleDatabase-iPhoneOS.a” \
“${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/libPlausibleDatabase-iPhoneSimulator.a” \
-create -output “${FRAMEWORK}/Versions/Current/${PRODUCT_NAME}”

cd “${FRAMEWORK}” && ln -sf “Versions/Current/${PRODUCT_NAME}” ./

看来上面的方法没有产生真正意义上的Framework,所谓的Framework不是hack bundle就是 hack static lib

至于第二种方法为什么可以实现,因为Framework其实也是一个bundle (a structured directory),

可以参照apple的官方说明 http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/Framework.html

 

详见:http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WhatAreFrameworks.html%23//apple_ref/doc/uid/20002303-BBCEIJFI

What are Frameworks?

framework is a hierarchical directory that encapsulates shared resources, such as a dynamic shared library, nib files, image files, localized strings, header files, and reference documentation in a single package. Multiple applications can use all of these resources simultaneously. The system loads them into memory as needed and shares the one copy of the resource among all applications whenever possible.

A framework is also a bundle and its contents can be accessed using Core Foundation Bundle Services or the Cocoa NSBundle class. However, unlike most bundles, a framework bundle does not appear in the Finder as an opaque file. A framework bundle is a standard directory that the user can navigate. This makes it easier for developers to browse the framework contents and view any included documentation and header files.

Frameworks serve the same purpose as static and dynamic shared libraries, that is, they provide a library of routines that can be called by an application to perform a specific task. For example, the Application Kit and Foundation frameworks provide the programmatic interfaces for the Cocoa classes and methods. Frameworks offer the following advantages over static-linked libraries and other types of dynamic shared libraries:

  • Frameworks group related, but separate, resources together. This grouping makes it easier to install, uninstall, and locate those resources.
  • Frameworks can include a wider variety of resource types than libraries. For example, a framework can include any relevant header files and documentation.
  • Multiple versions of a framework can be included in the same bundle. This makes it possible to be backward compatible with older programs.
  • Only one copy of a framework’s read-only resources reside physically in-memory at any given time, regardless of how many processes are using those resources. This sharing of resources reduces the memory footprint of the system and helps improve performance.
Note: Frameworks are not required to provide a programmatic interface and can include only resource files. However, such a use is not common.

The Darwin layer contains many static and dynamic libraries but otherwise, most Mac OS X interfaces are packaged as frameworks. Some key frameworks—including Carbon, Cocoa, Application Services, and Core Services—provide convenient groupings of several smaller but related frameworks. These framework groups are called umbrella frameworks and they act as an abstraction layer between a technology and the subframeworks that implement that technology.

In addition to using the system frameworks, you can create your own frameworks and use them privately for your own applications or make them publicly available to other developers. Private frameworks are appropriate for code modules you want to use in your own applications but do not want other developers to use. Public frameworks are intended for use by other developers and usually include headers and documentation defining the framework’s public interface.

 

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>