Due to some bugs and questions with the old tutorial, I’m creating this new one, much more simpler and less bugs than the another one. I’ll not post the old link here because everything you need to know you can find right here.
Nowadays, exist few alternatives to create a Framework to iOS, changing the default Xcode Script, which could not be a good choice if you want to publish the APPs constructed with your custom Framework. I’ll treat here about how to construct an Universal Framework to iOS, using the default tools from Xcode.
Let’s start!
Here is a little list of contents to orient your reading:
| List of Contents to this Tutorial | |
|---|---|
You can download the project I used in this article:

Download now
Xcode project files to Framework-iOS
403kb
FAQ
top
First off, I want to make sure you understand what this Framework to iOS can do, this can safe your time reading this article:
- Can I use this Framework as a Bundle to store my files, XIBs, images?
A: Yes, you can and now it’s very very easy to retrieve your files. - Can I use this Framework to import other Frameworks, like import UIKit, CoreGraphics, OpenGL?
A: No. There is no way to do that. Your code in this custom Framework can import classes from other frameworks normally, but it is just a reference, classes from another framework will not be compiled at this time. So you must import the referenced Framework on the new project as well. - Will be my code visible to others?
A: No. This Framework will export a compiled binary, so anyone can see inside it. You can make the same for some other files, like XIBs. - Why I need this?
A: This is for developers/teams that want to share their codes without shows the entire code (.m/.c/.cpp files). Besides this is for who want to organize compiled code + resources (images, videos, sounds, XIBs, plist, etc) into one single place. And this is also for that teams that want to work together above the same base (framework).
Framework on iOS? Really?
top
Ok buddies, let’s make something clear, many people had said:”iOS doesn’t support custom Frameworks!”, “Custom Framework is not allowed at iOS!”, “Doesn’t exist custom Framework on iOS!” and many other discouraging things like these. Look, I’ve made many frameworks and worked with many others, I don’t believe that is really impossible to use a Framework on iOS. According to my experience and knowledge about Frameworks, it’s absolutely feasible a custom Framework on iOS Devices. If we think more about this issue we can find an elegant solution, right? First, let’s understand what a Framework really is, here is the definition of framework by Apple’s eyes:
A 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.
Doesn’t make many sense something with this description not be allowed in iOS, thinking in architecture and structure. Apple also says:
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.
Good, now thinking about iOS security, performance and size, the only thing in a Framework definition which doesn’t fit in iOS technology is the “dynamic shared library”. The words “dynamic” and “shared” are not welcome in the iOS architecture. So the Apple allows us to work and distribute something called “Static Library“. I don’t like it! It’s not so easy as a Cocoa Framework, if a developer got your Static Library, he needs to set a header path too, or import the header files… it’s not useful, that’s a shit!
Well, so a Framework concept is absolutely compatible with iOS, except by the “dynamic shared library”, on the other hand Apple says that a “static library” is OK for iOS. So if we replace the “dynamic shared libraries” by a “static library” we could construct a Custom Framework to iOS, right?
Right!!!!
This is exactly what we’ll make in this article, let’s construct a Framework with Static Library, by the way, an Universal Framework.
Understanding Universal, Dynamic and Static concepts
top
Simple answer:
- Universal: Which works perfect on all architectures. iOS devices uses armv6 and armv7, iOS simulator on MacOS X uses i386.
- Dynamic: The compiler doesn’t include the target files directly. The classes/libraries are already pre-compiled (binary format) and lies on the system path. Besides, the dynamic libraries can be shared by many applications. This is exactly what Cocoa Framework is.
- Static: It represents that classes/libraries which is compiled by the compiler at the build phase. These files can’t be shared by other applications and relies on application path.
Simple as that. If you need more informations about Dynamic VS Static libraries, try this Apple’s Documentation.
No more concepts, hands at work!
Constructing a Framework Project
1. Create the Project:
top
I want to show you step by step of the entire process, so let’s start with the most basic, create an iOS project. You can choose one application template in Xcode, this is not really important, but remember to choose one template which could test your Framework code before export it.
2. Framework Classes:
Remember to create an “import header” to make everything simpler and organized to the user of your framework. Remember to write this header file with a framework notation, just as shown in the image bellow. Also remember to create your classes taking care to hide the classes which should not be visible to the other developers (users of your framework). We will set the public and private headers soon, but it’s very important to you protect the “core” classes, I mean, that classes which you don’t want to make visible to other developers.
For those private classes, you could import their header inside the “.m” (or .mm, .cpp, etc) file of a public class, by doing this you protect the header of private classes. Well, I know you probably already know that, I’m saying just to reinforce.
Remember that organization is 90% of a good framework, so try follow all the Apple advices to create your classes names, methods, properties, functions, etc.
Creating the Framework
3. Create a Framework Target:
top
OK, let’s create a target to compile our framework. Click on the icon of your project in the project navigator at the left and hit the button “Add Target”. A new window will come up. Now is our first trick. Instead to create a “Cocoa Touch Static Library” or a “Cocoa Framework” we will create a “Bundle” target.
A Bundle? Really? Yes! I can explain. 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”, so we can’t use this target. On the other hand, we can’t use “Cocoa Touch Static Library” either, because it doesn’t use the framework structure that we want.
Now, the Bundle target could be the best choice. It can hold any file we want, we can compile source code inside it and… we can turn it into a framework. To say the truth, almost all “Framework & Library” targets could be turned into a framework too, even the “Cocoa Touch Static Library”, throughout this article you probably will figure out how. For now, let’s create a Bundle target.
4. Bundle Setup:
top
It’s time to make all the necessary changes to the Bundle target. Different than the old tutorial. You don’t need to clean up anything. Just know that everything else will be ignored (linked frameworks .plist files, .pch etc…).
I’m sure you already know this, but just to reinforce, here is the Build Setting screen, you can find it by clicking on the project icon in the left project navigator and then clicking in the “Build Setting” tab.
Here is our second great trick, or should be better to say “tricks”. Let’s change the “Build Setting” following this list:
- Base SDK: Latest iOS (iOS X.X) (in the X.X will appear the number of the lastest iOS SDK installed on your machine).
- Architectures: $(ARCHS_STANDARD_32_BIT) armv6 (it’s very important to be exactly this value including the space before “armv6″) This setting is valid to Xcode 4.2, if you are using an old version, use the “Standard (armv6 armv7)” option. (the values for this property depend on the value of the item bellow, so set that first).
- Build Active Architecture Only: NO (otherwise we can’t compile to armv6 and armv7 at the same time).
- Valid Architecture: $(ARCHS_STANDARD_32_BIT) (it’s very important to be exactly this value). If your Xcode is showing two lines with armv6 and armv7, delete then and insert this value in one single line.
- Dead Code Stripping: NO.
- Link With Standard Libraries: NO.
- Mach-O Type: Relocatable 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: This setting is not mandatory, but if you are planning to use any kind of C++ code (.cpp or .mm) on this framework, Chris Moore (on the comments) advises to use the “-lstdc++” option. In this case could be a good idea to use “-ObjC” too, to avoid conflicts in old compilers.
- Wrapper Extension: framework. Here we change the Bundle to a Framework. To Xcode, frameworks is just a folder with the extension .framework, which has inside one or more compiled binary sources, resources and some folders, a folder, usually called Headers, contains all the public headers.
- Generate Debug Symbols: NO (this is a very important setting, otherwise the framework will not work on other computers/profiles).
- Precompile Prefix Header: NO.
- Prefix Header: “”. (Leave it blank).
IMPORTANT: Since the Xcode 4.x the architectures armv6 has no longer support. So, to create a real Universal Framework we must make a small “hack”:
- After change the settings above close the Xcode, find the .xcodeproj (the project file) in Finder and then “Show Package Contents”.
- Open the file “project.pbxproj” into a text editor.
- Delete all the lines with VALID_ARCHS = “$(ARCHS_STANDARD_32_BIT)”.
5. Adding code and resources to the Bundle (Framework)
top
It’s time to place the content in our framework and define the public headers. To do that, with the Bundle target selected, click on the “Build Phase” tab. At bottom, hit the button “Add Phase” and then “Add Copy Headers“.
Open the recently created “Copy Headers” section and separate your public headers from the private or project headers. The difference here is:
- Public: Headers that other developers must know in order to work with your framework. In the final framework product, these headers will be visible even to Xcode.
- Private: Headers that is not necessary to other developers, but is good for consult or for reference. These headers will not be visible to Xcode, but will be in the framework folder.
- Project: Headers that the other developers nor Xcode have access. In reality these headers will not be placed in the final product, this is just to instruct the compiler to create your custom framework.
Now, open the “Compile Source” section and put there all your .m, .c, .mm, .cpp or any other compilable source file.
If your framework include not compilable files, like images, sounds and other resources, you can place them in the “Copy Bundle Resources” section. Later, when we generate the final framework, all your resources will be placed in a folder called “Resources”, but you can change it. That folder is very important, because it will be part of the path to retrieve your resources from the framework product.
Tip: To add many files at once, click on the “+” button and write the files’ extension on the search field. For example “.m”, “.c”, “.cpp”, “.h”, etc. This can save a lot of time.
This is how your “Build Phase” will looks like:
Building the Universal Framework
6. Creating Universal Target:
top
To join both architectures products into one, we must to use the Lipo Tool. It’s a tool which comes with iOS SDK, just to know, it is in “
Add a new target, hit the “Add Target” button, just as you did with Bundle Target. At this time a good choice is the “Aggregate” target. It doesn’t create any product directly, its purposes is just to aggregate another targets and/or run some scripts, exactly what we want! To use the Lipo Tool we’ll need to create a “Run Script” at the “Build Phase“.
7. Lipo Tool Script:
top
This will be our greatest trick. The following script will make everything we need. It will compile the Framework Target to iOS Device and Simulator at once, will merge them with Lipo tool and will organize a good Framework Bundle structure.
Copy and paste this on your “Run Script” phase:
| Xcode Script to Lipo Tool |
|---|
# Sets the target folders and the final framework product.
FMK_NAME=FI
FMK_VERSION=A
# Install dir will be the final output to the framework.
# The following line create it in the root folder of the current project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
# Working dir will be deleted after the framework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
# Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator
# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
# Creates and renews the final product folder.
mkdir -p "${INSTALL_DIR}"
mkdir -p "${INSTALL_DIR}/Versions"
mkdir -p "${INSTALL_DIR}/Versions/${FMK_VERSION}"
mkdir -p "${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources"
mkdir -p "${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers"
# Creates the internal links.
# It MUST uses relative path, otherwise will not work when the folder is copied/moved.
ln -s "${FMK_VERSION}" "${INSTALL_DIR}/Versions/Current"
ln -s "Versions/Current/Headers" "${INSTALL_DIR}/Headers"
ln -s "Versions/Current/Resources" "${INSTALL_DIR}/Resources"
ln -s "Versions/Current/${FMK_NAME}" "${INSTALL_DIR}/${FMK_NAME}"
# Copies the headers and resources files to the final product folder.
cp -R "${DEVICE_DIR}/Headers/" "${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/"
# Removes the binary and header from the resources folder.
rm -r "${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/Headers" "${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/${FMK_NAME}"
# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}"
rm -r "${WRK_DIR}"
Now build the Aggregate target. Doesn’t matter you build for iOS Device or Simulator, this script will create a working folder, compile the framework target twice in there (device + simulator) and will output a folder called “Products” located in the project root folder. There is your Universal Framework to iOS!
Congratulations!
Importing your Universal Framework
8. Importing:
top
To test your Universal Framework, create a new Xcode project, select the Application target and go to “Build Phase” tab. Open the section “Link Binary With Libraries” and hit the “+” to add a new Framework. Click the “Add Other…” button and select your Universal Framework. Remember, you must to select the “.framework” folder. Remember to import your Framework Principal Header as a framework notation. Xcode will use your public headers in the Code Completion.
Let’s understand what happens until here:
When we set the “Mach-O Type” to “Relocatable Object File” the Xcode understand that everything related to that package will be like a “Binary Archive” like a ZIP. But that archive must be compiled again in new projects.

