In the previous article, we introduced the runtime is what, is a theoretical introduction, you read the last article is very urgent to know what the runtime is capable of? Don't worry, this blog is going to explain how the runtime is applied to the actual combat runtime official documentation is here, including the interface name and instructions for use. The interfaces described below can be found in this document.
use in SetValue in KVCWe know that in KVC if the object does not have this attribute or the variable is directly crash, such as:
- Runtimeobj *obj = [[Runtimeobj alloc]init];
- [obj setvalue:@ "value4name" forkey:@"objname"]; Runtimeobj has no objname this attribute
This code will directly crash there is no headache for this feeling, if you can first check in some way and then set that will not crash? Yes, this thing runtime can do it first look at the sample code:
-(BOOL) Hasattribute: (NSString *) AttName
{
BOOL flag = NO;
U_int count;
Ivar *ivars = Class_copyivarlist ([Self class], &count);
For (int i = 0; i < count; i++)
{
Const char* propertyname = Ivar_getname (Ivars[i]);
NSString *strname = [NSString stringwithcstring:propertyname encoding:nsutf8stringencoding];
if ([AttName isequaltostring:strname]) {
flag = YES;
}
NSLog (@"===%@", strName);
}
return flag;
}
Yes, this function can help you check if there is a property or variable, and the next code is explained below: *
IvarPrototype is
typedef struct OBJC_IVAR *ivar;*
class_copyivarlistReturns a class of all properties or variant prototypes
Ivar *class_copyivarlist (class cls, unsigned int *outcount); *
Ivar_getnameReturns the name of the struct without the Ivar, which is the name of the variable's prototype
const Char *ivar_getname (Ivar v);* There is also a function corresponding to this
class_copypropertylistAnd
class_copyivarlistDifferences in the former only take attributes (
properties of the @property declarationAll of the latter are stated in the interface curly braces. The sample code used by Class_copypropertylist is as follows:
- objc_property_t* properties= class_copypropertylist ([Self class], &count);
- for (int i = 0; i < count; i++)
- {
- Const char* propertyname = Property_getname (Properties[i]);
- NSString *strname = [NSString stringwithcstring:propertyname encoding:nsutf8stringencoding];
- NSLog (@"===%@", strName);
- }
Two different can be used in code to demonstrate, the specific code to write their own I will not post it, to see what the difference between the two? With this step, are you worried about the crash when abusing KVC?dynamically creating FunctionsSometimes a function is created dynamically based on the project's requirements, and the runtime is able to see the code first:
void DynamicMethod (id self, SEL _cmd)
{
printf ("SEL%s did not exist\n", Sel_getname (_cmd));
}
+ (BOOL) Resolveinstancemethod: (SEL) Asel
{
Class_addmethod ([Self class], Asel, (IMP) DynamicMethod, "[email protected]:");
return YES;
}
void DynamicMethod (id self, SEL _cmd)
{
printf ("SEL%s did not exist\n", Sel_getname (_cmd));
}
+ (BOOL) Resolveinstancemethod: (SEL) Asel
{
Class_addmethod ([Self class], Asel, (IMP) DynamicMethod, "[email protected]:");
return YES;
}
Test code:
- Runtimeobj *obj = [[Runtimeobj alloc]init];
- [obj performselector: @selector (DynamicMethod:)];
See how the Code works:
* + (BOOL) Resolveinstancemethod: (SEL) AselWhen calling such a method, the function is dropped without this method.
* Class_addmethodis to dynamically add a method prototype to a class
BOOL Class_addmethod (class cls, SEL name, IMP imp, const char *types)
Note: IMP is a function pointer |
* “
[email protected]:"is a kind of argument that will be explained in detail later
Replace an existing functionIn the mixed code can not follow the existing ideas to execute the original function, then we replace it is not good, look at the runtime how to do it? First on the code: (Note that the following code is to speak Targetreplacemethod replaced by Demoreplacemethod)
-
- void Demoreplacemethod (id self, SEL _cmd)
-
- {
-
- NSLog (@"Demoreplacemethod");
-
- }
-
-
-
- -(void) Replacemethod
-
- {
-
- Class strcls = [self class];
-
- SEL targetselector = @selector (Targetrelplacmethod);
-
- Class_replacemethod (Strcls,targetselector, (IMP) demoreplacemethod,null);
-
- }
-
-
-
- -(void) Targetrelplacmethod
-
- {
-
- NSLog (@"Targetrelplacmethod");
-
- }
Test code:
- Runtimeobj *obj = [[Runtimeobj alloc]init];
- [obj Replacemethod];
- [obj Targetrelplacmethod];
Operation Result:
- 2014-05-12 19:38:37.490 runtime[1497:303] Demoreplacemethod
is not the original
NSLog (@ "Targetrelplacmethod");This sentence will be replaced without execution! Note: 1.
Class_replacemethodmethod is to dynamically replace
MethodThe function, prototype
IMP。 2.
Class_replacemethod (class cls, SEL name,imp IMP, const char *types)The return value is the address of a new function (
Imp pointer)。 3. In the actual project will often use this way, such as: IOS 7 and below 7 draw Navigationbar, you slowly experience it.
Dynamic Mount ObjectsWe should not be unfamiliar with this word, but here is a little bit of a subtle difference here, bloggers are not very good at explaining the meaning of the word, then I would like to cite an example: if you want to use a property when passing (parameter), According to the previous thinking: I inherit this class again a new class is done, OK, this idea is not a problem, but you do not think to create a new. h and a. m file a little bit of a hassle? Programmers are lazy, if there is a way to directly talk about the properties I want to mount it would not be better? The code is simple and easy to understand. Read the headline and you should know that the runtime can help you fulfill your wishes. Here's how to use runtime to dynamically mount another object on an existing object. Let's not say the direct code (here is the example of Uialertview):
-
- Parameters required to mount the object (Uialertview Mount object)
-
- Static const char krepresentedobject;
-
- -(void) Showalert: (ID) Sender
-
- {
-
- Uialertview *alert = [[Uialertview alloc]initwithtitle:@"hint" message:message delegate:self cancelButtonTitle:@ " Cancel" otherbuttontitles:@ "go to see", nil];
-
- Alert.tag = Alert_goto_tag;
-
- Objc_setassociatedobject (Alert, &krepresentedobject,
-
- @"I was mounted",
-
- Objc_association_retain_nonatomic);
-
- [Alert show];
-
- }
This is just a mount to see how to get the objects we mount (NSString @ "I was mounted")
-
- -(void) Alertview: (Uialertview *) Alertview Clickedbuttonatindex: (nsinteger) Buttonindex
-
- {
-
- if (Buttonindex = = 1) {
-
- NSString *str = Objc_getassociatedobject (Alertview,
-
- &krepresentedobject);
-
- NSLog (@"%@", str)
-
- }
-
- }
Write your own code to see if the effect is the same as what you think? Below is explained below: 1.
static const char krepresentedobject;This is just a mark, but the essential specific what role did not do research, I think it should be you mount a mark
RuntimeIt should be based on this tag to distinguish which instance the mounted object is mounted on. 2.
Objc_setassociatedobjectDynamically sets the associated object (that is, Mount). 3.
Objc_getassociatedobjectGet associated objects dynamically see, there's no need to preach here.
KrepresentedobjectThe sign, it seems, is a little proof of my previous conjecture.
What can objective-c runtime do?