IOS Runtime Runtime

Source: Internet
Author: User

The OBJC runtime makes C an object-oriented capability to create, inspect, modify, and alter classes, objects, and their methods while the program is running. (Runtime is written in C and assembly)

Runtime system is a series of functions and data structure of the public interface dynamic shared Library, in the/USR/INCLUDE/OBJC directory can see the header file, you can use some of these functions through C language to achieve the same function in Objective-c.

Runtime is also called Runtime, is a set of low-level C language API, which is one of the core of IOS internal, we usually write the OC code, the bottom is based on it to achieve.

Objective-c is a dynamic language that puts some work into the code when it is run and not at compile time. In other words, there are many classes and member variables that we do not know when we compile, and at run time, the code we write is translated into full, deterministic code execution.

Therefore, the compiler is not enough, and we also need a runtime system to handle the compiled code.

the OBJC_CLASS structure in objc/runtime.h is defined as follows:
struct Objc_class {class ISA objc_isa_availability;//isa pointer to Meta class, because the OBJC class itself is also an object, in order to handle this relationship, Runtime creates the Meta class, and when it sends a message to the class [NSObject alloc], it is actually sending the message to class object#if!__objc2__class Super_class objc2_ unavailable; Parent Class const char *name objc2_unavailable; Class name long version objc2_unavailable; The version information of the class, which defaults to 0long info objc2_unavailable; Class information for the run-time use of some bit ID long instance_size objc2_unavailable; The instance variable size of the class struct objc_ivar_list *ivars objc2_unavailable; The member variables of this class are linked list struct objc_method_list **methodlists objc2_unavailable; Method definition of the linked list struct objc_cache *cache objc2_unavailable; Method cache, the object to a message will look for the message object according to the ISA pointer, which will be traversed in the methodlists, if the cache, the usual method calls can improve the efficiency of the call. struct Objc_protocol_list *protocols objc2_unavailable; Protocol chain List #endif} objc2_unavailable;

Objc_object is an instance struct of a class, and objc/objc.h is defined as an instance struct of a class Objc_object:
struct Objc_object {Class isa objc_isa_availability;}; typedefstruct Objc_object *id;

When you send a message to object, the runtime library finds the class that this instance belongs to, based on the ISA pointer of object, and then finds the corresponding method to run in the class's method list and the parent class method list. An ID is a pointer to a objc_object struct type that can be converted to any object.

Meta class: The class of a class object, when sending a message to an object, runtime looks for a method to send a message to the object's list of class methods, but when a message is sent to the class, runtime looks in the class's Meta class method column. All meta classes, including the root Class,superclass,subclass Isa, point to the root class's meta class, which creates a closed loop.

Associating objects using
//dynamically connects a tap gesture operation to any uiview. -(void) Settapactionwithblock: (void (^) (void)) block{UITapGestureRecognizer *gesture = Objc_getassociatedobject (self     , &kdtactionhandlertapgesturekey); if (!gesture) {gesture = [[UITapGestureRecognizer alloc] initwithtarget:self action: @selector (__handleaction          Fortapgesture:)];          [Self addgesturerecognizer:gesture]; Objc_setassociatedobject the created gesture object and block as the associated object (self, &kdtactionhandlertapgesturekey, gesture, Objc_associati     On_retain); } objc_setassociatedobject (self, &kdtactionhandlertapblockkey, block, objc_association_copy);} Target and action-(void) __handleactionfortapgesture for gesture recognition objects: (UITapGestureRecognizer *) gesture{if (gesture.state = = uigesturerecognizerstaterecognized) {void (^action) (void) = Objc_getassociatedobject (self, &kdtactionhand          Lertapblockkey);          if (action) {action (); }     }}
Method call Flow

The message function, which sends a message in OBJC, encloses the receiver and the message in brackets, and binds the message and method only until run time.

Method swizzling

is to change the actual implementation of a selector technology, you can modify the selector corresponding function at run time to modify the method implementation. However, when some classes cannot modify their source code and change their method implementations, you can use method swizzling to achieve the goal by remapping the method, but it is difficult to debug with message forwarding.

