Create a static library in iOS

Source: Internet
Author: User
Tags image filter uikit

If you have been an iOS developer for some time, you might have a set of your own classes and tool functions that are reused in most of your projects. The simplest way to reuse code is to simply copy/paste the source file. However, this approach will soon become a maintenance nightmare. Because each app has its own copy of the code, it's hard to keep all copies synchronized when fixing bugs or upgrading. This is the static library to save you. A static library is a wrapper for several classes, functions, definitions, and resources that you can package and easily share between projects. In this tutorial, you will create your own generic static library in two ways. For best results, you should be familiar with OBJECTIVE-C and iOS programming. The knowledge of Core image is not required, but it can be helpful if you are interested in how the sample project and the filter code work. Be prepared to reduce, reuse and regenerate your code in the name of efficiency! Why use a static library There are several reasons why you might create a static library:1. You want to package and easily share some of the classes that you and your colleagues in your team use frequently with others around you. 2. You want to get some general-purpose code under your control so that it can be repaired and upgraded. 3. You want to share the library with others, but don't want them to see your source code. You want to create a snapshot version of a library that is still being developed. This tutorial assumes that you have finished learning Core image Tutorial and are handy with the code that shows how to apply picture effects. Add the above code to a static library, and then use the static library in a modified version of the app. We'll get an exact same app with all the benefits from the list above. StartRun Xcode, select File\new\project, select Ios\framework & Library\cocoa Touch Static Library in the Choose a template dialog box, such as: Click Next. In the Project Options dialog box, enter Imagefilters as the product name. Enter a unique company ID to ensure that use Automatic Reference counting is selected and include Unit tests is unchecked. For example: Click Next. Finally, select the location where you want to save the project and click Create. Xcode is ready for the static library project and has even added a imagefilters class for you. This is where your filter code is going to be stored. Note: You can add any number of classes to the static library or delete the original class from it. The code in this tutorial will be written in the Imagefilters class that was created at the beginning. Your Xcode project is still blank, now we add some code to go in! Image FilterThe library is designed for iOS using Uikit, so the first thing you need to do is import Uikit into the header file. Open ImageFilters.h and add the following code at the top of the file:
    1. #import <UIKit/UIKit.h>
Next, paste the code from the following declaration section below @interface Imagefilters:nsobject
    1. @property (nonatomic,readonly) UIImage *originalimage;
    2. -(ID) initwithimage: (UIImage *) image;
    3. -(UIImage *) grayscaleimage;
    4. -(UIImage *) oldimagewithintensity: (cgfloat) level;
The declarations in these header files define the public interface of the class. When other developers (including yourself) use the library, you can simply read the header file to know the class name and the method of exposure. Now add the implementation. Open the Imagefilters.m file and paste the following code under #import "ImageFilters.h":
    1. @Interface Imagefilters ()
    2. @property (Nonatomic,strong) Cicontext *context;
    3. @property (Nonatomic,strong) ciimage *beginimage;
    4. @end
