Runtime mechanism Method Learning

Source: Internet
Author: User

Runtime this thing is not known for the first time, after knowing it is the mechanism of OC Dynamic language, without it that OC can not be called Dynamic language. Before it was possible that everyone knew about the runtime, as programming skills deepened and needed, everyone began to be more concerned with the underlying implementation and in the way they needed it more. At this time the runtime began to fire slowly, as an iOS programmer, if go out to say that they do not know runtime is undoubtedly a very lost point of things. Because the runtime of the bottom implementation of the author did not make too clear, here is to mention a few about the runtime method.

Dynamic addition of 1.runtime properties

When I first learned about OC, I was sure everyone had heard that attributes could not be added to the class. And I'm going to do this here. Add a block property to UIButton to make it easy to implement the click Method. First create a UIButton class (Uibutton+block), and then we'll implement

 1  uibutton+block.h file  2  //  define a block  3  typedef void  (^actionblock) (UIButton * sender);  4  @ Interface   UIButton (Block)  6  Span style= "color: #008000;" >//  Define the method when the button uses a block  7 -(void  ) Handleclickevent: ( uicontrolevents) aevent Usingblock: (actionblock) block;  8   @end  

The. h file is easier to read than to explain, followed by. m files

1 //define keywords for adding attributes2 Static Char*Overviewkey;3 @implementationUIButton (Block)4 5- (void) Handleclickevent: (uicontrolevents) aevent Usingblock: (actionblock) block{6     //set the associated object (the associated person, keyword, association, attribute State)7Objc_setassociatedobject (Self, &Overviewkey, block, objc_association_copy_nonatomic);8     //Add a Click event to a button9 [Self addtarget:self Action: @selector (buttonclicked:) forcontrolevents:aevent];Ten } One  A- (void) buttonclicked: (UIButton *) sender{ -     //Gets the associated object (the associated person, keyword) -Actionblock Clickedblock = Objc_getassociatedobject (self, &overviewkey); the     //Block is called if block exists -     if(Clickedblock! =Nil) { - Clickedblock (sender); -     } +}