Then, when we create a Framework Bundle structure, Xcode understand that everything inside it is organized in folders like “Headers” and
Now, to retrieve the resources, make use of the main bundle, just as you are used to:
| Framework Bundle |
|---|
[[NSBundle mainBundle] pathForResource:@"FI.framework/Resources/FileName"
ofType:@"fileExtension"];
Conclusion
top
Well done, my friends! As we are used, let’s make a final review and take care with some possible problems.
- In a common Xcode project, create a Bundle target.
- Make the necessary setup, place your sources, headers and resources in it.
- Create an Aggreate target and place a Run Script in it.
One last advice: Take care with your classes structure. If you set, for example, the ClassB.h as a Project or Private header, but in your code you import it into a Public header, this will cause conflicts.
And one last tip: Notice in the sample project I removed the scheme for the “Bundle Target”. We don’t need that scheme any more, because the new script will manage the compilation to us.
That’s all, buddies.
Enjoy your Framework to iOS!
Thanks for reading,
See you soon!








Pingback: Creating Universal Framework to iPhone iOS
Thanks for this article my friend .. Will try it out and disturb you if in case of queries
Diney nice work. I was able to get your first version to work. I was going through this version, in step 4, I was unable to find “Generate Debug Symbols” in the build settings. I am using Xcode 4.0.2.
Hello buddy,
Thanks,
“Generate Debug Symbols” is under “ – Code Generation”, that means, if you are using LLVM compiler 2.0 it will be under “LLVM compiler 2.0 – Code Generation”.
You can also insert “generate debug symbols” in the search box.
Interesting when I was doing this the first time I used the search box, looking for various forms of Generate Debug Symbols, but nothing showed up. After building it once, I was able to find it. Might be the same issue that editing “Architectures” has if you have not already edited “Base SDK” first.
BTW you might want to switch the order of those two, it works much better that way.
I was unable to get the build script to work. Note I did went through the tutorial and did not download the project.
It is pretty obvious that it is a debug/release issue. Since this version does not use schemes, I was wondering how to tell the compile to build release not debug. This might have to do with the previous post.
Xcode reported:
cp: build/Release-iphoneos/CPTUI.framework/Headers/: No such file or directory
cp: build/Release-iphoneos/CPTUI.framework/: No such file or directory
rm: /Users/mmorris/devl/objc/CPT/CPTUI/Products/CPTUI.framework/Versions/A/Resources/Headers: No such file or directory
rm: /Users/mmorris/devl/objc/CPT/CPTUI/Products/CPTUI.framework/Versions/A/Resources/CPTUI: No such file or directory
Well, when you set “Generate Debug Symbols” to NO this issue should be solved.
Besides, you can change “${CONFIGURATION}” key-word to “Release”. This will solve the problem securely.
Just noticed that you updated your script by changing “${CONFIGURATION}” to “Release”
xcodebuild -configuration “${CONFIGURATION}” -target “${FMK_NAME}” -sdk iphoneos
xcodebuild -configuration “${CONFIGURATION}” -target “${FMK_NAME}” -sdk iphonesimulator
to:
xcodebuild -configuration “Release” -target “${FMK_NAME}” -sdk iphoneos
xcodebuild -configuration “Release” -target “${FMK_NAME}” -sdk iphonesimulator
——————————————————–
Do you know how to set ${CONFIGURATION} from Xcode? If so you could have made the following changes:
DEVICE_DIR=${WRK_DIR}/${CONFIGURATION}-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/${CONFIGURATION}-iphonesimulator/${FMK_NAME}.framework
# Building both architectures.
xcodebuild -configuration “${CONFIGURATION}” -target “${FMK_NAME}” -sdk iphoneos
xcodebuild -configuration “${CONFIGURATION}” -target “${FMK_NAME}” -sdk iphonesimulator
——————————————————–
The question is probably mute because we don’t gain anything from have a Debug version.
hehehe
You answered your question by yourself.
There is no point on creating a Debug Framework. This is why we turned off “Generate Debug Symbols”.
Statement 1 in the FAQ
Can I use this Framework as a Bundle to store my files, XIBs, images?
A: Yes, you can and now it’s very very easy to retrieve your files.
Caused me some confusion which I notice others shared in the first version.
My framework is a UI framework which has images in it for buttons. The framework directly uses the images. I believe this is different than what you are stating that you can create a framework with images that external code can use.
I was able to include images into my framework that my framework uses by using:
/usr/bin/xxd -i image.png image.png.h
and
#import “image.png.h”
UIImage *image = [[UIImage imageWithData: [NSData dataWithBytesNoCopy: image_png length: image_png_len]] retain];
[image releas];
Yes,
This new approach give u an easy way to export any non-compilable file and let them visible to the users of your framework.
Great stuff!! Thanks a lot!
Okay all is working. Again well done Diney. Only change that I made to the script was to keep all of the intermediate files together.
from:
WRK_DIR=build
xcodebuild -configuration “Release” -target “${FMK_NAME}” -sdk iphoneos
xcodebuild -configuration “Release” -target “${FMK_NAME}” -sdk iphonesimulator
to:
WRK_DIR=${SYMROOT}/${TARGET_NAME}
xcodebuild -configuration “Release” -target “${FMK_NAME}” -sdk iphoneos SYMROOT=”${WRK_DIR}”
xcodebuild -configuration “Release” -target “${FMK_NAME}” -sdk iphonesimulator SYMROOT=”${WRK_DIR}”
Followed step by step and downloaded sample code (several times) under XCode 4.0.2. But when I import the general header file, it always fails, ie:
#import
Produces the error:
FI.h: No such file or directory
Otherwise, your sample and my application attempts all seem to compile and produce the expected output, but cannot include it in any of my projects successfully.
Hi james,
Remember to check the box of “Add to target” when importing new files, otherwise Xcode can’t link the file with the target.
Secondly, remember you must import any other framework referenced by your code.
it’s great idea.. I created the framework and all looks great. I changed the install location to ~/Library/Frameworks in the shell script
but when I imported the framework to another project
the linker fails with
ld: framework not found xxxx
Command /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang failed with exit code 1
This is a typical problem w debug symbols. Make sure you turn off this option on step 4
thanks!! it resolved!!!
Great job man….created the Framework but
I tried everything out and even downloaded the demo but wont work in Xcode 4.2.3
still getting
ld: framework not found FRapp
Command /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang failed with exit code 1
Pingback: Is a Dynamically Linked Framework possible on iOS? | Technical support, Computer, programming issue, issue tracking, quality assurance
I’m very pleased with you tutorial, but I’m having a hard time with something and thought you or someone else might be able to help. I’m trying to include a third party library and make calls to that library within the framework project and then use the framework in my main project. First I’d like to know if this is possible as I haven’t been successful, and two if it is possible how to best accomplish it. I have heard that dynamically linked libraries is not allowed, but aside from Apple’s rule, is it possible to link libraries within frameworks in xcode? I appreciate anyone’s input. Thanks!
Hi my friend,
Let’s go to your questions:
1 – You can link another frameworks and libs in your “custom framework” code, however you must to import the same framework/lib in your main project because you can’t use dynamical links in iOS.
2 – It’s not just an Apple’s rule. The iOS works with sandbox concept, which each APP has its own sandbox. One sandbox can’t share any kind of code with another one and you can’t install anything directly in the device’s “hard drive”. This is why you can’t use dynamical frameworks/libs on iOS, there is no “shared sandbox” on iOS. Some guys, hackers like the Jailbreak’s creators, have broken this sandbox security, however this “jail-break” is specific for each device. So to use a kind of dylib on iOS you must break the device’s security and break the Xcode’s compiler (some text files of configuration).
Sincerely, in my opinion… Don’t try it… it’s so much work for nothing. Try to think inside the Apple’s path, follow the device’s rules and you can make great things. Remember that there are reason for that kind of security, when you break it, your APP becomes more vulnerable.
Pingback: Créer un framework pour iOS | Coding artist
Life was good until I made a change to one of my classes (project structure has not changed) and I now I get the following error when I try to link with the framework for a device target (the simulator target links without issue).
Assertion failed: (atom->fixupCount() == 1), function targetCString, file /SourceCache/ld64/ld64-123.3/src/ld/parsers/macho_relocatable_file.cpp, line 4831.
0 0×13886 __assert_rtn + 86
1 0x2dfd8 mach_o::relocatable::PointerToCStringSection::targetCString(mach_o::relocatable::Atom const*, ld::IndirectBindingTable const&) const + 280
2 0x2b27c mach_o::relocatable::PointerToCStringSection::contentHash(mach_o::relocatable::Atom const*, ld::IndirectBindingTable const&) const + 76
3 0x2c57f mach_o::relocatable::Atom::contentHash(ld::IndirectBindingTable const&) const + 47
4 0xae870 ld::tool::SymbolTable::findSlotForReferences(ld::Atom const*, ld::Atom const**) + 704
5 0xb21dc ld::tool::Resolver::convertReferencesToIndirect(ld::Atom const&) + 268
6 0xb33f2 ld::tool::Resolver::doAtom(ld::Atom const&) + 642
7 0x21f7c mach_o::relocatable::File::forEachAtom(ld::File::AtomHandler&) const + 60
8 0xaa29e ld::tool::InputFiles::forEachInitialAtom(ld::File::AtomHandler&) const + 46
9 0xb5924 ld::tool::Resolver::resolve() + 84
10 0x14ff7 main + 871
11 0x1d95 start + 53
collect2: ld returned 1 exit status
Command /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2 failed with exit code 1
Well buddy…
By the error, seems your code in that class is not well written, actually, a C code.
I’ve saw this error before, but it just happen when you broke the C pattern, like when you try to initialize a static variable with a default value. When the compiler exit with code 1, this is always a code problem.
Do you have a test target in you framework project? It’s very important that you have one. Before to compile your framework, make sure your code is running OK .
to clarify … The change was in a class in the framework. Neither the framework or app project structures have changed. The error occurred when linking the app.
The issue was a bug in the linker under Xcode 4.0.2. Under Xcode 4.1 links without issue.
Nice!
Excellent tutorial! I have been able to get classes instantiated, as well as get images and other resources OK. The one issue I have is that I load XIBs that have references to images, for example, and the cannot load:
Could not load the “66-microphone.png” image referenced from a nib in the bundle with identifier “com.waynehartman.FrameworkConsumer”.
How do I specify in the XIB that it should load that image resource from its own bundle, and not that of the Main Bundle? I’d really prefer to avoid having to create the XIB in each project, or have an extra copy of its images imported into my consuming project. Any ideas would be welcome.
So I was able to get it to work if I referenced the resource inside the XIB using the resource path prefix that you mention at the end of the article, but then I cannot view the images in IB. Any other workaround that you can suggest?
Well, I’m not sure.
I need to make some tests here with images inside the XIB.
I’ll reply you as soon as possible.
Thank you great job
warning: (i386) /Users/dnssnd/Documents/CAFE/CAFELibrary/build/CAFELibrary.build/Release-iphonesimulator/lib.build/Objects-normal/i386/SampleA.o unable to open object file
warning: (i386) /Users/dnssnd/Documents/CAFE/CAFELibrary/build/CAFELibrary.build/Release-iphonesimulator/lib.build/Objects-normal/i386/SampleA.o unable to open object file
I followed your instruction i got the above error
hey buddy,
The i386 is the simulator architecture and the .o files are always related to the debug symbols.
So your problem is probably related to the debug symbols generation.
Did u tried the sample project?
http://db-in.com/downloads/framework-ios.zip
Cheers,
I was able to build the framework now
If i try to include the class files in the framework i get class not found error
Found it out !!!!
we have to include #import
sampleframework is name of the framework
classname is the name of the class
Thank you so much Diney Bomfim Finally learnt to build a framework properly
Nice!
You’re welcome.
I have an issue with Xcode 4.2 and the framework recipe. The issue is the result of Xcode 4.2 and its default behavior to only build for armv7 and not armv6 & armv7.
I assume the framework’s build settings need to be changed
Architectures: i386 armv6 armv7
Valid Architecture: $(ARCHS_STANDARD_32_BIT)
However the frame work only has armv7 and i386
I tried:
Architectures: i386 armv6 armv7
Valid Architecture: armv6 armv7
Architectures: i386 armv6 armv7
Valid Architecture: i386 armv6 armv7
And both fail to build.
Hi Morris,
I had the same issue here… very simple to solve:
just add a line with the “armv6″ option bellow the “$(ARCHS_STANDARD_32_BIT)” on the “Architectures” option.
Tried that …
Architectures: $(ARCHS_STANDARD_32_BIT) armv6 (selected other added a line with $(ARCHS_STANDARD_32_BIT) and a line with armv6)
Valid Architecture: $(ARCHS_STANDARD_32_BIT)
nm -a CPTUI.framework/CPTUI | grep arch
CPTUI.framework/CPTUI (for architecture armv7):
CPTUI.framework/CPTUI (for architecture i386):
in Valid Architectures u don’t need to use $(ARCHS_STANDARD_32_BIT) anymore.
Just one line with armv6 and another one with armv7.
Make sure the “Build Active Architecture Only” is set to NO.
Compiler LLVM GCC 4.2 or Apple LLVM 3.0
Architectures:
$(ARCHS_STANDARD_32_BIT)
armv6
Valid Architecture:
armv6
armv7
Build Active Architecture Only: No
————————————————-
=== BUILD NATIVE TARGET CPTUI OF PROJECT CPTUI WITH CONFIGURATION Release ===
Check dependencies
[BEROR]No architectures to compile for (ARCHS=i386, VALID_ARCHS=armv6 armv7).
** BUILD FAILED **
So … I made one change …
Valid Architecture:
i386
armv6
armv7
————————————————-
builds but …
I do not see any thing for armv6 in the Log Navigator and …
nm -a CPTUI.framework/CPTUI | grep arch
CPTUI.framework/CPTUI (for architecture armv7):
CPTUI.framework/CPTUI (for architecture i386):
Ignore the other post at this level as I made a mistake. This is the correct one …
Architectures:
$(ARCHS_STANDARD_32_BIT)
armv6
Valid Architecture:
armv6
armv7
Build Active Architecture Only: No
————————————————-
=== BUILD NATIVE TARGET CPTUI OF PROJECT CPTUI WITH CONFIGURATION Release ===
Check dependencies
2011-10-14 14:47:50.910 xcodebuild[2397:3f03] error: Error Domain=NSPOSIXErrorDomain Code=2 UserInfo=0x200772ca0 “Non-zero exit code 255 returned from shell command: /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2 -v -E -dM -arch armv6 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk -x objective-c -c /dev/null 2>&1″
2011-10-14 14:47:50.914 xcodebuild[2397:3f03] Warning: Couldn’t discover the ‘llvm-gcc-4.2′ compiler’s built-in search paths and preprocessor definitions for language dialect ‘objective-c’.
Compiler: /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2
Reason: /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2 -v -E -dM -arch armv6 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk -x objective-c -c /dev/null 2>&1
CompileC /Users/mmorris/Library/Developer/Xcode/DerivedData/CPTUI-ezjrxybxyybadxguvscgaqtaelju/Build/Products/Universal/CPTUI.build/Release-iphonesimulator/CPTUI.build/Objects-normal/armv6/CPTDatePickerInputView.o CPTUI/Source/CPTDatePickerInputView.m normal armv6 objective-c com.apple.compilers.llvmgcc42
cd /Users/mmorris/devl/objc/CPT/CPTUI
setenv LANG en_US.US-ASCII
setenv PATH “/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin”
/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2 -x objective-c -arch armv6 -fmessage-length=0 -pipe -std=gnu99 -Wno-trigraphs -fpascal-strings -Os -Wreturn-type -Wunused-variable -Wshorten-64-to-32 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk -fexceptions -mmacosx-version-min=10.6 -fobjc-abi-version=2 -fobjc-legacy-dispatch -D__IPHONE_OS_VERSION_MIN_REQUIRED=40200 -iquote /Users/mmorris/Library/Developer/Xcode/DerivedData/CPTUI-ezjrxybxyybadxguvscgaqtaelju/Build/Products/Universal/CPTUI.build/Release-iphonesimulator/CPTUI.build/CPTUI-generated-files.hmap -I/Users/mmorris/Library/Developer/Xcode/DerivedData/CPTUI-ezjrxybxyybadxguvscgaqtaelju/Build/Products/Universal/CPTUI.build/Release-iphonesimulator/CPTUI.build/CPTUI-own-target-headers.hmap -I/Users/mmorris/Library/Developer/Xcode/DerivedData/CPTUI-ezjrxybxyybadxguvscgaqtaelju/Build/Products/Universal/CPTUI.build/Release-iphonesimulator/CPTUI.build/CPTUI-all-target-headers.hmap -iquote /Users/mmorris/Library/Developer/Xcode/DerivedData/CPTUI-ezjrxybxyybadxguvscgaqtaelju/Build/Products/Universal/CPTUI.build/Release-iphonesimulator/CPTUI.build/CPTUI-project-headers.hmap -I/Users/mmorris/Library/Developer/Xcode/DerivedData/CPTUI-ezjrxybxyybadxguvscgaqtaelju/Build/Products/Universal/Release-iphonesimulator/include -I/Users/mmorris/Library/Developer/Xcode/DerivedData/CPTUI-ezjrxybxyybadxguvscgaqtaelju/Build/Products/Universal/CPTUI.build/Release-iphonesimulator/CPTUI.build/DerivedSources/armv6 -I/Users/mmorris/Library/Developer/Xcode/DerivedData/CPTUI-ezjrxybxyybadxguvscgaqtaelju/Build/Products/Universal/CPTUI.build/Release-iphonesimulator/CPTUI.build/DerivedSources -F/Users/mmorris/Library/Developer/Xcode/DerivedData/CPTUI-ezjrxybxyybadxguvscgaqtaelju/Build/Products/Universal/Release-iphonesimulator -F/Users/mmorris/devl/objc/CPT/CPTUI/lib -c /Users/mmorris/devl/objc/CPT/CPTUI/CPTUI/Source/CPTDatePickerInputView.m -o /Users/mmorris/Library/Developer/Xcode/DerivedData/CPTUI-ezjrxybxyybadxguvscgaqtaelju/Build/Products/Universal/CPTUI.build/Release-iphonesimulator/CPTUI.build/Objects-normal/armv6/CPTDatePickerInputView.o
Command /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/llvm-gcc-4.2 failed with exit code 255
and those errors came from the
xcodebuild -configuration “Release” -target “${FMK_NAME}” -sdk iphonesimulator SYMROOT=”${WRK_DIR}”
part of the build script, the
xcodebuild -configuration “Release” -target “${FMK_NAME}” -sdk iphoneos SYMROOT=”${WRK_DIR}”
worked with both armv6 and armv7 parts
the arch was armv6 … would have expected i386
Do you have the iOS SDK 4 and 3 on your machine?
Here I had to download and install them.
Sorry not sure what you are asking. Are you talking about … from the Xcode menu:
Xcode –> Preferences –> Downloads
If so, I have “iOS 4.3 Simulator” installed.
“iOS 4.0 – 4.2 Device Debugging Support” and “iOS 3.0 – 3.2.2 Device Debugging Support” are not installed.
Yep,
So maybe you need to install them.
Check on your folder:
/Developer/Platforms/iPhoneOS.platform/Developer/ and see what SDKs you have.
iOS 5 doesn’t use armv6 anymore…
ls -la /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/
drwxr-xr-x 8 root wheel 272 Sep 20 02:26 iPhoneOS5.0.sdk
ls -la /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/
drwxrwxr-x 8 root admin 272 Mar 30 2011 iPhoneSimulator4.3.sdk
drwxr-xr-x 8 root wheel 272 Oct 12 17:15 iPhoneSimulator5.0.sdk
Yeah I am pretty sure Xcode 4.2 can build armv6, as I have built simple apps and ran them directly on an iPhone 3G. That was fun getting that to work — seem my answer at http://stackoverflow.com/questions/7760946/possible-to-target-older-ios-versions-when-using-xcode-4-2-and-ios-5-sdk/7762979#7762979
But back to this … The last suggestion looked like it compiled armv7 and armv6, but when it was compiling for the iphonesimulator it had armv6 in the compiler commands (see #40 above) I would have expected i386. Send me an email (think you have it when I signed up here) and I will send you a stripped down version of the project.
Yes,
Xcode 4.2 can compile to armv6. I’m compiling NinevehGL to armv6 right now.
Let me see your project. I’ll send u an email.
cya
First off I want to say thanks for Diney for helping me resolve the issue with Framework recipe and Xcode 4.2 posts 35-47.
Just in case anyone else out there has the same problem I will summarize the solution.
The build settings for:
Architectures: click other and type:
$(ARCHS_STANDARD_32_BIT)
armv6
Valid Architectures: $(ARCHS_STANDARD_32_BIT)
build the framework
test to make sure all three architectures are there by running:
nm -a .framework/ | grep arch
make sure you see three lines, one with armv7, armv6, and i386.
If armv6 is missing, close Xcode, find the project in finder, show the contents of the .xcodeproj, open the file project.pbxproj, delete the two lines with VALID_ARCHS = “$(ARCHS_STANDARD_32_BIT)”
Thanks again for the help.
the nm line did not come out correctly
nm -a name.framework.name | grep arch
You’re welcome, bro!
But if I want to debug into this framework, what should I do? Should I make another debug version framework?
Thanks~
Hello Leira.
If you want to debug you can generate another target, like a unit test or an application test, in the same project and test your code.
The framework only makes sense for release version, because its purpose is to share your code without expose the .m files (or .mm, or .cpp)
This is the reason of the “Release” configuration.
But, if you want to take advantage of some “Debug” macros and specs, just set it in the script. But as I said, there is no purpose in that.
Cheers,
Hi Diney,
First of all, I would like to say “Nice work on your framework tutorial! This is truly good stuff.”.
Now for a little trouble shooting.
I was able to create a framework and use it with ease if it only had Objective-C code in it. However, once I added any .cpp or .mm (C++) code to my framework, the framework would build fine but the project that included the framework would complain about “undefined symbols” in the C++ code. The code itself has no issues as I have used it outside of a framework in other projects in the past. See error snippet below for an example of the error I’m getting in my project that includes the framework. Is there a “magic” setting that I’m missing in my build settings? Any ideas?
Undefined symbols for architecture i386:
“std::terminate()”, referenced from:
PalSpeechRecordSiren7::PalSpeechRecordSiren7() in MSAudio
PalSpeechRecordSiren7::~PalSpeechRecordSiren7() in MSAudio
“vtable for __cxxabiv1::__class_type_info”, referenced from:
typeinfo for IPalObject in MSAudio
typeinfo for IPalAudioService in MSAudio
typeinfo for IPalSpeechService in MSAudio
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
“vtable for __cxxabiv1::__si_class_type_info”, referenced from:
typeinfo for PalAudioCodec in MSAudio
typeinfo for PalAudioCodecSiren7 in MSAudio
typeinfo for PalAudioService in MSAudio
typeinfo for PalSpeechRecord in MSAudio
typeinfo for PalSpeechRecordGsm610 in MSAudio
typeinfo for PalSpeechRecordSiren7 in MSAudio
typeinfo for PalSpeechService in MSAudio
…
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Hi bro,
Few time ago, I had a similar problem… but the problem was with the C++ code, because there is no real restriction or anything that could generate an error like this in this framework approach.
Just to let you know, I’ve used that C++ code in many other projects too and always worked fine… however, just inside the framework the real problem comes up.
So I was pretty sure that the problem was not with my code… however I was wrong… the problem was the code.
I suggest you to create a blank (or almost blank) .mm/.cpp file and test the framework with it.
Anyway, I’ll try to simulate the same error here using C++ files and reply to you soon.
Cheers,
Thanks Diney! Your reply was very fast. I’m simply impressed by your devotion to help people with problems that they come across when following your tutorial. Not a lot of people do that. Thank you.
Additional info:
The bug shows as an “Apple Mach-O Linker (Id) Error”.
Try something like operator overloading… the compiler seems to complain about those as well.
The code in question here was written in 1997 and has been used in a lot of projects since the time it was written. I’m not saying that it is impossible that something is wrong with this code, just seems unlikely.
Additionally am I’m getting things like:
Unknown type name ‘class’; did you mean ‘Class’?
and
Unknown type name ‘namespace’
Seems like it’s not recognizing that the code is C++. The cpp files have a .cpp extension.
Hi William,
In my tests, I got the same error:
“”Apple Mach-O Linker (Id) Error”
“Undefined symbols for architecture i386:
“_defaultTest”, referenced from:
_globalTest in Test.o
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status”
However it compiles pretty fine if I just use the code directly instead of creating the framework.
This happened because I’d created two unambiguous definition, creating a duplicated global variable, without make use of the “extern” keyword.
This error also happened when I created a referenced global variable (using “extern” keyword), but never really defined the global one.
Well, It’s hard to say something, because that error can be generated by hundreds of problems. Problems that never appear outside the framework.
Besides, the new compilers can interpreter the code following new rules, some of them that could be a new good practice to old codes. What compiler are you using?
It’s really hard to say without see the code. If you send me the code, or a part of it, I could try to help you more.
Unfortunately I’m not allowed to share the actual code. However, I did build a very simple test project and framework that I can share with you that has the same problems. I’ve compressed the framework and test project into a zip file. Where would you like me to send them?
diney@db-in.com
Sent. Thanks again.
It turns out that you may need to add “-lstdc++” to the “Other Linker Flags” in the build settings of your project that uses your custom framework.
Additionally it seems that you can mix .cpp and .m/.mm header files in your framework header file.
After I made those changes, everything works.
Excellent tutorial. And the activity on this thread is great, thanks Willian for the -lstdc++ flags setting, saved me trouble as soon as I hit the problem.
I’m creating a framework which then relies on a bunch of static libs that are compiled for ARM or for the Simulator.
I have to look into it, but any quick clues on how I can put these into the framework? Or would I distribute them alongside the framework..
Cheers
Thank you buddy,
Until now, I didn’t find a way to compile another libs/frameworks inside this framework approach. Actually, I think this is not possible. Any code to iOS must be compiled when you compile the final APP. This framework approach that I shown is just a way to “pre-compile” some amount of code. It’s not a real framework, which support many libs inside it.
But if you find a way, please, let me know.
Regards,
I’m getting the following errors with Generate Debug Symbols OFF, anyone knows how i can resolve this?
Thanks.
‘Cocoa/Cocoa.h’ file not found
Cp: build/Release-iphoneos/MyFramework.framework/Headers/: No such file or directory
Rm: /Users/freak4pc/Work/MyFramework/MyFramework/Products/MyFramework.framework/Versions/A/Resources/Headers: No such file or directory
Rm: /Users/freak4pc/Work/MyFramework/MyFramework/Products/MyFramework.framework/Versions/A/Resources/MyFramework: No such file or directory
Build task claims to succeed in spite of generating error messages
Hi Shai,
Are you importing the external frameworks into your new project?
Remember that this framework approach doesn’t give support to external frameworks in it.
Judging by the error, seems the framework was not compiled properly, check the final framework folder and see if the files you are compiling are really there.
Every time that the framework can’t be compiled, it’s always because one of the settings in the step 4.
Cheers,
The problem was it tried to import Cocoa.h which is Mac only , i removed that import and added UIKit.h instead and it worked correctly and built with no errors, ill now try importing the framework and test it to hope its working
Thanks!
I got this when trying to use the frameowk:
Undefined symbols for architecture armv7:
“_OBJC_CLASS_$_CLLocation”, referenced from:
objc-class-ref in Dropico
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I guess its because i forgot to add CoreLocation.framework, but i added it now and still getting that error, Any ideas?
Take a look at the comment #48
http://db-in.com/blog/2011/07/universal-framework-iphone-ios-2-0/#comment-3537
Cheers,
Thanks again Diney
Unforuntately i couldn’t get it to work for me …
Re-compiled with armv6 and its still looking for CoreLocation even though its compiled into the Frameowkr…
Also i tried running this : ‘nm -a name.framework.name | grep arch’ but wasn’t exactly sure what to do there (nm -a Myframework.framework didn’t work …)
Thanks again
Hey buddy,
I can’t figure out what is happening.
I suggest you to try the sample project (http://db-in.com/downloads/framework-ios.zip) and see what happens.
If you still with troubles, please send me the sample with your changes.
Cheers,
Ok i got the info and managed to compile it on armv6 as well but it doesn’t solve the problem , still same error, only thing that works is adding CoreLocation.framework to the target project as well, but its a bit of hassle… Theres no way to include in my own framework?
Wait wait wait….
Didn’t you include the CoreLocation again on your new project?
Oh dude… I told you before, in the FAQ above. This framework approach doesn’t work at this way, it can’t be used to pre-compile other frameworks, it’s not allowed on iOS.
This framework approach is just to compile you very OWN code, not the code inside other libs or frameworks.
In fact, you don’t need to include the CoreLocation framework when you are compiling your own framework. You just need to reference it in your code (“#import <CoreLocation/CoreLocation.h>”).
The most important thing is that you must include the CoreLocation framework in the final project (the APP project).
For example, if your custom framework uses the UIKit, CoreGraphics and CoreVideo inside the code, the project that will use your custom framework must include those 3 frameworks.
Yeah i guessed thats the deal ,
This is my first time with this process and your tutorial was extremely helpful!
Thank you Diney and sorry for being so much trouble
You’re welcome buddy.
Thank you, I’m glad to help.
You’re not a trouble. If you have more questions, please, post.
Cheers,
Also , could you clarify abit on the “private/project/public” header types?
It appears that if i put something in private or project even the framework itself can’t include it from other headers, right? So how can i use them ?
Hi again buddy,
Sure!
The project and private headers is for those header files that you don’t want AND don’t need to share.
For example, when you #import a .h file inside a .m file or inside a private .h file. It means that just the project will have access to that file.
However, for ALL .h files included in public .h files, must be public as well.
The most important thing is that you can’t make cross or invalid references between public and private/project headers, especially inside your code.
I hope it helps.
So if one of my public headers #imports a file called “MyFile.h” , MyFile.h must be public as well ?
Thank you so much for all your responses, i really appreciate it!
Yes!
You got it.
But if you set a header file as private/project, then the #imports in it can be anything (private, project or public). The important thing is to never import a private header inside another public headers.
Hey All, maybe you can assist with some weird issue i’m having. I’ve compiled this ARC-based framework successfully with a Depolyment target of iOS 4.3 , but when i import the framework to a 4.3 project it shows a ld: duplicate symbol _objc_retainedObject error, but it doesnt when its on 5.0 …
I’ve posted a question on StackOverflow, if any of you could try and assist – i’m really confused with this
http://stackoverflow.com/questions/8375233/ld-duplicate-symbol-objc-retainedobject-on-ios-4-3-but-not-on-ios-5-0
Hello buddy,
I never seen something like this. Conflicting with SDK… it’s very strange.
Well, you know, ARC is not a runtime feature, it’s a compiler thing. So, when you create your framework it’s compiled, so the ARC instructions is executed and converted into real code. I don’t know if it’s possible, because any other of the Apple Frameworks use ARC inside the framework.
ARC is something made to make the APP dev easier… so the best place to ask this question is probably the Apple Dev Forum, which have people specialized in ARC technology.
https://devforums.apple.com/community/ios
I’ll try to make some research as well.
Cheers
Oh… and something I’ve seen before, it’s not exactly equal, but can help you.
When I compiled a framework using MRC, I let some MRC instructions in some header files (like “autorelease”). So when I tried to use that framework in another ARC project I got some errors, saying that I can’t use MRC in ARC.
I removed that instruction from the headers, I compiled again, and it worked.
The point is, don’t expose anything in the headers that could cause conflicts. Let the header files of your framework just to instruct Xcode about your methods and properties.
So, thinking at this way, don’t include any ARC instruction inside the headers… or your framework will can’t be used without ARC.
Cheers,
Thanks for the replies man ,
The problem isn’t arc or not-arc , it happens for both. The problem is it shows that error message on 4.3, and it doesnt show it on 5.0 . Im not sure whats this arclite library and why does it say its duplicate if ive never included it… This is really frustrating. Ill try the apple dev forum just in case. Thanks!
Well,
So certainly it’s a problem with the configs of your project.
Try the sample project. It’s working 100%.
Pay attention to the details.
Hey Diney, just wanted to tell you this problem was fixed and post the answer for anyone who might bump into the same issue.
This was a result of an ARC-AFNetworking-4.3/5.0 collision which was resolved by removing a reference to NSJSONSerialization.
Full answer and info is here
http://stackoverflow.com/questions/8375233/ld-duplicate-symbol-objc-retainedobject-on-ios-4-3-but-not-on-ios-5-0/8415556#8415556
Thanks again my friend!
Shai
Thank you, buddy!
Thanks for a wonderful tutorial Diney… I have some doubts regarding this 1 – What is the settings bundle in your sample project and what does it contain. 2 – Can we include coredata classes in our framework. Now, coming to my errors
, when i try to build the aggregate file, some of my Macro constants are throwing errors saying “Use of undeclared identifier xxxxxxx”… Can you tell me what might be the problem here?
Hi buddy,
Thank you! I’m glad you liked.
1 – Here is the settings: http://db-in.com/blog/2011/07/universal-framework-iphone-ios-2-0/#step_4
2 – Your custom classes can be, but not classes from another libs or frameworks.
Where you placed the Macros? On .h or .m files.
By what you are saying, this problem is probably related to the private/public headers and .h access conflicts.
Cheers,
i somehow craked it Diney…. no more erros now. I’v created a framework out of all my available classes. I have imported the newly created framework into my new xcode project. But i am not getting any response when i try to call the methods present in my framework. Even the Log statements in my framework methods are not getting printed. There were no errors either… Any thing more should i do here???
i have imported the framework in my new class as well.
Hiho,
It’s hard to say without see anything.
Try to use the sample project and compare it to your project:
http://db-in.com/downloads/framework-ios.zip
Pingback: How to add core data classes to a framework in iOS
Using the latest XCode with iOS5 it randomly hangs when executing xcodebuild from within the lipo script.
Any workaround for this issue?
Thank for the great tutorial. I’m starting to build a custom framework and I was wondering if I can manipulate screen elements from inside my framework. Since it’s just plain Obj-C code, I believe I can do it. Have you tried it?
Hello buddy,
Sure you can. For example, when you use Cocoa and hit a textfield, the keyboard automatically comes up right in front of everything else. The UIAlertView animate itself. Of course, if you are planning a Framework, probably you will want to trigger your actions from a function or from a method.
Cheers,
not making framework for both simulator and device
Sorry, what did u mean?
What’s your issue?
hey diney actually i was using the framework from Debug folder. so it was working for one…
diney i am getting the issue in
generate debug symbols not found…
Hi,
It’s hard to say what is happening with you with only these informations. Creating a framework will never show the error that is happening, because Apple doesn’t think about it before. So there are many reasons that could lead you in this.
A little mistake in any of the steps, on your classes’ code, destination or in any part of the process can lead you in this.
So, my advice is to take the sample project and try it, change its settings and try to find out the difference between it and your project.
If you want, I can take a look at your project to find out what is happening: diney@db-in.com
everything working fine. Lots of thanks to you
Hello,
When I move my framework from Project Navigator to Copy Bundle Resources I can no longer install the application via iTunes or testflightapp.com, the message is displayed on the iPod’s screen saying that it couldn’t be installed at this time. When I remove framework from Copy Bundle Resources it can be installed again.
Installing via Xcode always works.
Diney – do you have any solution for this issue?
I don’t know what it’s about. Give me more information about what are u doing in the entire process.
Remember that one error in one step may not appear until you use the final framework.
Diney, I did everything as you described in the article above.
I’ve moved my frequently used parts of code to the custom framework so I don’t have to copy the .h & .m files to every new project and compile them every time. Here everything works beautifully – I can submit it to the App Store, I can share it with my beta testers and so on.
But the problem starts when I want to use some resources – like images, xib files etc that has been added to my custom framework. And here starts the trouble. As you said, to use those resources I have to move the framework from Project Navigator (left sidebar) to the “Copy Bundle Resources” section of my target. So my framework is both in “Link Binary With Libraries” and “C.B.R.”.
At this point I can use all the resources that has been added to my custom framework, I can launch the application using Xcode on both simulator and my device. But when my beta testers try to run this app, the installation shows the alert on device saying that installation has failed. They install it via iTunes. When I install it via iTunes – the same alert is displayed on my device.
And again – as soon as I remove the framework from Copy Bundle Resources, me and my beta testers can install the app through iTunes without any problems.
Hi,
I see.
Well, this problem seems doesn’t have a solution for now. Just don’t use resources inside the framework. Leave it only for code.
To resources, like images, use another bundle, a simple bundle from the Xcode template.
Just it.
If I find a solution for that, I’ll inform you.
Hello,
How do I include the xib files into framework?
appreciate if you can guide me.
Regards..mkorat
I think it could be possible
However the tests prove this framework approach doesn’t work well with resources in it.
QQ: Why my framework does not show along with the list of other Apple frameworks while linking with test client?
The Xcode framework window is path dependent.
Your framework just appear there if you place it inside the /Developer/Library/Frameworks. But as the new Xcode is a single APP, you should place it inside the APP.
However, for somehow, maybe a Dcode bug, no custom framework or lib you put inside that folder will work when you compile your project.
Hello folks,
I just did an Ad-Hoc-Deployment with a little TestApp using the above framework approach containing several images and xibs via iTunes and I _cannot_ confirm any problems with it.
So it seems that there is no fundamental problem…
Regards,
Peer
hi,
Provide this helpful tutorial in youtube video.
Thanks
Selvam Sankaran
Hi Diney,
I am new to iOS development, and this is just what I am looking for.
I have a newbie question. I’m not sure how you build the aggregate target. How do you run the script that calls lipo from within Xcode?
Thanks for any help.
Greg
Hi,
You’re welcome.
About your question:
1 – Create the aggregate target.
2 – Click on its icon. (will appear a list of targets when you click on the project icon in the navigation panel).
3 – Click on “Build Phase” tab.
4 – Click on the plus button in the right lower corner and choose “Add Run Script”.
5 – So copy and past the Lipo script in there.
Well, buddy, I must to remember you that this is an advanced technique for advanced developers. This Framework approach is just if you want to share your Very Own code without expose the implementation files. Just it, nothing more. With this Framework approach you can not put the iOS framework that you often use into one single place, this is not allowed in the iOS devices. You can’t merge two frameworks.
So, as you said that you’re new to iOS dev, think about if this is really your intention, because if not, this Framework will not serve to you.
Hi Diney,
Thank you for the quick response.
What I am trying to do is this. I have made some custom controls that I want to use in multiple projects. I thought if I created a framework then it could be used across multiple projects. Should I be doing it differently?
Thanks again,
Greg
Hey Greg,
So you are on the right path!
This is exactly for that this framework approach is for.
If you have any problem, please fell free to ask.
Cheers,
Hi Diney,
Thanks for this awesome Project Template. It all works like a charm … except the code completion when using header, provided by the framework.
In the screenshot of your old tutorial the pop-up for the import of #import is visible.
However in your current sample this is not working. I’ve searched for hours and tried many things out but I can’t figure this out. It is really annoying if you have many headers in a large Framework
Have you got an answer to this problem?
greetz Steve
Hi man,
Thanks, I’m not sure if I got your point.
The “#import with many headers”? Does your framework have many header that other developer must import to use your custom framework?
If so, this is not the correct approach. For example, you never import iOS header like “UIView.h”, “UIViewController.h”, “UINavigationBar.h”, etc… Because there is a single header in the UIKit that import all the public classes of the framework. So the user just need to import “UIKit.h”. In the case of this custom framework you should use the same approach. Create a single header with the name of your framework and import all the framework classes there.
This was your doubt?
Thanks for your reply Diney!
My last post seems not be be submitted successfully …
What I meant, was that I have no code completion when typing in the import statements for the framework headers that provide further headers.
For example:
I have a header named Core.h in my framework that imports CoreClass1.h CoreClass2.h etc.
When typing in the header import for MyFramework/Core.h the code completion is missing. Apple provides this: When I type in Quartz/Q .. it will autocomplete it to Quartz/QuartzCore.h. In my framework my Core.h header will be hard to find without any special prefix because all of the other header it implements are also in the bundle.
If I need a single header of my Core framework e.g Core.h/CoreClass1.h I have to know the exact name because it won’t autocomplete.
Maybe its a little bit more clear what I meant.
Steve
Hello Buddy,
As I told you before. It’s not a good approach to force the user importing many headers of your framework. The good approach is to import only one single header. Usually with the same name as the framework “” and this “MyFramework.h” is just a file that imports all the public headers of your framework.
The code completion depends on the folder the framework are. In the case of this custom framework if you put it in any of the default framework folders it will not work, because it is not a real framework.
So, there is no import header completion with this framework approach. Sorry for that, but this is not a big deal if you follow the best practices.
Hope you understand.
Hi again,
I understand what you mean. Thanks for your reply. Then I will simple use one header for all imports.
One last question:
Importing 30 headers globally or more has no negative impact concerning performance?
Hello buddy,
I suggest you to take a look at the UIKit/UIKit.h or Foundation/Foundation.h.
This is the normal behavior in C. There is no kind of impact specially in the performance. This is not how standard C works.
Everything is compiled at once, I mean, to the compiler there is no separated files, everything is compiled as one single big file. The imports and headers is just an external reference, a convention that we adopt to make the code more readable by other developers.
So when you use “#import” this is not a runtime instruction, this is a compiler time instruction, it’s a macro, just like “#define”. You know how macro works, right?
By the way, nor header nor imports are necessary to C. In the runtime the C is a pure abstract language, everything is in fact an “id” (equivalent to void *). If you have more interest to understand the compiler and the runtime behavior in C/Obj-C I suggest you a fast search about these subjects.
Hope it help you to understand.
Cheers,
Hi Diney,
I am new to iOS Dev [shift from java and javascript development] and my first task was to develop a library so that our customers can use our API from our library to build their App.
I nearly search for 1 week to get info on building library, finally my friend gave me this blog which help to understand and solve my problem.
Thanks for the post.
After following your steps I was not able to still build .framework. finally after 3 hours of investigation I found that I need to change the scheme from applicationName to aggregateName ( from Product > Edit Scheme menu.)
If possible can you edit your post to include this step?
Regards,
Ravi Kishore.
Hello Ravi,
Thanks for your feedback.
What Xcode are u using for?
Since the Xcode 4, when you create a new target, in this case the Bundle target it will create schemes automatically for you. So you don’t really need to edit them.
Did you already have a project and just tried to create a framework from them? This is another situation which you could need to edit schemes manually.
Hi Diney,
Yes I already have a project.
What I meant by editing scheme is that current Active scheme is not aggregate so when I changed Active Scheme to aggregate it worked.
Regards,
Ravi Kishore.
Well buddy… this is what I suppose you’ll do when I say “Now build the Aggregate target”.
This is about your practice with Xcode. And I’m not focused on teaching Xcode here.
Happy you find it by your self.
Hi Diney,
If a framework has a storyboard, then how to access that storyboard?
I am using below API:
[UIStoryboard storyboardWithName:@"ShareWidget" bundle: nil]
and
[UIStoryboard storyboardWithName:@"ShareWidget" bundle: [NSBundle bundleWithIdentifier:@"com.testframework"]]
In both the cases it says unable to find “ShareWidget” in the current App.
Is this correct way to access it or there’s another way?
Because using this storyboard I would initiate initateViewController from current ViewController.
Regards,
K. Ravi Kishore.
Hi Diney,
After some troubleshooting I was able to load the bundle using the below code snippet:
NSString *resourceBundlePath = [[NSBundle mainBundle] pathForResource:@”lib1234″ ofType:@”framework”];
NSBundle *resourceBundle = [NSBundle bundleWithPath:resourceBundlePath];
UIStoryboard * stWidgetSB = [UIStoryboard storyboardWithName:@"ShareWidget" bundle: resourceBundle];
but it gives an error:
Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘Could not find a storyboard named ‘ShareWidget’ in bundle NSBundle (not yet loaded)’
When will this error occur and how to solve it?
Regards,
K. Ravi Kishore.
I found solution for this. storyboard name was “ShareWidget_iPhone” and not just “ShareWidget”. So when I gave “ShareWidget_iPhone” it worked.
I got confused! All step is run well. But when I create a text project for framework. The #import or #import “TFdemo.h” is not found by the project. But the framework in the project which I can see the TFdemo.h file in the /TFDemoFramework/Headers.
I expect to get your help as soon as possible! Thanks!
addtion: The TFDemo.h is public and my xcode is xcode 4.2
Hello buddy,
It’s simple, take another look at 2. about “import headers”.
It’s one single header that import all other headers of your framework, just like the Cocoa does.
Remember now that the file is not at your main folder in the project, it’s inside a framework, so you must import it as a normal framework header, for example:
#import
Get it?
Hello and thanks for you article.
I have a problem with ios simulator. I successfully build and test my framework with a test project on my device. but it gives me error on simulator.
ld: warning: ignoring file /Users/macbookpro/Desktop/test-app/../netmera, missing required architecture i386 in file
Undefined symbols for architecture i386:
“_OBJC_CLASS_$_NetmeraClient”, referenced from:
objc-class-ref in test_appViewController.o
“_OBJC_CLASS_$_NetmeraContent”, referenced from:
objc-class-ref in test_appViewController.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Hello buddy,
Well, so your global framework was not compiled properly.
Review the steps, specially that one about Lipo script and the final framework.
A good tip is to pay attention to the file size.
The final binary will have about the double file size compared to the single frameworks for iOS or Simulator.
For example:
ARMV 6/7 – 500kb
i386 – 500kb
Final framework – 1MB
BTW, take a look at the sample project to help you finding the error.
I’m sorry. that was my foult. i used the binary file under …Xcode/DerivedData/inomeraNetmera-fjmsjkzbuhheokfvrlnznedxhotx/Build/Products/Debug-iphoneos/netmera.framework
it is ok now
hello thanks for your article,
I have made the universal framework in ios. But i am facing issue in delegate methods. I have used textField delegate methods in my framework.
When i import this framework in my application , and used this utility, delegate methods are not getting called. I have researched. But i am not getting the issue what is it?
Well buddy,
This seems to be caused by misspelling. You must be sure that all the connectors and names are matching the correct action.
This is the reason I said that is very important to have a testing target inside the project, that means, a target to you use your code before compiling the framework.
Thanks.
Minor question: Is there a way read version number and target name (from the framework target) in the aggregator shell script?
Hi.
When I’m importing some Frameworks (OpenGLES, QuartzCore, CoreGraphics), it has problems with i386 architecture. I cannot compile, please help.
Like:
Undefined symbols for architecture i386:
“_OBJC_CLASS_$_CAEAGLLayer”, referenced from:
And:
ld: warning: unexpected dylib (/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/System/Library/Frameworks//OpenGLES.framework/OpenGLES) on link line
I’ve got over this, simply forget to link frameworks into the client/test project. But the unexpected dylib warnings still appears in the framework target, a bit annoying.
Hello buddy,
About the target name and version… probably not. Because these are bundle information and the shell script doesn’t know anything about that because it runs before the target compilation starts.
About your second question:
Are you trying to link other frameworks or dylibs with your custom framework?
You know that this is not possible, right?
Understand this framework approach as a way to compile ONLY YOUR OWN CODE and make it private, so anyone else will see nor change your code.
ALL the related frameworks or dylibs that is used by your custom framework code MUST BE imported again when using your custom framework into other projects.
Sorry to hear.
Some kind of static info.plist tweak by hand? I have both my framework’s product name, and version number in its info.plist. Can you show me how to read it off?
Ye, I see that client should import the frameworks again.
The only problem left is the warning at the framework building phase (it works well, though):
ld: warning: unexpected dylib (/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/System/Library/Frameworks//OpenGLES.framework/OpenGLES)
About name and version,
As I told you, I don’t think it’s possible.
This is the reason I’ve defined in the script the first two variables
FMK_NAME=FI
FMK_VERSION=A
You should use that to orient your script, because I don’t think it’s possible to read the name and version directly from the bundle.
This warning is strange. Check what your code is importing and how it’s importing.
Remember that the bundle target should has no linked binaries or any other dependencies on it. Only your own code will be compiled inside your custom framework.
Ohh, what did I wrecked?
ld: framework not found EPPZKit
clang: error: linker command failed with exit code 1 (use -v to see invocation)
HomescreenViewController setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key
this is the exception
Hello buddy,
I’m 99% sure you are using XIBs right? The point is, the view is not connected or there is a misspelling in one of your outlets.
hii
I have made a custom framework as described by you and in that one of my class contain quartzcore framework imported in it. so when i am importing my framework in other project exception is throwing. i am also importing quartz core frame work in other project.
Hello,
First of all I want to congratulate you for the tutorial. It’s fine.
And coming in, I have a doubt. Is there any way to debug the application and stand on a breakpoint, I can go into methods of framework classes seeing your code?
I hope I explained well.
Thank you!
Hi,
Well, once the framework is compiled there is no way to get access to the inner code, just as all the Cocoa frameworks, if you make a break point in your code and then go ahead step by step you’ll just see runtime instructions, making references to your own non-framework code.
But while you’re developing the framework and you have acccess to the code, of course you can make break points.
Hello, Thank you for this great tutorial!
I’ve been using this to create frameworks for some time and it’s been working without any issues until now. After the last Xcode update (4.6) I started getting errors in Organizer when creating AdHocks from an archieve and it turns out that adding the framework to the copy bundle resources build phase is what’s causing it… have you seen this too and if so, do you have any suggestions of how to get around it without actually adding the resources to the app project manually?
Thank you!
Hello,
Well, I and all the others I know still using with 4.6 and making the frameworks, compiling AdHocks and everything else without any trouble.
Make sure your framework is beeing compiled to the universal version, including both archs. Pay attention to the final size of the framework, it must be bigger than when you just make a simple compilation generation only one arch.
Thanks for your quick reply!
After removing the framework from the resources, cleaning, restarting and adding it back, the error is gone!
Wish I knew what the problem was tho…
Now with 4.6 xCode it says this target might include it’s own product when building. btw
First I want to thank you about this great tutorial. It is clear and easy to go through.
I’ve read all the comments and like a lot of others I have the same linker error. But i did set the Generate Debug Symbols to NO. Is it because I’ve added the armv7s architecture?
Can you help me out?
Hello buddy,
No, the debug symbol will appear in any kind of C compiler.
Make sure the “All” option is checked.
In the “Build Settings” tab, there is a search field right below. In the same line the first two options are “Basic All”.
If “Basic” is set you’ll not see the option anyway.
Thank you for the amazing tutorial! But for some reason the Products folder isn’t being created with your script. Any ideas on how to fix this?
Thanks,
Blake
Hi, I solved the last problem. But now I am getting this:
The following build commands failed:
CompileC build/BCClasses.build/Release-iphonesimulator/BC.build/Objects-normal/armv6/BCImageView.o BCClasses/../../BCImageView.m normal armv6 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC build/BCClasses.build/Release-iphonesimulator/BC.build/Objects-normal/armv6/BCButton.o BCClasses/../../BCButton.m normal armv6 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC build/BCClasses.build/Release-iphonesimulator/BC.build/Objects-normal/armv6/BCStandardConnection.o BCClasses/../../BCStandardConnection.m normal armv6 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC build/BCClasses.build/Release-iphonesimulator/BC.build/Objects-normal/armv6/BCLoginView.o BCClasses/../../BCLoginView.m normal armv6 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC build/BCClasses.build/Release-iphonesimulator/BC.build/Objects-normal/armv6/BCRatingView.o BCClasses/../../BCRatingView.m normal armv6 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC build/BCClasses.build/Release-iphonesimulator/BC.build/Objects-normal/armv6/BCSlideshowView.o BCClasses/../../BCSlideshowView.m normal armv6 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC build/BCClasses.build/Release-iphonesimulator/BC.build/Objects-normal/armv6/BCDateLabel.o BCClasses/../../BCDateLabel.m normal armv6 objective-c com.apple.compilers.llvm.clang.1_0.compiler
CompileC build/BCClasses.build/Release-iphonesimulator/BC.build/Objects-normal/armv6/BCRSSReader.o BCClasses/../../BCRSSReader.m normal armv6 objective-c com.apple.compilers.llvm.clang.1_0.compiler
(8 failures)
rm: /Users/Blake/Dropbox/Personal/iPhone Apps/BCClasses/BCClasses/Products/BC.framework/Versions/A/Resources/BC: No such file or directory
lipo: can’t open input file: build/Release-iphoneos/BC.framework/BC (No such file or directory)
Showing first 200 notices only
Command /bin/sh emitted errors but did not return a nonzero exit code to indicate failure
Thanks,
Blake
Sorry for the last two posts, I figured those out
Now I’m getting this:
ld: framework not found BC
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have made sure that I set debug symbols off in the bundle build settings. What should I do to fix this?
Thanks,
Blake
Hello buddy,
Yes! This is the correct answer since your first question.
Good luck.
Hello, Diney,
First of all, thank you very much! Excellent stuff.
But I still have difficulties to make your sample project run. I have been following your instructions, the framework seems to be correctly built and I have made a one view universal sample app (with and without ARC), development target iOS 6.1.
If I try to call the public method “methodA” in the “FIClassA” class, I would expect it to write “Calling methodA at FIClassA” to the console area. Am I missing something?
My ViewController.m looks now like this:
#import "ViewController.h"
#import
#import // because it is in the framework
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[FIClassA methodA];
}
It complains: “No known class method for selector ‘methodA’”, – at least the class by itself seems to be known (is syntax highlighted in Xcode).
Sorry for this beginner question.
Is there anything I should think about specifically? I am trying to make a framework of non-ARC code to be used in a “modern” ARC environment.
Thank you very much indeed.
Hello, Diney,
An edit function would be nice, seems to have eaten my slashes in the code part. Sorry.
Hello, Diney,
It is embarrassing, I forgot to initiate the class:
FIClassA *classA = [[FIClassA alloc] init];
[classA methodA];
Please don’t tell anybody
At least this part could be found in his stolen rubbish.
By the way, I like your NinevehGL project! I am actually playing around with iSGL3D at this moment, but the project is rather dead unfortunately.
Since I see some results with your framework sample, I will try to compile an iSGL3D framework to run under ARC conditions.
Thanks a lot! Cheers
Hello buddy,
Thanks for your comments. I’m glad you found the solution by your own.
This could be good to others facing the same problem as you.
Following these steps correctly the framework will compile and work regardless the Xcode or iOS version.
If something goes wrong, just double check the mistakes the people are used to make:
- Public Headers are correctly set on “Building Phase”? The sources (.m, .mm, .cpp) are also placed in “Build Phase”?
- The architectures are correct (armv7, armv7s, etC)? The framework is being compiled to each of those archs?
- To make sure the binary is being compiled, remove the last line of the shell script (rm -r “${WRK_DIR}”). This will keep the working folder, so you can check if the binary is at least being compiled to each platforms. If one platform is missing, start tracking what could lead to that specific platform compilation to fail.
- Make sure the “Debug Symbols” are off.
Those few steps could sounds confusing at the first time, but if you pass through them at least one time you’ll see how easy it is.
Excellent Tutorial…
I was able to instantiate the class and print stuff out of it. But when I tried to add the class’s view as a subview in the app. It says,
Could not load NIB in bundle: ‘NSBundle (loaded)’ with name ‘/Users/nbkqkka/Library/Application Support/iPhone Simulator/6.1/Applications/EF0A9D34-1BDB-482C-8706-6B8C3E60D412/MLTestHarnessApp.app/MyTestFrameworkBundle.framework/Resources/ViewController_iPad.nib”
Could you please help me with this…
This is how I am instantiating the class.
NSString *path = [[NSBundle mainBundle] pathForResource:@”MyTestFrameworkBundle.framework/Resources/ViewController_iPad” ofType:@”nib”];
NSLog(@”Path:%@”, path);
ViewController *controller = [[[ViewController alloc] initWithNibName:path bundle:[NSBundle mainBundle]] autorelease];
[controller printTHis:@"hello"];
[self.view addSubview:controller.view];
[self.view bringSubviewToFront:controller.view];
Console output
MLTestHarnessApp[87975:c07] Path:/Users/i-raqz/Library/Application Support/iPhone Simulator/6.1/Applications/EF0A9D34-1BDB-482C-8706-6B8C3E60D412/MLTestHarnessApp.app/MyTestFrameworkBundle.framework/Resources/ViewController_iPad.nib
I did a show package contents of the app but i couldn’t see the Framework folder, I thought the folder will be copied as it is into dervied data.
When you compile a bundle within your framework you must add it to your project as well, that means, you will add the framework, then open the Framework folder in finder, navigate to the bundle and import it to the project again.
When you import a compiled framework its bundle doesn’t comes.
Pingback: 【私訳】iOSのスタティックフレームワークを高速かつ効果的に、作成・開発・配布する方法 | yumtec.info