iOS Development: Xcode packaging Framework

Source: Internet
Author: User
Tags join object model wrapper root directory

I think this packaging framework is a relatively important function that can be used to do things:

(1) Packaging functional modules, such as the more mature function modules packaged into a package, and then their own or other colleagues to use more convenient.

(2) Packaging projects, sometimes encountered this situation, that is, a company to find two development companies to do two projects, and then ask one of their projects nested into another project, at this time can also be nested projects packaged into a framework to put in, this is more convenient.

Why do we need frameworks?

It's cumbersome to share libraries in a developer-friendly way. You need to include not only the library itself, but all header files, resources, and so on.

The way Apple solves this problem is the framework. Basically, this is a folder that contains a fixed structure and includes everything necessary to reference the library. Unfortunately, iOS disables all dynamic libraries. At the same time, Apple also removed the ability to create a static iOS framework from Xcode.

Xcode can still support the ability to create frames and reboot this feature, we need to make some minor changes to Xcode.

Encapsulating the code in a static frame is allowed by the App Store. Although the form is different, in essence it is still a static library.

Category of frame (framework)

Most frameworks are in the form of dynamic link libraries. Because only Apple can install dynamic libraries on iOS devices, we cannot create this type of framework.

Static link libraries are the same as dynamic libraries, except that they link binary code at compile time, so using a static library does not have a problem with dynamic libraries (that is, no one can use a dynamic library on iOS except Apple).

The "pseudo" framework is implemented by cracking the Xcode target bundle (using certain scripts). It is not different from the static frame on the surface and when used. The functionality of the "pseudo" framework project is almost indistinguishable from the actual frame project (not all).

The embed frame is a wrapper in the static frame so that Xcode can get the resources within the framework (Pictures, plist, NIB, etc.).

This publication includes templates for creating static and "pseudo" frameworks, as well as an "embedded" framework for both.

Which template to use?

There are two templates for this release, and each template has a "strong" "weak" two categories. You can choose the one that works best (or both).

The biggest difference is that Xcode cannot create a "true" frame unless you install a static frame file Xcspec in Xcode. It's a shame (this file is for the project, not the framework).

To put it simply, you can decide which template to use:

If you do not want to modify Xcode, use the "pseudo" frame version

If you just want to share the binary (not the project), both of them can be

If you want to share the framework with developers who do not want to modify Xcode, use the "pseudo" framework version

If you want to share the framework with developers who have modified Xcode, use the "true" framework version

If you want to rely on a framework project as a dependency on another project (through workspace or subprojects), use the "true" framework (or "pseudo" framework, use-framework--to see later)

If you want to add other static libraries/frameworks to your framework project and link them to the final results so that you don't need to add them to the user project individually, use the "pseudo" framework

"Pseudo" frame

The "pseudo" framework is a cracked "Reloacatable object File" (a relocatable format for object files that holds code and data that is suitable for connecting to other target files to create an executable object file or a shareable target file). It allows Xcode to compile something similar to a frame--a bundle, in fact.

The pseudo-framework template divides the process into several steps, using certain scripts to produce a true static framework (based on a static library rather than Reloacatable object file). Furthermore, the framework project defines it as a wrapper.cfbundle type, a "second-class citizen" in the Xcode.

So it works just as well as a "true" static framework, but it's a hassle when it comes to dependencies.

Dependency issues

If you don't use dependencies, it's not a problem to just create a normal project. But if you use Project dependencies (like in workspace), Xcode is a tragedy. When you click the ' + ' button under "Link Binary with Libraries", the pseudo frame cannot be displayed in the list. You can drag it manually from your "pseudo" frame project, but when you edit your main project, a warning appears:

warning:skipping file '/somewhere/myframework.framework ' (unexpectedfile type ' Wrapper.cfbundle ' in Frameworks & Libraries Build phase)

and accompanies the link error in the pseudo frame.

Fortunately, there is a way to solve it. You can manually tell Linker by using the "-framwork" switch in "other Linker Flags" to link to your frame:

-framework Myframework

The warning still exists, but at least it can be linked correctly.

Add additional libraries/frames

If you join other static (not dynamic) libraries/frameworks into your "pseudo" frame project, they will "link" into your final binary frame file. In the true frame project, they are pure references, not links.