Here objc_setassociatedobject(< #id Object#>, < #const void *key#>, < #id Value#>, < #objc_ Associationpolicy policy#>)

will be the runtime method. This method has 4 parameters, the first of which is the category: self (to whom the attribute is added), the second argument is the Property keyword: &overviewke (which is the identifier for the property), the third argument is the property: Block (the property to add), and the fourth parameter is the property modifier: objc_association_copy_nonatomic (as the modifier for the property, Nonatomic,copy). With this method, we can dynamically add properties to a class.

This method is simpler when the property is added and we need to get this property objc_getassociatedobject(< #id Object#>, < #const void *key#>). Note Here is the Property keyword, because to ensure that the scope of the property keyword, so the use of static as its modifier, and because the runtime mechanism is a C language implementation, so here the keyword needs to use the char type!

After the definition of the use of a simple straight line of code to use

1 // define a UIButton and use its methods 2 [button handleclickevent:uicontroleventtouchupinside usingblock:^ (UIButton *sender) {3         NSLog (@ " you clicked the%@ button ", [sender currenttitle]); 4     }];

It is easier to understand and read the UIButton Click events that are rewritten by the runtime.

How to use the 2.runtime archive

In a custom class archive, we need to write the property one by one, in the case of fewer attributes may not feel any problem, but if the property is more, this kind of writing is clumsy, here we use the runtime method to dynamically get its properties, and write.

First create a new class yourself, here I created a Bqperson class

1 BQPerson.h File2 @interfaceBqperson:nsobject <NSCoding>3 //Suppose there are dozens of properties here.4@property (nonatomic, copy) NSString *name;5@property (nonatomic, copy) NSString *Crad;6@property (nonatomic, copy) NSString *birthday;7 @property (nonatomic, assign) Nsinteger age;8@property (nonatomic, copy) NSString *iphone;9@property (nonatomic, copy) NSString *adress;Ten @property (nonatomic, assign) cgfloat height; One @property (nonatomic, assign) cgfloat weight; A  - @end

We then implement the archive in the. m file through the runtime.

1- (ID) Initwithcoder: (Nscoder *) adecoder{2     if(self =[Super Init]) {3         //define length4Unsignedintindex =0;5         //dynamically getting an array of member variables6Ivar *ivars = Class_copyivarlist ([selfclass], &index);7          for(inti =0; I < index; i++) {8             //Remove Variables9Ivar Ivar =Ivars[i];Ten             //Get variable name One             Const Char*name =Ivar_getname (Ivar); A             //output attribute name and its in-memory offset -NSLog (@"%s%TD", Name,ivar_getoffset (Ivar)); -             //Solution: How to call the Decodeobjectforkey theNSString *key =[NSString Stringwithutf8string:name]; -             IDValue =[Adecoder Decodeobjectforkey:key]; -             //Assign Value - [self setvalue:value forkey:key]; +         } -         //Since this is the C language used, you need to manage your memory manually + Free (ivars); A     } at     returnSelf ; - } -  -- (void) Encodewithcoder: (Nscoder *) acoder{ -     //define length -Unsignedintindex =0; in     //dynamically getting an array of class member variables -Ivar *ivars = Class_copyivarlist ([selfclass], &index); to      for(inti =0; I < index; i++) { +         //remove the corresponding variable -Ivar Ivar =Ivars[i]; the         //gets the name of the variable taken out *         Const Char*name =Ivar_getname (Ivar); $         //Archive: Archive Call method Encodeobject:forkey:Panax NotoginsengNSString *key =[NSString Stringwithutf8string:name]; -         IDValue =[self valueforkey:key]; the [Acoder encodeobject:value Forkey:key]; +     } A     //releases the array of variables obtained the Free (ivars); +}

Here we first use class_copyivarlist(< #__unsafe_unretained class Cls#>, < #unsigned int *outcount#>) method to get an array of member variables for a class, where the first argument is a class: [Self Class] (gets the member variable of the class), and the second argument is an unsigned integer pointer: index (to record the length of the array). Next we return the name of a variable by ivar_getname(< #Ivar v#>) and then convert the name to the NSString type. Can be unpacked and archived. It is important to note that this is because C language is used, so the array needs to be released manually!

3.runtime Method of Exchange

After the project becomes larger, because the function needs us to achieve 2 methods of exchange, if a change in the code is relatively difficult, here we can use the runtime through a few lines of code to directly exchange the 2 methods we need to exchange. Examples are as follows:

1+ (void) load{2     Staticdispatch_once_t Oncetoken;3Dispatch_once (&oncetoken, ^{4Method Testfirst =Class_getinstancemethod (Self, @selector (Testfirst));5Method secondtest =Class_getinstancemethod (Self, @selector (secondtest));6         if(Testfirst! = Nil && secondtest! =Nil) {7 method_exchangeimplementations (Testfirst, secondtest);8}Else{9NSLog (@"method Get failed");Ten         } One     }); A } -  -- (void) Viewdidload { the [Super Viewdidload]; -      - [self testfirst]; - [self secondtest]; + } -  +- (void) testfirst{ ANSLog (@"1===%s", __func__); at } -- (void) secondtest{ -NSLog (@"2===%s", __func__); -}

According to the normal procedure in Viewdidload should be the first to go Testfirst method, and then go Secondtest method, but here we in load (class first loaded into memory when the call) method used

Class_getinstancemethod (< #__unsafe_unretained class Cls#>, < #SEL name#>) returns a method with the first argument: self (class instance object), second argument: @selector (Testfirst) (method selector, select a method). Finally we use method_exchangeimplementations(< #Method M1#>, < #Method m2#>) to dynamically exchange the 2 methods obtained, So in the exchange of the method implementation, the 2 methods are interchangeable, it is important to note that after the exchange, the exchange is the implementation of 2 methods of the address , such as calling the [self Testfirst] method will go Secondtest Method!

4.runtime the Assgin modifier has the attribute of the weak modifier (the object does not exist with the nil attribute)

Because this method is not practical, only as a theoretical supplement so simple description can be, the first to add a property to the NSObject object, if the object is destroyed before destroying its properties, then the property is destroyed when the object is set to nil. The following are the specific practices

4.1. Overriding the set method of Assgin

-(void) Settestview: (UIView *) testview{    = TestView;    [TestView psp_rundealloc:^{        = nil;    }];}

4.2. Write a nsobject category and dynamically add a property

-(void) Psp_rundealloc: (void (^) ()) block{    if  (block) {        * PSPOBJC = [[Pspobjectblock alloc] initwithblock:block];         " PSPOBJC " , PSPOBJC, Objc_association_retain);}    }

The internal implementation of the 4.3.PSPOBJC attribute is as follows

  @interface   Pspobjectblock () {Blocktest _ Block;}   @end   @implementation   Pspobjectblock - (Instancetype) Initwithblock    :(blocktest) block{self  = [super Init];  if   = [block copy];  return   self;}  //  call block when destroying to make non-weak property values Nil -(void  ) dealloc{ if   (_block) {_block (); }}

Interested friends can try to achieve this method, about the runtime knowledge of the record to share it here, if there are any errors, I hope you point out, thank you!

Runtime mechanism Method Learning

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.