Objective-C Object Model and Application

Source: Internet
Author: User

Preface

Original article. For more information, see Tang Qiao's technical blog.

This article mainly introduces the implementation details of the Objective-C object model andisa swizzlingAndmethod swizzling. I hope this article will help you better understand Objective-C objects.

ISA pointer

Objective-C is an object-oriented programming language. Every object is an instance of a class. In Objective-C, each object has a pointer named isa pointing to the class of the object. Each class describes the characteristics of a series of its instances, including the list of member variables and the list of member functions. Each object can receive messages, and the list of messages that the object can receive is saved in its corresponding class.

PressShift + Command + OInput NSObject. h and objc. h to open the NSObject definition header file. We can see through the header file that NSObject is a struct containing the isa pointer, as shown in:

According to the design principles of object-oriented language, everything should be an object (strictly speaking, Objective-C does not fully implement this because it has simple variable types such as int and double ). In Objective-C, every class is actually an object. Each class also has a pointer named isa. Each class can also accept messages, such[NSObject alloc]Is to send the name to the NSObject classallocMessage.

PressShift + Command + OEnter runtime. h to open the Class definition header file. We can see through the header file that the Class is also a struct containing the isa pointer, as shown in. (In the figure, there are other member variables besides isa, but they are used to be compatible with the legacy logic of Objective-C in non-Version 2.0. You can ignore this variable .)

Because a class is an object, it must also be a real column of another class. This class is a metadata class (metaclass). The metadata class saves the list of class methods. When a class method is called, The Meta class first checks whether it has the implementation of this class method. If not, the Meta class searches for this method from its parent class, until the inheritance chain header is found.

Metadata (metaclass) Is also an object, so where does the isa pointer of the Meta class point? For the sake of design integrity, the isa pointer of all meta classes will point to a root Meta class (rootmetaclass). The isa pointer of the root metaclass itself points to itself, thus forming a closed loop. As mentioned above, the list of messages that an object can receive is saved in the corresponding class. In actual programming, we almost never encounter the situation of sending messages to the Meta class, so its isa pointer is rarely used in reality. However, this design ensures that object orientation is clean, that is, everything is an object and there is an isa pointer.

Let's take a look at the inheritance relationship, because the class method definition is saved in the Meta class (metaclass), And the method calling rule is that if the class does not have a method implementation, it continues to search for its parent class. Therefore, to ensure that the class method of the parent class can be called in the subclass, the Meta class of the subclass will inherit the Meta class of the parent class. In other words, class objects and metadata objects have the same inheritance relationship.

I would like to clarify the relationship, but this part is indeed a bit difficult. The figure below may give you a clearer picture of the relationship between isa and inheritance (this picture is from here)