You can avoid this situation in the project by simply including the header file rather than the static library/framework itself (so that the compilation passes).

"True" frame

All aspects of the "true" framework conform to the "true" standard. It is a real static framework, just as it was created using the feature that Apple removed from the Xcode.

In order to create a real static framework project, you must install a Xcspec file in Xcode.

If you publish a "true" framework project (rather than compiling it), the person wishing to compile the framework must also install the Xcspec file (using the installation script for this release) so that Xcode can understand the target type.

Note: If you are publishing a fully-compiled framework, rather than a framework project, end users do not need to install anything.

I have submitted a report to Apple, hoping they will update the file in Xcode, but that takes a little time. Openradarlink here

Add other static libraries/frames

If you join other static (not dynamic) libraries/frames to your "real" frame project, they will only be referenced and not be linked to the final binaries like "pseudo" frames.

Upgrading from earlier versions

If you are upgrading from a Mk6 or earlier version, using the "true" static framework and using the previous version of Xcode4.2.1, run uninstall_legacy.sh to uninstall all revisions that were used for Xcode earlier. Then run install.sh and reboot the Xcode. If you use Xcode4.3, you only need to run install.sh and restart Xcode.

Installation

Run the install.sh scripts in the real framework directory or the fake framework directory, respectively, to install (or you can run two).

Restart Xcode, you will see the Staticios framework (or the fake Static IOS framework) under the framework&library of the New Project Wizard.

Uninstall please run unistall.sh script and restart Xcode.

Create an iOS framework project

Create a new project.

Project type Select the static iOS framework (or the fake static iOS framework) under Framework&library.

Select Include unit test (optional).

Add classes, resources, etc. to target.

The header file that you want to use for other items must be declared public. Go to Target's build phases page, expand the Copy headers entry, and drag the header file that needs to be public from project or private to the public section.

Compile your IOS framework

Select scheme for specified target

Modify scheme's run configuration (optional). The Run configuration uses debug by default, but you may want to use release when you are ready to deploy.