The above code declares some properties that are used internally. They are not public, so references to using the library do not use their portals. Finally, you need to implement the method. Paste the following code into @implementation imagefilters: below:
  1. -(ID) initwithimage: (UIImage *) image
  2. {
  3. self = [super init];
  4. if (self) {
  5. _originalimage = image;
  6. _context = [Cicontext Contextwithoptions:nil];
  7. _beginimage = [[Ciimage alloc] initwithimage:_originalimage];
  8. }
  9. return self;
  10. }
  11. -(uiimage*) Imagewithciimage: (Ciimage *) ciimage
  12. {
  13. Cgimageref cgiimage = [Self.context createcgimage:ciimage fromRect:ciImage.extent];
  14. UIImage *image = [UIImage imagewithcgimage:cgiimage];
  15. Cgimagerelease (Cgiimage);
  16. return image;
  17. }
  18. -(UIImage *) grayscaleimage
  19. {
  20. if (!self.originalimage)
  21. return nil;
  22. Ciimage *grayscalefilter = [cifilter filterwithname:@"Cicolorcontrols" Keysandvalues:kciinputimagekey, Self.beginimage, @"inputbrightness", [NSNumber numberwithfloat:0.0], @"Inputcontrast", [NSNumber numberwithfloat:1.1], @"inputsaturation", [NSNumber numberwithfloat:0.0], nil].outputimage;
  23. Ciimage *output = [cifilter filterwithname:@"Ciexposureadjust" Keysandvalues:kciinputimagekey, GrayScaleFilter, @ "Inputev", [NSNumber numberwithfloat:0.7], nil].outputimage;
  24. UIImage *filteredimage = [self imagewithciimage:output];
  25. return filteredimage;
  26. }
  27. -(UIImage *) oldimagewithintensity: (cgfloat) intensity
  28. {
  29. if (!self.originalimage)
  30. return nil;
  31. Cifilter *sepia = [cifilter filterwithname:@"Cisepiatone"];
  32. [Sepia setValue:self.beginImage Forkey:kciinputimagekey];
  33. [Sepia setvalue:@ (intensity) forkey:@"inputintensity"];
  34. Cifilter *random = [cifilter filterwithname:@"Cirandomgenerator"];
  35. Cifilter *lighten = [cifilter filterwithname:@"Cicolorcontrols"];
  36. [Lighten setValue:random.outputImage Forkey:kciinputimagekey];
  37. [Lighten setvalue:@ (1-intensity) forkey:@"inputbrightness"];
  38. [Lighten setvalue:@0.0 forkey:@"Inputsaturation"];
  39. Ciimage *croppedimage = [Lighten.outputimage imagebycroppingtorect:[self.beginimage extent];
  40. Cifilter *composite = [cifilter filterwithname:@"Cihardlightblendmode"];
  41. [Composite setValue:sepia.outputImage Forkey:kciinputimagekey];
  42. [Composite setvalue:croppedimage Forkey:kciinputbackgroundimagekey];
  43. Cifilter *vignette = [cifilter filterwithname:@"Civignette"];
  44. [Vignette SetValue:composite.outputImage Forkey:kciinputimagekey];
  45. [Vignette setvalue:@ (intensity * 2) forkey:@"inputintensity"];
  46. [Vignette setvalue:@ (intensity *) forkey:@"Inputradius"];
  47. UIImage *filteredimage = [self imageWithCIImage:vignette.outputImage];
  48. return filteredimage;
  49. }
This code implements the initialization and image filter functions. The ability to explain the above code in detail is beyond the scope of this tutorial, and you can learn more about core image and filters from core image tutorial. Here, you already have a static library, and it has a public class imagefilters that exposes the following 3 methods: Initwithimage:Initialize the filter class Grayscaleimage:To create a gray-scale picture oldimagewithintensity:Create a picture of the nostalgic effect now build and run your library. You'll notice that Xcode's "run" button simply executes a build and doesn't actually run the library to see the effect, because there's no real app. The suffix name of the static library is. A instead of an. app or. ipa file. The generated static library can be found under the Products folder in the project navigation bar.  Right-click on the LIBIMAGEFILTERS.A and select Show in Finder from the pop-up menu. Xcode opens the folder in the Finder, and you can see a structure similar to the following: There are two things left to complete a library product: 1.Header Files:All of the public header files for the library can be found in the Include folder. In this example, there is only one public class so there is only one ImageFilters.h file in the folder. You'll use this header file in your app project later to make Xcode recognize exposed classes at compile time. 2.Binary Libraty:The static library generated by Xcode is IMAGEFILTERS.A. To use the library in your app, you need to link to that file. These two sections are similar to what you need to do to include some new frameworks in your app, simply import the frame header file and create a link. The library is ready and requires additional instructions that, by default, the library file will only be built for the current schema. If you build under the simulator, the library will contain the result code corresponding to the i386 schema, and if it is built under the real machine device, you will get the code corresponding to the ARM architecture. You may need to build two versions of the library and select one to use when switching from the emulator to the device. What to do? Fortunately, there is a better way to support multiple platforms without having to build multiple configurations or build products in the project. You can create a universal binary that contains the result code for 2 schemas. Universal Binary BinaryA generic binary is a special binary file that contains result codes that correspond to multiple schemas. You may be familiar with the transition from PowerPC (PPC) to Inter (i386) 's Mac computer product line. In this process, the MAC application is typically migrated to a binary file that contains 2 executable packages so that the application can run on the PowerPC Mac computer Inter. The concept of supporting arm and I386 is not very different at the same time. Here the static library contains result codes that support iOS devices (ARM) and emulators (i386). Xcode recognizes a common library, and each time you build an application, it chooses the appropriate architecture based on the target.  In order to create a generic binary library, a system tool called Lipo is required. Don't worry, it's not that lipo!. :] (Lipo has fat meaning-translator note) Lipo is a command-line tool that allows you to perform operations on common files (similar to creating generic binaries, listing common file contents, and so on). The purpose of using Lipo in this tutorial is to federate binary files of different schemas into a single output file. You can use the Lipo command directly from the command line, but in this tutorial you can have Xcode perform a command-line script that creates a common library for you. A collection target in Xcode can build multiple targets at once, including command-line scripting. Select File/new/target in the Xcode menu, select Ios/other and click Aggregate,: Name the target universallib, and make sure Imagefilters project is selected: In the Project Navigation view, select Imagefilters, and then select the Universallib target. Switch to the Build Phases tab, where you set the action to be performed when building the target. Click the Add Build Phase button and select Add Run script from the pop-up menu, such as: Now you need to set the script entry. Expand the Run script module and paste the following code below the shell line:
  1. # define output Folder environment variable
  2. Universal_outputfolder=${build_dir}/${configuration}-universal
  3. # Step 1. Build Device and Simulator versions
  4. Xcodebuild-target imagefilters only_active_arch=no-configuration ${configuration}-sdk iphoneos BUILD_DIR="${ Build_dir} "build_root=" ${build_root} "
  5. Xcodebuild-target imagefilters-configuration ${configuration}-sdk iphonesimulator-arch i386 BUILD_DIR="${BUILD_ DIR} "build_root=" ${build_root} "
  6. # Make sure the output directory exists
  7. Mkdir-p "${universal_outputfolder}"
  8. # Step 2. Create Universal binary file using Lipo
  9. Lipo-create-output " ${universal_outputfolder}/lib${project_name}.a" "${build_dir}/${configuration}- Iphoneos/lib${project_name}.a " " ${build_dir}/${configuration}-iphonesimulator/lib${project_name}.a "
  10. # Last touch. Copy the header files. Just for convenience
  11. Cp-r "${build_dir}/${configuration}-iphoneos/include" " ${universal_outputfolder}/"
