- 浏览: 171474 次
- 性别:
- 来自: 济南
最新评论
-
enefry:
如果 请求头是 range bytes=100-100 怎么 ...
[JSP]断点续传多线程链接下载! JSP/Servlet 实现 -
zhw332548183:
请问楼主,为什么 图片截取完毕后,会一直显示 正在保存 ...
从android系统图库中取图片的代码 -
zhw332548183:
请问楼主,为什么 图片截取完毕后,会一直显示 正在保存 ...
从android系统图库中取图片的代码 -
lovebirdegg:
82934162 写道lovebirdegg 写道829341 ...
怎样将xmppframework应用于iphone应用程序开发 -
82934162:
lovebirdegg 写道82934162 写道请问,你现在 ...
怎样将xmppframework应用于iphone应用程序开发
For some reason Apple reserves the ability to create iPhone frameworks for their own use. They are a very useful ability to have because they package headers together with a universal binary. „Universal“ meaning that you get binary code for multiple platforms rolled into a single file. Frameworks are also dynamically loaded which means that less binary code fills up your memory as only stuff is put there that is actually needed.
But alas, no frameworks for us.
Until now I am selling my components in the Dr. Touch’s Parts Store as source code which at the same time means that I could not provide demonstration versions to try out in your own code. If you have the code, what incentive is there to pay the price?
It has been suggested to me by several people independently to make a static library to solve this problem. Could be time- or otherwise limited, but then people could try the parts out and see how well they fit with their own work.
Also next to still offering access to my repositories at full price, I could be selling indidual versions without right to upgrade to get started at a substantial discount. Later if you find that the component really IS worth what I am asking for, you could upgrade to the lifetime upgrade plan via the SVN repo.
Another reason to figure out this Static Library Magic is so that I can bundle my own utility classes that I keep adding to and improving in a central place. This gives me the choice of adding an external SVN reference or to simply copy the static library into my new projects.
In this article I am describing how to create a universal static library for both Intel and Arm architectures, how to glue them together into a single file and how to add it to a new demo project.
Step 1 – Code for a new utility static library
Start out by creating an iPhone static library project.
So that there is actually code inside our static library we create a
class extension for NSURL to give us a dictionary of all the parameters
passed in a URL. This is quite useful when analyzing the parameters from
the applicationion:didFinishLaunchingWithOptions if your app is
launched via its URL scheme.
NSURL+DT.h
@interface NSURL ( DT) // dictiary which contains param = value for each parameter - ( NSDictionary * ) dictionaryOfParameters; @end |
NSURL+DT.m
#import "NSURL+DT.h" @implementation NSURL ( DT) - ( NSDictionary * ) dictionaryOfParameters { NSString * paramName; NSString * paramValue; NSMutableDictionary * tmpDict = [ NSMutableDictionary dictionary] ; NSScanner * scanner = [ NSScanner scannerWithString: [ self query] ] ; // NOTE: This cannot deal with values that contain & or similar HTML entities while ( ! [ scanner isAtEnd] ) { [ scanner scanUpToString: @ "=" intoString:& paramName] ; [ scanner scanString: @ "=" intoString: nil ] ; [ scanner scanUpToString: @ "&" intoString:& paramValue] ; [ scanner scanString: @ "&" intoString: nil ] ; [ tmpDict setObject: paramValue forKey: paramName] ; } return [ NSDictionary dictionaryWithDictionary: tmpDict] ; } @end |
Drag the header into the „Copy Headers“ section of the target. Drag the implementation file into the „Compile Sources“ section. Contrary to a regular iPhone app target you have to do that manually so that your static library actually contains anything to compile. Also note that the build steps differ from those for an app target.
Step 2 – Set up the targets
Your default Cocoa Touch static library comes with a single target. We want to be able to build for multiple targets with different architectures. So first we change the current target’s base SDK to iPhone SDK 3.0. This will build it for the arm6 and arm7 platforms. Rename the target by appending Dev to the target name so that we know this is the one set up for device.
Next we duplicate the target by right-clicking on it and „Duplicate“. Rename the second target by appending Sim to the name to signal that this is the one built for simulator.
We also set the base SDK for the Sim target to be the same version but for simulator. This causes the build to be made for the i386 platform.
The SDK you choose in the upper lefthand box overrides the set base SDK for your targets. So if you want the selected SDKs to be built for you have to set it to „Use Base SDK“. If this is set then building the individual targets obeys the individually set base SDK.
Let’s try building both targets. There is no Build-All option yet, so we build both targets one after the other.
It’s no problem that they have the same output file name because due to the different SDK they end up in different subfolders of your build folder, Debug-iphonesimulator and Debug-iphoneos. If you like you can get them renamed by changing the product name of the targets, but that’s optional. The following shows the layout of your project after all setup but before the builds as the products are still red.
Step 3 – A „Build All“ Target with merging
We don’t want to have to build all targets individually every time and also we still need to glue them together. So we create a new aggregation target which we call „Build & Merge Libraries“
To this combation target we add our previous targets as dependencies. This will cause the building of sub-targets if they are outdated.
Apple provides the lipo tool for merging multiple binaries into one. Most likely you have it already installed at /usr/bin/lipo, mine is dated July 3rd 2009 and I did not manually install it.
We add a new “Run Script Build Phase” after the two sub-targets and fill in our code to make a new output folder and merge the libraries.
Here’s the code. It basically instructs lipo where to find the two libraries for the different architectures and where to write the merged result lib archive.
# make a new output folder mkdir -p ${PROJECT_DIR}/build/${BUILD_STYLE}-iphoneos/DTUtilities # combine lib files for various platforms into one lipo -create "${PROJECT_DIR}/build/${BUILD_STYLE}-iphoneos/libDTUtilities.a" "${PROJECT_DIR}/build/${BUILD_STYLE}-iphonesimulator/libDTUtilities.a" -output "${PROJECT_DIR}/build/${BUILD_STYLE}-iphoneos/DTUtilities/libDTUtilities-${BUILD_STYLE}.a" |
Step 4 – Package it for distribution
If you want to use the library in another project or hand to somebody else you have to add the headers and any other resources (like images) that it uses. A framework would have taken care of this for us, but we need to transfer these files manually. So we’ll make two extra build steps to automate the copying of files and zipping it into a handy archive.
We add a new “Copy Files Build Phase” and set it up so that our header is copied. We want the header to go into our subfolder of the products folder.
Drag the header into this phase. If there where any PNGs or other resources we would drag them into here as well.
Finally, so that we can send it off we want to make a compressed archive out of our result. This can be accomplished by yet another run script build phase. I found that the ditto command does the best job of making archives that look like you made them in Finder.
ditto -c -k --keepParent "${PROJECT_DIR}/build/${BUILD_STYLE}-iphoneos/DTUtilities" "${PROJECT_DIR}/build/${BUILD_STYLE}-iphoneos/DTUtilities.zip" |
So in total our Build & Merge target looks like this:
If we now build this target, provided that we have chosen Base SDK in the top left picker, we get a ZIP file that contains all our resources and the merged static library with code that can be linked with arm6, arm7 and Intel binaries.
Step 5 – Use it in a different project
From this point on, this diverges from the topic of this article. Therefore if all you where looking for was how to make a Universal Static Library you can stop reading right now.
To actually use/test this library we’ll make a very simple project that just logs the parameters passed if our demo app is called via an URL scheme.
We create a new project for a new View-based application. Then we drag the header and library from our distribution folder into our project and choose that we want it to be copied to our project. Note that Xcode automatically adds the library to the linker phase of the target.
So that we can test the calling via URL we’ll add some code to the app delegate to NSLog the passed parameters. Don’t forget the import.
- ( BOOL ) application: ( UIApplication * ) application didFinishLaunchingWithOptions: ( NSDictionary * ) launchOptions { NSLog( @ "%@" , launchOptions) ; NSURL * launchURL = [ launchOptions objectForKey: UIApplicationLaunchOptionsURLKey] ; NSDictionary * parameters = [ launchURL dictionaryOfParameters] ; NSLog( @ "%@" , parameters) ; // Override point for customization after app launch [ window addSubview: viewController.view] ; [ window makeKeyAndVisible] ; return YES ; } |
We need to add a URL scheme to our app so that it can be launched via URL. This is done by adding a URL identifier and a URL scheme to the info plist.
Now if we where to simply try this out we would get an exception that our dictionaryOfParameters method is an unrecognized selector. The reason being that C and C++ generates symbols for each function whereas Objective-C only generates one per class. We need to force the linker (ld ) to also load the members of the class. This is achieved by the linker flag -ObjC.
The second problem being that NSURL itself is in a different archive than our category extension. It’s in fact in a dynamically bound object file in one of Apple’s frameworks. Thus the linker thinks it’s already got all that makes up NSURL and does not load our category extension. At runtime it turns out that this assumption was false and thus we get the crash. Fortunately we can force inclusion of all our objects from our static library by adding the linker flag -all_load.
-all_load will include all members of all classes from all your static libraries. If you happen to have dozens of static libraries and you want to force the full loading only of individual ones you can use the -force-load parameter as an alternative because it allows you to specify a single library archive to completely load. But for a single static library it’s probably ok to go with all_load.
These flags need to be added to the target’s “Other Linker Flags”.
Note: If you built previously you have to clean the build and make a new build for linker flag changes to take effect.
We can now try out our app. We hit Build&Run once so that we get the latest version installed. Next we go into mobile Safari in iPhone Simulator and enter a URL that begins with demo:// so that the iPhone OS starts our app.
This causes Safari to quit and our app to start. The results from NSLog in simulator also end up in the console app where we can see that all is working. The first NSLog shows the options dictionary, the second the dictionary that our category extension method returned.
Ok, Simulator works, that alone does not fully convince us. We’ll also want to try it out on device to see if the linker was able to get the arm code from the merged library. We’ll use a nifty feature of the debugger to have it not start the app, but instead wait until the next launch.
For the LibDemo executable set the debugger settings to “Wait for next launch/push notification”.
If we now debug then Xcode will not start our app, but wait faithfully until it is launched the next time. So if we repeat our test in Mobile Safari, this time on device, we’ll see on the console the same result proving that it works.
<script type="text/javascript"><!-- google_ad_client = "pub-1142183725909145"; google_ad_slot = "4110438702"; google_ad_width = 468; google_ad_height = 60; //--></script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script><script>google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad);</script>
Conclusion
You can see that it is really not very difficult to package your code into static libraries that combine multiple architectures, in our case i386, arm6 and arm7. This way you can let other people try out our components or classes without having to hand them the source code. They only need the headers, the lib archive (.a) file and any resources (like PNGs) that your components are using.
We’ve been using a Debug build of our library all this time. This preserves the debug symbols for our own development. But for release and distribution builds we will probably want to make a Release build of the library so that debug symbols are stripped out.
Now that I have learned these steps I will start making static libraries for all my components on the Dr. Touch’s Parts Store so that people interested in using them have a way to try before they buy. I’m yet uncertain how I want to limit the functionality though. Maybe I’ll superimpose a big translucent “SAMPLE” over a control or maybe I’ll add some time limiting functionality. I’ll figure it out.
Besides of being able to provide free samples I am also contemplating offering one-time-only purchases of all my components without free upgrades to major new versions and without source code. This could be offered at a fraction of the cost of the source code itself.
So universal static library are a powerful tool to have in your arsenal as iPhone developer. Still be hope that some day Apple lets us make frameworks for iPhone as well.
发表评论
-
Key-Value Coding. Key-Vaule Observing
2012-02-17 11:41 1258Key-value coding (KVC) 是 ... -
FMDB:我的SQLite救星
2011-08-23 17:08 1304FMDB:我的SQLite救 ... -
统计代码行数
2011-01-04 16:39 2452http://lovebirdegg.appspot. ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.2(3)
2010-04-16 15:25 1279原文地址:http://www.aisidechina.com ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.2(2)
2010-04-16 15:22 1777原文地址:http://www.aisidechina.com ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.1
2010-04-14 10:27 1749原文地址:http://www.aisid ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.2(1)
2010-04-14 10:25 981原文地址:http://www.aisidechina.com ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.4
2010-04-12 17:16 1170原文地址:http://www.aisid ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.3
2010-04-08 08:10 1394《iPhone应用程序开发 ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.2
2010-04-08 08:09 1421原文地址: http://www.aisidechina. ... -
7 tips for using UIWebView
2010-03-26 14:34 2177For an IPhone app I have been b ... -
how to use TouchXML
2010-03-25 21:50 1647iphoen do not have NSXML* libra ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.1
2010-03-25 12:57 1098原文地址:http://www.aisidechina.com ... -
10 个在app store中需要避免的错误(一)
2010-03-19 18:13 1544原文 #1 Creating an Overly Compl ... -
Filtering Fun with Predicate
2010-03-16 09:34 1520原文:http://lovebirdegg.co.tv/201 ... -
《iPhone应用程序开发指南》第一章 1.1(2)
2010-03-12 17:12 2935原文地址: http://www.aisidechina. ... -
《iPhone应用程序开发指南》第一章 1.1(1)
2010-03-12 17:11 2220原文地址: http://www.aisidechina. ... -
《iPhone应用程序开发指南》目录
2010-03-12 17:09 2171原文地址 http://www.ais ... -
《iPhone应用程序开发指南》介绍
2010-03-12 17:07 2796原文地址 http://www.ais ... -
14 open source iphone app store apps
2010-03-10 20:34 1563http://lovebirdegg.co.tv/2010 ...
相关推荐
在动态库(dynamic libraries)和静态库(static libraries)使用模板(template)
FFmpeg 4.2.2 static libraries for macOS.rar Mac 上面使用的静态库 ,用来设计播放器或者设计视频剪辑工具,视频下载工具
给大家介绍一下在动态库(dynamic libraries)和静态库(static libraries)使用模板(template)的用法和解决方案。
官方下载链接:https://www.altium.com/documentation/other_installers#!libraries
Nvidia CUDA libraries for testing
Agilent IO Libraries Suite 14.2,支持配合安捷伦IntuiLink使用,是安捷伦仪器连接电脑必备的软件。不同版本IO Libraries并不能兼容,所以不是最新的就是最好。
Axure RP9 Libraries
protel99se 元件库:Protel DOS Schematic Libraries.ddb
DSP2833x_Libraries 开发库函数
Agilent IO Libraries Suite 14.2,支持配合安捷伦IntuiLink使用,是安捷伦仪器连接电脑必备的软件。不同版本IO Libraries并不能兼容,所以不是最新的就是最好。
MySQL_LoadRunner_libraries,将解压的文件中,bin目录下的文件放到loadrunner的bin目录下,include目录下的文件放到loadrunner的include目录下
This repo provides pre-compiled onnxruntime shared and static libraries for various platforms. 此存储库为各种平台提供预编译的 onnxruntime 共享库和静态库。 可以在golang里面结合github....
This HOWTO for programmers discusses how to create and use program libraries on Linux. This includes static libraries, shared libraries, and dynamically loaded libraries.
The POCO C++ Libraries are... > a collection of C++ class libraries, similar in concept to the Java Class Library, the .NET Framework or Apple's Cocoa; > focused on "internet-age" network-centric ...
JSP Tag Libraries
英文清晰版 Getting Started with LLVM Core Libraries ,学习LLVM必不可少的资料 A practical guide to understanding LLVM with the help of source code references and snippets, insights on how compiler ...
android builded ffmpeg2.1.3 to shared libraries
Axure92个常用组件Libraries.rar
Download Libraries Old Content - visit altium.com/documentation Modified by Admin on Sep 13, 2017 Download all Libraries: Download all Libraries, in single ZIP file (305MB) ...