The compilation framework (regardless of whether the target is iOS device and simulator will compile the same binary, so it doesn't matter who chooses it).

Select your framework from the products below, "show in Finder".

There are two folders under the build directory: (yourframework). Framework and (your framework). Embeddedframework.

If your frame has only code, no resources (such as pictures, scripts, xib, coredata momd files, etc.), you can put (yourframework). The framework is distributed to your users. If you also include resources, you must distribute (your framework). Embeddedframework to your users.

Why do I need the embedded framework? Because Xcode does not find resources in static frames, if you distribute (your framework). The framework, all resources in the frame are not displayed and are not available.

A embedded framework is just an add-on package outside of a framework that includes symbolic links to all the resources of the framework. The goal is to allow Xcode to find these resources.

Using the iOS framework

The iOS framework is about the same as the regular Mac OS dynamic framework, except that it is statically linked.

Use a frame in your project, just drag it into your project only. When you include a header file, remember to enclose the frame name with angle brackets instead of double quotes. For example, for frame myframework:

#import

Usage issues

Headers not Found

If Xcode cannot find the header files for the frames, you may have forgotten to declare them public. Refer to the "Create an iOS Framework project" Step 5th.

No Such Product Type

If you do not install the iOS Universal framework in Xcode and attempt to compile a universal framework project (for the "true" framework, not the "fake" framework), this can cause the following errors:

Target Specifies product type ' com.apple.product-type.framework.static ', but there ' s no such product type for the ' Iphonesi Mulator ' Platform

In order to compile the true iOS static framework, Xcode needs to make some changes, so in order to compile the true static framework project, install it in all development environments (not required for users who use the framework, only if you want to compile the framework).

The selected run destination is isn't valid for this action

Sometimes, xcode errors and loads the wrong active settings. First, try restarting Xcode. If the error persists, Xcode produces a bad project (because of a bug in Xcode4, this problem occurs for any type of project). If so, you need to create a new project and start over again.

Link warning

The first time the frame target is compiled, Xcdoe cannot find the folder in the link Phase report:

Ld:warning:directory not found for option '-l/users/myself/library/developer/xcode/deriveddata/ Myframework-ccahfoccjqiognaqraesrxdyqcne/build/products/debug-iphoneos '

At this point, you can clean and recompile target, and the warning will be eliminated.

Core Data MOMD not found

For framework projects and application projects, Xcode compiles MOMD (managed object model files) in different ways. Xcode will simply create a. mom file in the root directory without creating a. MOMD directory (the directory contains versioninfo.plist and. Mom files).

This means that when you instantiate Nsmanagedobjectmodel from the model of a embedded framework, you must use the. mom extension as the URL for model instead of the. momd extension.

Nsurl *modelurl = [[NSBundle mainbundle]urlforresource:@ ' mymodel ' withextension:@ ' Mom '];

Unknown class MyClass in Interface Builder file.

Because static frames are statically linked, linker will strip out all the code it deems useless. Unfortunately, linker does not check the Xib file, so if the class is referenced in Xib and not referenced in O-C code, linker deletes the class from the final executable file. This is a linker problem, not a framework problem (this problem occurs when you compile a static library). This problem does not occur with the Apple built-in framework because they are dynamically loaded at runtime, and dynamic libraries that exist in the firmware of iOS devices are not likely to be deleted.

There are two solutions:

Let the end users of the framework turn off the Linker optimization options by adding-OBJC and-all_load to their project's other Linker flags.

Add a code reference to the class in another class in the frame. For example, suppose you have a MyTextField class that is removed by linker. Suppose you have a myviewcontroller, it's used in Xib, and Mytextfield,myviewcontroller is not removed. You should do this:

In the MyTextField:

+ (void) Forcelinkerload_ {}

In the Myviewcontroller:

+ (void) Initialize {[MyTextField forcelinkerload_];}

They still need to add-OBJC to linker settings, but they do not need to force all_load.

The 2nd approach requires you to do a little more work, but it lets end users avoid turning off linker optimizations when using your framework (turning off linker optimization causes the object file to swell).

Unexpected file type ' Wrapper.cfbundle ' in frameworks &libraries build phase

This problem occurs when you rely on a "fake" framework project as a workspace, or as a subproject (the "true" framework project does not have this problem). Although this framework project produces the correct static framework, Xcode can only see this as a bundle from the project file, so it emits a warning when checking dependencies and skips it in the linker phase.

You can manually add a command to allow linker to link correctly during the link phase. In the Otherlinker flags that rely on your static framework project, add:

-framework Myframework

The warning still exists but does not cause the link to fail.

Libraries being linked or not being linked to the Finalframework

Unfortunately, the "true" framework and the "fake" framework templates work differently in the process of introducing static libraries/frameworks.

The true frame template takes a normal static library generation step and does not link to other static libraries/frames to the final production.

The "fake" framework template uses the "cheat" xcode to make it think that it is compiling a target file in a relocatable format that, in the link phase, is like compiling an executable file, linking all the static code files to the final build (although it does not check for actual target code). To achieve the same effect as the "true" framework, you can include only the library/frame header file into your project without having to include the library/framework itself.

Unrecognized selector in (some class with a category method)

If your static library or static framework contains a module (only declared in the class code, no class implementation), linker will not be able to figure it out and remove the code from the binary file. Because there is no such method in the resulting file, a "Unrecognizedselector" exception is reported when the method defined in this class is invoked.

To resolve this, add a "fake" class to the module code that contains this class. Linker found that there is a complete o-c class that links the category code to the module.

I wrote a header file LoadableCategory.h to ease this workload:

#import "Someconcreteclass+myadditions.h"

#import "LoadableCategory.h" make_categories_loadable (someconcreteclass_myadditions); @implementation Someconcreteclass (myadditions)

...

@end

When using this framework, you still need to add-OBJC to the other Linker flags in build setting.

Execute any code before unit test crashes

If you create a static frame (or library) target in Xcode4.3, you check "withunit tests" and it crashes when you try to run a unit test:

Thread 1:exc_bad_access (code=2, address=0x0) 0 0x00000000---dyldbootstrap:start (...)

This is a bug in the lldb. You can use GDB to run unit tests. Edit scheme, select Test, and change the debugger debugger from Lldb to gdb in the Info tab.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.