The code is not very complex, it works like this: Universal_outputfolderIncludes the folder where the generic binary package will be stored: "Debug-universal" Step 1.Line 2nd executes the xcodebuild and commands it to build the binary files of the ARM architecture. (You can see the-sdk iphoneos parameter in this line) the next line executes the Xcodebuild command again and builds a binary file of the iphone emulator for the inter schema in another folder, where the key parameter is-SDK Iphonesimulator-arch i386. (If you are interested, you can learn more about Xcodebuild on the man page) Step 2.There are now 2. A files that correspond to two schemas respectively. Execute lipo-create and use them to create a generic binary. The last line is to copy the header file to the outer layer of the Generic build folder. (with the CP command) your run script window should look like this: Now you are ready to build a generic version of a static library. In the Scenario menu, select Set Target Universallib, as follows (unlike "IOS device" above, you may see your device name): Click the play button to build a goal for the collection scheme. On LIBIMAGEFILTERS.A, select the show in Finder again to view the results. Switch the Finder to the column view to view the folder hierarchy, you can see a new folder called Debug-universal that contains a generic version of the library (or release-universal if you build a release version), such as: In addition to the binary files that link to the emulator and the real device, you can also find common header files and static library files. This is all the knowledge you need to learn to create your own universal static library. To sum up, a static library project is very similar to an application project. You can have one or more classes, and the final product is a header file and a. a file. This. A file is a static library that can be linked to multiple applications. using a static library in your appUsing the Imagefilters class in your app and working directly with the source code is not much different: Import the header file and start using the class. The problem is that Xcode does not know the location of the header files and library files. There are two ways to bring a static library into the project: Method 1:Direct reference to header files and library binaries (. a) Method 2:Choosing a library project as a subproject depends entirely on your preferences or whether you have a static library of source code and a project configuration file at your disposal. This tutorial will cover two methods. You are free to try the first or second, but it is recommended to try each of the two in the order described in the article. At the beginning of the two sections, a ZIP file is required that is a modified version of the app created in core Image tutorial, and the modified version uses the new Imagefilters class in the library. The main purpose of this tutorial is to teach you how to use a static library, so the modified project includes the source code required for all applications. This allows you to focus on the engineering settings needed to use the library. Method 1: Header files and library binariesIn this section, you need to download the starter project for the. Copy the compressed file to any folder on your hard drive and unzip it. You can see the following folder structure: For convenience, the. A common library file and header files have been copied with a copy in it, but the project is not set up to use them. You will start here. Note: The standard UNIX Introduction convention is an include folder that holds header files and a Lib folder for storing library files (. a). This folder structure is a convention and is not mandatory. You do not need to follow this structure or copy files to the project folder. In your own app, you can choose the location of the header and library files, as long as the appropriate path is set up in the Xcode project. Open the project, build and run your app, and you'll see the following error: As expected, the app doesn't know where to look for the header file. To solve this problem, you need to add a header Search Path to the project to indicate where the header file will be stored. Setting the header file search path is always the first step in using a static library. According to the demonstration, click on the Project root node (1) in the navigation bar and select the Coreimagefun target (2). Select Build Settings (3), and locate the header Search paths setting item in the list. If necessary, you can filter the large list of settings (4) by typing "header search" in the search box. Double-click the header Search paths entry, pop up a floating window, click the + button, enter:
    1. $SOURCE _root/include 
