Building Objective-C static libraries with categories

Q: How do I fix "selector not recognized" runtime exceptions when trying to use category methods from a static library?

How Solution Try the runtime environment calls the static library classification, the newspaper "selector not recognized" abnormal?

  Today while browsing YYKit library, a macro definition caught my attention: YYSYNTH_DUMMY_CLASSfrom literally see is the definition of a no effect of dumb class. Description as follows:

/**
 Add this macro before each category implementation, so we don't have to use
 -all_load or -force_load to load object files from static libraries that only
 contain categories and no classes.
 More info: http://developer.apple.com/library/mac/#qa/qa2006/qa1490.html .
 *******************************************************************************
 Example:
     YYSYNTH_DUMMY_CLASS(NSString_YYAdd)
 */
#ifndef YYSYNTH_DUMMY_CLASS
#define YYSYNTH_DUMMY_CLASS(_name_) \
@interface YYSYNTH_DUMMY_CLASS_ ## _name_ : NSObject @end \
@implementation YYSYNTH_DUMMY_CLASS_ ## _name_ @end
#endif

  According to YYKit author's description, in the category plus a macro definition to avoid such a complex operation, the authors did not explain the specific principles, only a connection to the development of Apple's official documentation. This link may be because of an official document finishing, URL path has expired. But the search keywords in the URL of the official website to find this information . According to this information in-depth look at the principles which here and how to solve these problems.

The official document begins with a question, is that the issues raised above, ha ha. The next official document given to the solution to the problem:

A: If you're seeing a "selector not recognized" runtime exception when calling a category method that is implemented in a static library, you are hitting the link-time build issue described here, and need to add the -ObjC linker flag to your project, by following these steps:

  1. In Xcode, choose View > Navigators > Show Project Navigator, or press ⌘1.
  1. Select your project under the PROJECT heading in the Project Navigator, then select the Build Settings tab.
  2. Scroll down to the Other Linker Flags build setting under the Linking collection, or type "Other Linker Flags" into the search bar.
  3. Set the value of the Other Linker Flags build setting to $(OTHER_LDFLAGS) -ObjC.

Translation: When you call classification implemented in a static library methods at runtime encountered "selector not recognized" runtime exception, then you hit the so-called "the link-time build described in this document issue "problem, and you need to add in your project -ObjC linker flagto solve this problem. Specific steps :( here is not translated Meme da).

Figure 1: Modifying the Other Linker Flags build setting.

Troubleshooting

If adding the -ObjC flag isn't fixing the problem, double check that a conflicting Target build setting is not overriding it, by following the above steps, but selecting the current target under "TARGETS" in step 2, instead of the project.

Solve the problem

  If you add -ObjC flagnot solve the problem, check the previous operation to ensure that no conflict with Target build setting and make it invalid. Accordance with the above steps, the second step when selecting "the TARGETS" target under, rather than selecting project.

Other Causes of selector not recognized Exceptions

The most common causes of a "selector not recognized" exception are:

No Such Method

The method really does not exist. Check your spelling. Check documentation to verify that the method exists on the version of the operating system your app is using.

Memory Management

Your app is trying to use an object after it has been deallocated, use the Zombies instrument to debug this kind of problem. You are seeing "selector not recognized" because the memory has been re-allocated as a different kind of object.

Lead to selector not recognized Exceptionsother causes abnormal

  Cause selector not recognized Exceptionscause of the abnormality is usually:

Method does not exist

  The method actually does not exist. Check if your spelling is incorrect. Consult the documentation, make sure you call the method of memory in the current version of the operating system.

Memory Management

  After the object has been released, your application and try to access it, the original target storage memory has been re-assigned to other classes of objects, so when you visit the original object again, it will happen "selector not recognized" exception. Use Zombies instrumenttools to debug this problem. (This section of the document is not fluent, slightly rearranged)

What causes those exceptions?

An impedance mismatch between UNIX static libraries and the dynamic nature of Objective-C can cause category methods in static libraries to not be linked into an app, resulting in "selector not recognized" exceptions when the methods aren't found at runtime.

Cause these abnormalities cause

