Application of runtime mechanism in OBJECTIVE-CFirst, the initial knowledge of the runtime
Objective-c is a dynamic language, the so-called dynamic language, is in the execution of the program dynamically determine the variable type, the implementation of variable type corresponding method. Therefore, the technique of string mapping classes is used in Object-c to dynamically create class objects. Because of the dynamic language characteristics of OC, we can change the object's variables and even methods dynamically when the program is running, which is what we call the runtime mechanism.
Second, do you have any way to manipulate such variables?
First, let's take a look at an example where I created a MyObject class:
//.h===========================
@interface MyObject : NSObject
{
@private
int privateOne;
NSString * privateTow;;
}
@end
//=============================
//.m===========================
@interface MyObject()
{
@private
NSString * privateThree;
}
@end
@implementation MyObject
- (instancetype)init
{
self = [super init];
if (self) {
privateOne=1;
[email protected]"Tow";
[email protected]"Three";
}
return self;
}
-(NSString *)description{
return [NSString stringWithFormat:@"one=%d\ntow=%@\nthree=%@\n",privateOne,privateTow,privateThree];
}
@end
//=============================
This class is quite safe, first of all, in the header file does not provide any method interface, we have no way to use dot syntax to do any operation, Privateone and Privatetow two variables, although declared in the header file, but is a private type, through the way of pointers we can see them, But you can't do anything to read the changes, the following are the hints in Xcode:
He will tell us that this is a private variable that we cannot use. For Privatethree, we are helpless, not only can not use, we can not even see its existence. So what are some of the ways you can manipulate these variables? Yes, it's time to show the real technology: runtime!
third, get the variable list of the object through the runtime
To manipulate the variables of the object, we should first capture these variables, so that they have no place to hide. Whether the declaration is in the header file or the implementation file, whether the type is public or private, as long as the variable is declared, the system allocates space for it, we can capture it through the runtime mechanism, the code is as follows:
#import "ViewController.h"
#import "MyObject.h"
// Contains runtime header files
#import <objc / runtime.h>
@interface ViewController ()
@end
@implementation ViewController
-(void) viewDidLoad {
[super viewDidLoad];
// We first declare an unsigned int pointer and allocate memory for it
unsigned int * count = malloc (sizeof (unsigned int));
// Call the runtime method
// Ivar: the object content object returned by the method, here will return a pointer of type Ivar
// class_copyIvarList method can capture all the variables of the class, and store the number of variables in an unsigned int pointer
Ivar * mem = class_copyIvarList ([MyObject class], count);
// traverse
for (int i = 0; i <* count; i ++) {
// traverse by moving the pointer
Ivar var = * (mem + i);
// Get the name of the variable
const char * name = ivar_getName (var);
// Get the type of the variable
const char * type = ivar_getTypeEncoding (var);
NSLog (@ "% s:% s \ n", name, type);
}
// Free up memory
free (count);
// Pay attention to handling wild pointers
count = nil;
}
-(void) didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
The results are printed as follows, where I represents the int type :
is not a little surprised, no matter where the variable, as long as it is in, let it nowhere to hide.
Four, let me find you, let me change you!
It may not be possible to get the type and name of a variable, but it is not the case that we get the variable for the purpose of viewing it, but to manipulate it, which is a trivial matter for runtime. The code is as follows:
-(void) viewDidLoad {
[super viewDidLoad];
// Get variables
unsigned int count;
Ivar * mem = class_copyIvarList ([MyObject class], & count);
// create object
MyObject * obj = [[MyObject alloc] init];
NSLog (@ "before runtime operate:% @", obj);
// Setting variables
object_setIvar (obj, mem [0], 10);
object_setIvar (obj, mem [1], @ "isTow");
object_setIvar (obj, mem [2], @ "isThree");
NSLog (@ "after runtime operate:% @", obj);
}
TIP: When modifying an int variable, you may encounter a problem where, under arc, the compiler does not allow you to assign the value of the int type to the ID, and in buildset objective-c Automatic Reference counting is modified to No.
The printing effect is as follows:
As you can see, the variables that appear to be very safe are modified by us.
let me have a look at your method.
Variables through the runtime mechanism we can take and change the value, then we dare to try those private methods, first we add some methods in the MyObject class, we only implement, do not declare them:
@interface MyObject()
{
@private
NSString * privateThree;
}
@end
@implementation MyObject
- (instancetype)init
{
self = [super init];
if (self) {
privateOne=1;
[email protected]"Tow";
[email protected]"Three";
}
return self;
}
-(NSString *)description{
return [NSString stringWithFormat:@"one=%d\ntow=%@\nthree=%@\n",privateOne,privateTow,privateThree];
}
-(NSString *)method1{
return @"method1";
}
-(NSString *)method2{
return @"method2";
}
This way we can't call them outside, and as we do with the variables, we'll first capture these methods:
// Get all member methods
Method * mem = class_copyMethodList ([MyObject class], & count);
// traverse
for (int i = 0; i <count; i ++) {
SEL name = method_getName (mem [i]);
NSString * method = [NSString stringWithCString: sel_getName (name) encoding: NSUTF8StringEncoding];
NSLog (@ "% @ \ n", method);
}
Print as follows:
Given these method names, we can call them boldly:
MyObject * obj = [[MyObject alloc]init]; NSLog (@ "%@", [obj method1]);
Tip: Here the compiler will not give us a hint of the method, be assured that the call can be bold.
Vi. dynamically adding methods to the class
This is the most powerful part of the runtime mechanism to come, imagine, if we can dynamically add methods to the class, it would be a very exciting thing, note that here is the dynamic addition, and the biggest difference in the category is that this way is the runtime to decide whether to add methods.
-(void) viewDidLoad {
[super viewDidLoad];
// Add a new method, the third parameter is the type of the return value v is void, i is int :: is SEL, object is @ etc
class_addMethod ([MyObject class], @selector (method3), (IMP) logHAHA, "v");
unsigned int count = 0;
Method * mem = class_copyMethodList ([MyObject class], & count);
for (int i = 0; i <count; i ++) {
SEL name = method_getName (mem [i]);
NSString * method = [NSString stringWithCString: sel_getName (name) encoding: NSUTF8StringEncoding];
NSLog (@ "% @ \ n", method);
}
MyObject * obj = [[MyObject alloc] init];
// run this method
[obj method3];
}
// Method implementation
void logHAHA () {
NSLog (@ "HAHA");
}
The results of the operation are as follows:
In the past the five elements can be seen, the method has been added, from the last line can be seen, the implementation of no problem.
Seven, do some small hands and feet
Programmers always get the push, now we're going to do something and replace the function in our class with our function:
-(void) viewDidLoad {
[super viewDidLoad];
MyObject * obj = [[MyObject alloc] init];
// Replace the previous method
NSLog (@ "% @", [obj method1]);
//replace
class_replaceMethod ([MyObject class], @selector (method1), (IMP) logHAHA, "v");
[obj method1];
}
void logHAHA () {
NSLog (@ "HAHA");
}
Print as follows:
It's cool enough this time, and in this way we can mess up the system's functions. Of course, there are many cool ways of runtime:
ID object_copy (ID obj, size_t size)
Copy an Object
ID object_dispose (ID obj)
Releasing an Object
const char *object_getclassname (ID obj)
Gets the class name of the object
Ive
void Method_exchangeimplementations (Method m1, method m2)
Implementation of exchange two methods
Application of runtime mechanism in OBJECTIVE-C