    • Swizzling should always be executed in +load: Objective-c automatically calls the class's two methods +load and +initialize at run time. +load will be called when the class is initially loaded, and the +initialize comparison +load can be guaranteed to be loaded during the initialization of the class
    • Swizzling should always be executed in dispatch_once: Swizzling will change the global state, so take some precautions at runtime and use Dispatch_once to ensure that the code is executed only once, regardless of the number of threads. This will be a best practice for method swizzling.
    • Selector,method and implementation: These relationships can be understood in such a way that a class maintains a message that can be received at runtime, and each entry in the sub-publication is a method, where key is a specific name, and the SEL, The corresponding implementation is a pointer to imp, which points to the underlying C function.

#import <objc/runtime.h> @implementation Uiviewcontroller (Tracking) + (void) load {static dispatch_once_t Oncetok     En          Dispatch_once (&oncetoken, ^{class = [self class];          When swizzling a class method with the following://Class class = Object_getclass ((id) self); The pointer to Uiviewcontroller's @selector (viewwillappear:) was modified by method swizzling to point to the custom xxx_viewwillappear SEL Originalsele          ctor = @selector (viewwillappear:);          SEL swizzledselector = @selector (xxx_viewwillappear:);          Method Originalmethod = Class_getinstancemethod (class, Originalselector);          Method Swizzledmethod = Class_getinstancemethod (class, Swizzledselector); BOOL Didaddmethod = Class_addmethod (class, Originalselector, Method_getimplementation (swizzled          Method), method_gettypeencoding (Swizzledmethod)); If the method that you want to replace does not exist in the class, add and replace the two method implementations with the Class_addmethod and Class_replacemethod functions first. But if you already have the method you want to replace, call theThe Method_exchangeimplementations function swaps the implementation of two methods. if (Didaddmethod) {Class_replacemethod (class, Swizzledselector, Metho          D_getimplementation (Originalmethod), method_gettypeencoding (Originalmethod));          } else {method_exchangeimplementations (Originalmethod, Swizzledmethod); }     });}     #pragma mark-method swizzling-(void) Xxx_viewwillappear: (BOOL) animated {[Self xxx_viewwillappear:animated]; NSLog (@ "viewwillappear:%@", self);} @end

Runtime application gets information about the library provided by the system

Main functions

Gets the name of all loaded objective-c frames and dynamic Libraries const char * * OBJC_COPYIMAGENAMES (unsigned int *outcount);//Gets the dynamic Library const char * class where the specified class is located _getimagename (class CLS);//Gets the class name of all classes in the specified library or framework const char * * OBJC_COPYCLASSNAMESFORIMAGE (const char *image, unsigned int *outcount);

These functions enable you to get all the libraries of a class and which classes are included in a library

NSLog (@ "Get the dynamic library of the specified class"); NSLog (@ "UIView ' s Framework:%s", Class_getimagename (nsclassfromstring (@ "UIView")); NSLog (@ "Gets the class name of all classes in the specified library or frame"); const char * * classes = Objc_copyclassnamesforimage (Class_getimagename (nsclassfromstring ( @ "UIView")), &outcount), for (int i = 0; i < Outcount; i++) {NSLog (@ "Class name:%s", Classes[i]);}Results 2014-11-08 12:57:32.689 [747:184,013] Gets the specified class's dynamic library 2014-11-08 12:57:32.690 [747:184013] UIView ' s Framework:/system/ library/frameworks/uikit.framework/uikit2014-11-08 12:57:32.690 [747:184,013] Gets the class name of all classes in the specified library or frame 2014-11-08 12:57:32.691 [747:184013] class name:uikeyboardpredictivesettings2014-11-08 12:57:32.691 [747:184013] class Name: _ uipickerviewtopframe2014-11-08 12:57:32.691 [747:184013] class name: _uionepartimageview2014-11-08 12:57:32.692 [ 747:184013] class Name: _uipickerviewselectionbar2014-11-08 12:57:32.692 [747:184013] class Name: _ uipickerwheelview2014-11-08 12:57:32.692 [747:184013] class name: _uipickerviewtestparameters ...
Tracking the user behavior of the app

is to record the event when the user clicks. The general comparison is to record events in the Viewdidappear, so that the code that logs events is spread throughout the project. Inheritance or categorization can also be problematic. By using method swizzling, we replace the implementation of one approach with the implementation of another.

First define a category, add a method to swizzled @implementation Uiviewcontroller (Logging)-(void) Swizzled_viewdidappear: (BOOL) animated{/ /Call original implementation [self swizzled_viewdidappear:animated]; Logging [Logging Logwitheventname:nsstringfromclass ([self class]);} Next implement the Swizzle method @implementation Uiviewcontroller (Logging) void Swizzlemethod (class class, Sel Originalselector, SEL Swizzledselector) {//The method might not exist in the class, but in its superclass method Originalmethod = Class_ge     Tinstancemethod (class, Originalselector); Method Swizzledmethod = Class_getinstancemethod (class, Swizzledselector); Class_addmethod would fail if original method already exists BOOL Didaddmethod = Class_addmethod (class, Originalsele ctor, Method_getimplementation (Swizzledmethod), method_gettypeencoding (Swizzledmethod)); The method doesn ' t exist and we just added one if (didaddmethod) {Class_replacemethod (class, Swizzledsele ctor, Method_getimplementation (Originalmethod), method_gettypeencoding (Originalmethod));     } else {method_exchangeimplementations (Originalmethod, Swizzledmethod); }}//finally make sure to call the Swizzlemethod method at the start of the program to add +load in the previous Uiviewcontroller logging Category: Method, and then in +load: Replace the viewdidappear with @implementation Uiviewcontroller (Logging) + (void) load{Swizzlemethod ([self class], @selector ( Viewdidappear:), @selector (swizzled_viewdidappear:));} Simpler to replace the original IMP directly with the new IMP, instead of replacing it, it is only necessary to have a global function pointer pointing to the original imp. void (goriginalviewdidappear) (ID, SEL, bool), void Newviewdidappear (Uiviewcontroller *self, sel _cmd, BOOL animated) {//C All original implementation goriginalviewdidappear (self, _cmd, animated); Logging [Logging Logwitheventname:nsstringfromclass ([self class]);}     + (void) load{Method Originalmethod = Class_getinstancemethod (self, @selector (viewdidappear:)); Goriginalviewdidappear = (void *) method_getimplementation (Originalmethod); if (!class_addmethod (self, @selector (viewdidappear:), (IMP) newviewdidappear, method_gettypeencoding (OriginalmEthod)) {method_setimplementation (Originalmethod, (IMP) newviewdidappear); }}
 







IOS Runtime Runtime

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.