Because of UNIX static librariesand dynamic nature of Objective-Creason is not a good fit, resulting in classification method static library will not be linked to the app go, that they can not find a way in the runtime dynamic invocation, the result of "selector not recognized" exception occurs.

The Linker

When a C program is compiled, each "source file" is turned into an "object file" that contains executable functions and static data. The linker glues these object files together into a final executable. That executable is eventually bundled into an app by Xcode.

Linker

When a C program is compiled, all the "original file" are converted to "object file", the "object file" contains the executable and static data. These links will "object file" bonded together, eventually became an executable file. Xcode will eventually packaged into these executable files in the APP.

When a source file uses something (like a function) defined in another file, then an undefined symbol is written into the object file, to "stand in" for the missing thing. The linker resolves these symbols by pulling in the object files that include definitions of undefined symbols when building the final executable.

When an original document invokes methods defined in other documents or data, then a 未经定义的符号is written to the "object file", is used in place of the missing data or methods. When the composition of the final executable file, the linker extracts from those defined comprising "undefined symbols" definition "object files" to parse symbols.

For example, if main.c uses the function foo(), where foo is defined in another file, B.c, then the object file main.o will have an unresolved symbol for foo(), and B.o will include an implementation of foo(). At link time, B.o will be brought into the final executable, so that the code in main.o now references the implementation of foo() defined in B.o.

For example, if the main.ccalling method foo(), and foofunction in another file B.cdefinition, then object file main.othere will be an unresolved symbol represents foo(), and B.owill contain foo()methods. In the link stage, B.oit will be brought into the final executable file, so now main.othe code can be referenced in B.othe for foo()implementation.

A UNIX static library is just a collection of object files. Normally the linker only pulls in an object file from a static library if doing so would resolve some undefined symbol. Not pulling in all object files reduces the size of the final executable.

A UNIX static libraryjust object filestogether. The linker usually only from the static libraryextracts that contain the undefined symbolobject file parsing, and not all object filesare integrated in. This can reduce the volume of the final executable file.

Objective-C

The dynamic nature of Objective-C complicates things slightly. Because the code that implements a method is not determined until the method is actually called, Objective-C does not define linker symbols for methods. Linker symbols are only defined for classes.

Objective-C

OC dynamic characteristics make this process a little complicated a little. Because the code that implements a method until this method is called will be determined. Objective-C is not defined as a method of symbolic links, the link symbol only for the class definition.

For example, if main.m includes the code [[FooClass alloc] initWithBar:nil]; then main.o will contain an undefined symbol for FooClass, but no linker symbols for the -initWithBar: method will be in main.o.

For example: If this code main.m contains: [[FooClass alloc] initWithBar:nil];then main.oit will contain undefined symbol represents FooClass, but in the main.ofile, does not generate the link symbol to represent -initWithBar:the method.

Since categories are a collection of methods, using a category's method does not generate an undefined symbol. This means the linker does not know to load an object file defining the category, if the class itself is already defined. This causes the same "selector not recognized" runtime exception you would see for any unimplemented method.

Because the classification is a set of methods, if a class has been defined, in which a classification method is not generated undefined symbol, which means that the linker does not need to know the load corresponding object fileto the defined classification. Call any method to achieve the same will not lead to "selector not recognized" runtime exception.

The -ObjC Linker Flag

Passing the -ObjC option to the linker causes it to load all members of static libraries that implement any Objective-C class or category. This will pickup any category method implementations. But it can make the resulting executable larger, and may pickup unnecessary objects. For this reason it is not on by default.

The -ObjC Linker Flag

Specify the linker -ObjCoption enables the linker to load all static libraries total members, including Objective-Cthe type and classification. This will be elected to the realization of all classification methods. But also to make the most of the final executable file size is bigger, which is why not as the default option.

to sum up

YYKit in this macro is defined in the classification before adding an empty class, this .mfile contains the class, so the resulting .ofile will be packaged into the final executable file link, thereby avoiding the occurrence of an abnormality "selector not recognized" .

Guess you like

Origin www.cnblogs.com/miaocunfa/p/11585988.html