In this figure, the most confusing thing is the Root Class. In implementation, the Root Class refers to NSObject. We can see that:

  1. The NSObject class includes its object instance method.
  2. The NSObject metadata includes its class methods, such as the alloc method.
  3. The NSObject metadata class inherits from the NSObject class.
  4. The methods in an NSObject class are also found by NSObject subclass during method search. Class member variables

    If you think of an instance of the class as a structure (struct) of C language, the isa pointer mentioned above is the first member variable of the structure, and other member variables of the class are arranged in the structure in sequence. Shows the order (picture from iOS 6 Programming Pushing the Limits):

    To verify this statement, we create a new project in XCode and run the following code in main. m:

    12345678910111213141516171819202122232425262728293031
    #import 
            
             @interface Father : NSObject {    int _father;}@end@implementation Father@end@interface Child : Father {    int _child;}@end@implementation Child@endint main(int argc, char * argv[]){  Child * child = [[Child alloc] init];  @autoreleasepool {      // ...  }}
            

    We place the breakpoint under@autoreleasepoolAnd enterp *child, You can see that Xcode outputs the following content, which is consistent with the above statement.

    12345678910
    (lldb) p *child(Child) $0 = {  (Father) Father = {    (NSObject) NSObject = {      (Class) isa = Child    }    (int) _father = 0  }  (int) _child = 0}
    Variable and immutable

    Because the object layout in the memory can be regarded as a struct, the size of the struct cannot be changed dynamically. Therefore, the member variables cannot be dynamically added to the object at runtime.

    The method definitions of objects are stored in the Variable Area of the class. Objective-C 2.0 is not exposed in the header file, but in Objective-C 1.0, we can see that the definition list of a method is namedmethodListsAs shown in ). By modifying the pointer value to which the Pointer Points, You can dynamically add member methods to a class. This is alsoCategoryImplementation principle. It also explains whyCategoryOnly member methods can be added for objects, but member variables cannot be added.

    Please note thatobjc_setAssociatedObjectAndobjc_getAssociatedObjectThe method can add member variables to an object in disguise. However, because the implementation mechanism is different, it does not actually change the memory structure of the object.

    In addition to the object method, isa itself is also a pointer, so we can dynamically modify the isa pointer value at runtime to replace the entire object behavior. However, this application scenario is rare.

    System related API and application isa swizzling

    The implementation of KVO provided by the system uses the technology of dynamically modifying the value of the isa pointer. You can see the following description in Apple's document:

    Key-Value Observing Implementation Details

    Automatic key-value observing is implemented using a technique called isa-swizzling.

    The isa pointer, as the name suggests, points to the object's class which maintains a dispatch table. This dispatch table essential tially contains pointers to the methods the class implements, among other data.

    When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class. as a result the value of the isa pointer does not necessarily reflect the actual class of the instance.

    You shoshould never rely on the isa pointer to determine class membership. Instead, you shoshould use the class method to determine the class of an object instance.

    Similarly, Key-Value Coding (KVC) provided by the system is also used in isa swizzling technology ).(Thank you for pointing out the error. KVC does not use isa swizzling)

    Method Swizzling API description

    Objective-C provides the following APIs to dynamically Replace the implementation of class methods or instance methods:

    • class_replaceMethodDefinition of Replacement Methods
    • method_exchangeImplementationsImplement the exchange of two methods
    • method_setImplementationSet the implementation of one method

      There are some minor differences between the three methods. We will introduce them as follows:

      • class_replaceMethodIn Apple's document (as shown in), there are two different behaviors. This method is called when there is no original method to be replaced in the class.class_addMethodTo add a new method for this class,class_replaceMethodYou need to inputtypesParameters, whilemethod_exchangeImplementationsAndmethod_setImplementationBut not required.

        • method_exchangeImplementationsThe internal implementation of is actually called twicemethod_setImplementationMethod, which can be clearly understood from Apple's documentation (as shown in)

          From the above differences, we can summarize the application scenarios of these three APIs:

          • class_replaceMethodIf the method to be replaced does not exist, consider using this method.
          • method_exchangeImplementations, Used when two methods need to be exchanged for implementation.
          • method_setImplementationThe simplest method is to set the implementation method for a method. Example

            We need to use the system'sUIImagePickerController. However, in the iOS6.0.2 systemUIImagePickerControllerThere is a screen rotation Bug in the horizontal screen of the iPad, which leads to a wrong direction. For details about specific bugs, see here.

            To fix this Bug, we need to replaceUIImagePickerControllerThe following two methods

            12
            - (BOOL)shouldAutorotate;- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;

            We first implementedImagePickerReplaceMethodsHolderClass, used to define the method and implementation after replacement. As follows:

            123456789101112131415161718192021
            // ImagePickerReplaceMethodsHolder.h@interface ImagePickerReplaceMethodsHolder : NSObject- (BOOL)shouldAutorotate;- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;@end// ImagePickerReplaceMethodsHolder.m@implementation ImagePickerReplaceMethodsHolder- (BOOL)shouldAutorotate {    return NO;}- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {    return UIInterfaceOrientationPortrait;}@end

            Then, we can determine the current iOS version at the call. For versions between [iOS6.0, iOS6.1), we willUIImagePickerControllerReplacement of problematic methods. The Code is as follows:

            123456789101112131415161718192021222324
            #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)+ (void)load {    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        [self hackForImagePicker];    });}+ (void)hackForImagePicker {    // fix bug of image picker under iOS 6.0    // http://stackoverflow.com/questions/12522491/crash-on-presenting-uiimagepickercontroller-under-ios-6-0    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")        && SYSTEM_VERSION_LESS_THAN(@"6.1")) {        Method oldMethod1 = class_getInstanceMethod([UIImagePickerController class], @selector(shouldAutorotate));        Method newMethod1 = class_getInstanceMethod([ImagePickerReplaceMethodsHolder class], @selector(shouldAutorotate));        method_setImplementation(oldMethod1, method_getImplementation(newMethod1));        Method oldMethod2 = class_getInstanceMethod([UIImagePickerController class], @selector(preferredInterfaceOrientationForPresentation));        Method newMethod2 = class_getInstanceMethod([ImagePickerReplaceMethodsHolder class], @selector(preferredInterfaceOrientationForPresentation));        method_setImplementation(oldMethod2, method_getImplementation(newMethod2));    }}

            Through the above Code, we Patch the problematic system library functions in a specific version of iOS to solve the problem.

            Use of Open Source

            A few people who do not know the truth think that Apple will reject the App's use of the above APIs during the review, which is actually a misunderstanding of apple. It is safe to use the above APIs. In addition, the open source community also applies the above methods. For example:

            • The famous network library AFNetworking. AFNetworking network library (v1.x version) uses the class_replaceMethod method (105th rows of AFHTTPRequestOperation. m file)
            • Nimbus. Nimbus is a famous tool library, which providesNIRuntimeClassModifications.hFile used to encapsulate the preceding APIs.
            • IOS client for public comment in China. The client uses the Wax-based WaxPatch developed by them. WaxPatch can dynamically modify the client logic through server updates. WaxPatch mainly modifies the wax_instance.m file in wax, and adds class_replaceMethod to replace the original implementation, so as to modify the original behavior of the client. Summary

              Through this article, we learned about the Objective-C language object model and the Objective-C language object modelisa swizzlingAndmethod swizzling. This article also gives us a deeper understanding of the dynamic nature of the object model through specific instance code and open-source projects.

              Postscript

              After the article was published, some colleagues pointed out that the internal structure of isa has changed under the ARM64 CPU. I know this, but I hope I will discuss it later. If you are interested, you can view the video Session 404 Advanced in Objective-C from Apple's WWDC2013 this year.

              Reference
              • Https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Introduction/Introduction.html
              • Http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
              • Http://www.devalot.com/articles/2011/11/objc-object-model.html
              • Http://www.cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html
              • Http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html
              • Gunstep implementation source code
              • Http://algorithm.com.au/downloads/talks/objective-c-internals/objective-c-internals.pdf
              • Http://opensource.apple.com/source/objc4/objc4-532/runtime/
              • Https://github.com/AFNetworking/AFNetworking
              • Https://github.com/jverkoey/nimbus
              • Https://github.com/mmin18/waxpatchthis article published by: http://blog.devtang.com/, original address: http://blog.devtang.com/blog/2013/10/15/objective-c-object-model/, thank you for sharing.

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.