The popup should look like the following:  $SOURCE _root is a xcode environment variable that points to the project root folder. Xcode replaces this variable with the actual folder containing your project, which means that even if you move the project to a different folder or drive, it can still point to the newest location. Click the mouse outside the pop-up window to make it disappear, and you'll see that Xcode has automatically converted the variable to the actual location of the project,:  build and run the app to see what the results are. Uh...... Some link errors appear:  this doesn't look good, but it gives you another message you need. Look closely, you will find all the compilation errors are gone, all are replaced by link errors. This means that Xcode finds the header file and uses it to compile the app, but in the link phase, Xcode cannot find the result code for the ImageFilter class. Why?   is simple-you haven't told Xcode where to look for library files that contain class implementations. (see, no big deal)   back to the build settings (2) of the Coreimagefun target (1) as shown in the following screen. Select the build Phases Tag (3) and expand the link Binary with Libraries section (4). Finally, click the + button (5).   In the window that appears, click Add Other ... button, locate the LIBIMAGEFILTERS.A library file in the Lib subdirectory under the project root folder,:  Complete these, your build phase tag looks as follows:  the last step is to increase the-OBJC link identity. The link attempts to include only the required code more efficiently, and sometimes excludes static library code. With this identity, all objective-c classes and categories in the library are loaded appropriately. You can learn more from Apple's technical q&a QA1490.   Click the Build Settings tab to find the other linker flags settings,:  in the pop-up window, click the + button and enter-objc,:  to build and run the app at this time, you should not get any build error messages, The app shows its brilliance:  drag the slider to change the filter level, or click the Grayscale button. The code to apply a filter to a picture comes from a static library, not an app.   Congratulations-you've built your first static library and used it in a real app! You'll find that this method of including header files and libraries is used in many third-party libraries, such as admob,testflight or some commercial libraries that do not provide source code.   Method 2: Sub-item In this section, please download the required works here.   Copy downloaded files to any location, unzip. You can see the following folder structure:   If you have studied method one, you may have noticed the difference in engineering. This project does not have any header files and static library files-because it is not needed at all. As an alternative, you will add the Imagefilters Library project that you started to create in this tutorial as a dependency added to this project. Before you do this, build and run your app. You will see the following error:  if you have learned the previous method, you already know how to fix the problem. In the example project, you used the Imagefilters class in the Viewcontroller class, but did not tell Xcode where to look for the header file. Xcode tries to find the ImageFilters.h file, but it fails.   All that is required for the Imagefilters Library project as a subproject is to drag and drop the library project file into the library file tree. If the project is already open in another Xcode window, Xcode will not be able to add it as a sub-project correctly. So before continuing this tutorial, make sure that the Imagefilters Library project has been closed.   found the project file named Imagefilters.xcodeproj Library in the Finder. Drag it to the left navigation bar of the Coreimagefun project,:  complete the drag and drop, your engineering browsing view should look like the:  now that Xcode has identified the sub-project, you can add the library as an engineering dependency. This allows Xcode to make sure the library is up to date before building the main app.   Click on the project document (1) and select Coreimagefun Target (2). Click the Build Phases tab (3) and expand Target Dependencies (4),:  Click the + button to add a new dependency. As shown, make sure that you select the Imagefilters target (not universallib) from the pop-up window:  the dependency window should:  Finally, set the static Library project link to the app after the add is complete. Expand link Binary with libraries, click the + button,:  Select LIBIMAGEFILTERS.A, click add:  Add Library, Link binary with libraries section should:   Like method One, the final step is to increase the-OBJC link identifier. Click the Build Settings tab, locate the other linker flags settings,:  in the pop-up window, click the + button and enter-objc,:  build and run the app, there should be no errors, the app will be opened again: Drag the slider or click the Grayscale button to see the image filter results. The code for the filter logic is completely contained in the library.   If you add a library (using header files and library files) to the application in the first way, you may notice the difference from the second method. In method Two, you did not add any header file search paths in the project settings. Another difference is that you do not use the universal library. Why is there such a difference in  ? When adding a library as a sub-project, Xcode will consider almost everything for you. After you add the subproject and dependencies, Xcode knows where to look for header and binary files, and also knows which libraries to choose which architecture to build based on your settings. This is very convenient.   If you use your own library or have source code and engineering files, using libraries as sub-projects is an easy way to introduce static libraries. Make it easier for you to build consolidation as an engineering dependency and worry about fewer things.   FutureYou can download the project from here to all the code included in this tutorial. Hopefully this tutorial will give you a more in-depth understanding of the basic concepts of static libraries and how to use them in your application. The next step is to build your own library with the knowledge you've learned. You certainly have some common classes added to the project. They are excellent candidates for you to join your own reusable library. You can also consider creating multiple libraries based on functionality: The network part of the code as one, the UI part as another, and so on. You can add only the required code to the project. To reinforce and delve into the concepts that you have learned in this tutorial, I recommend Apple's documentation introduction to Using the Static Libraries in IOS.

http://blog.csdn.net/pcwe2002/article/details/45579241

Create a static library in iOS

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.