Good articles to my personal technology blog: https://cainluo.github.io/15033286127687.html
RunTime is a feature of Objective-C, in other words, because Objective-C is a dynamic language, and RunTime is its RunTime mechanism and so on and so forth, and so on and so forth…
But for scum like me, I think it’s just a bunch of STUFF written in C, so cut the crap and just masturbate.
Reprint statement: if you need to reprint this article, please contact the author, and indicate the source, and can not modify this article without authorization.
objc_msgSend
In our ordinary use, we will often declare a function, and then to call, but we do not know what operation, now let’s look at a piece of code:
#import "RunTimeModel.h"
#import <objc/message.h>
#import <objc/objc.h>
@implementation RunTimeModel
- (instancetype)init {
self = [super init];
if (self) {[self sendMessage];
[self sendMessage:100];
}
return self;
}
- (void)sendMessage {
NSLog(@"Message");
}
- (void)sendMessage:(NSInteger)messageCount {
NSLog(@"Message: %ld", messageCount);
}
@end
Copy the code
This code, which is normal Objective-C code that we write, can be rewritten from the terminal command line:
clang -rewrite-objc RunTimeModel.m
Copy the code
Then we get a runtimemodel. CPP file with 90,000 + lines of code in it, where we need to find something:
static instancetype _I_RunTimeModel_init(RunTimeModel * self, SEL _cmd) {
self = ((RunTimeModel *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("RunTimeModel"))}, sel_registerName("init"));
if (self) {((void(*) (id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("sendMessage"));
((void(*) (id, SEL, NSInteger(a))void *)objc_msgSend)((id)self, sel_registerName("sendMessage:"), (NSInteger)100);
}
return self;
}
Copy the code
((void(*) (id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("sendMessage"));
((void(*) (id, SEL, NSInteger(a))void *)objc_msgSend)((id)self, sel_registerName("sendMessage:"), (NSInteger)100);
Copy the code
This is what we do when we call a method in a.m file, which is converted to send messages to communicate. Objc_msgSend is declared in the #import
file:
OBJC_EXPORT void objc_msgSend(void /* id self, SEL op, ... * / )
OBJC_AVAILABLE(10.0.2.0.9.0.1.0);
Copy the code
There are two basic parameters, id and SEL respectively.
id / SEL
Id and SEL are both defined in #include
:
typedef struct objc_object *id;
typedef struct objc_selector *SEL;
Copy the code
- SEL:Essentially a mapping to a method
C
String, we can useObjective-C
the@selector()
orRunTime
In thesel_registerName
To get aSEL
Type method selector. - id:It is a structure pointer type that can point to
Objective-C
Any object in.
Objc_object definition:
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
Copy the code
In fact, this is the object’s original appearance, do not give beautiful appearance to deceive.
Isa isa member variable of a Class. It isa member variable of a Class. Isa isa member variable of a Class.
Class
#include
typedef struct objc_class *Class;
Copy the code
But actually Class is defined in #include
:
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if ! __OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
Copy the code
Here’s what’s inside:
- Class:There is also a
isa
Pointer, pointing to the owningmeta
(class). - Super_class: refers to its superclass.
- Name: name of the class.
- Version: indicates the version information of a class.
- Info: details about a class.
- Instance_size: The size of the sample object for this class.
- Ivars: A list of member variables pointing to this class, including internal variables.
- MethodLists: A list of sample methods pointing to this class, which links the method selector to the method implementation address.
- cache:
Runtime
Will save the called method tocache
When the method is called the first time, it is cached for the possibility that it will be called again. - Protocols: List of protocols pointing to this class.
Here,methodLists
And notice, it’s pointing toobjc_method_list
A pointer to a pointer, that is, it can be changed dynamicallymethodLists
Value to add member methods, which we often useCategory
That’s what it is, and because of it,Category
There’s usually no way to add attributes, so we have to write them ourselves.
See here, we almost know the basic things, now add a repair knife, look at the whole process:
Runtime
It’s gonna get usThe method call
intoMessage is sent
That’s what we were talking aboutobjc_msgSend
And pass the method caller and method selector as arguments.- This is when the method caller passes
isa
Pointer to find the class to which the method belongs, and thencache
ormethodLists
Find the called method and jump to the corresponding method to execute.- If the method is not found in the class, it passes
super_class
Look up the superclass and execute if it finds it (what if it doesn’t? This will be added later).
- If the method is not found in the class, it passes
Now, this may surprise some people, but methodLists are loaded with instance methods. What kind of methods?
Class methods are stored in a metaclass. The isa pointer is used to find the metaclass to which the Class belongs.
- (void)getClassMethods {
NSObject *obj = [[NSObject alloc] init];
unsigned int methodCount = 0;
const char *className = class_getName([obj class]);
Class metaClass = objc_getMetaClass(className);
Method *methodList = class_copyMethodList(metaClass, &methodCount);
for (int i = 0; i < methodCount; i++) {
Method method = methodList[i];
SEL selector = method_getName(method);
const char *methodName = sel_getName(selector);
NSLog(@"%s", methodName); }}Copy the code
Printout results: Vim
The 2017-08-22 13:24:19. 455 (1) the RunTime [32885-2667202] _installAppearanceSwizzlesForSetter: The 13:24:19 2017-08-22. 456 (1) the RunTime [32885-2667202] __accessibilityGuidedAccessStateEnabled 2017-08-22 13:24:19. 456 1.RunTime[32885:2667202] __accessibilityGuidedAccessRestrictionStateForIdentifier: The 13:24:19 2017-08-22. 456 (1) the RunTime [32885-2667202] __accessibilityRequestGuidedAccessSession: completion: The 2017-08-22 13:24:19. 456 (1) the RunTime [32885-2667202] isSelectorExcludedFromWebScript: The 2017-08-22 13:24:19. 457 (1) the RunTime [32885-2667202] isKeyExcludedFromWebScript: [32885:2667202] _webkit_invokeOnMainThread 2017-08-22 13:24:19.457 1 1.RunTime[32885:2667202] sbs_dataFromObject: 2017-08-22 13:24:19.457 1.RunTime[32885:2667202] sbs_dataFromObject: 2017-08-22 13:24:19.457 The 2017-08-22 13:24:19. 458 (1) the RunTime [32885-2667202] sbs_dataWithValue: The 13:24:19 2017-08-22. 458 (1) the RunTime [32885-2667202] sbs_valueFromData: ofType: The 2017-08-22 13:24:19. 458 (1) the RunTime [32885-2667202] CA_automaticallyNotifiesObservers: The 2017-08-22 13:24:19. 459 (1) the RunTime [32885-2667202] CA_setterForProperty: The 2017-08-22 13:24:19. 459 (1) the RunTime [32885-2667202] CA_getterForProperty: The 2017-08-22 13:24:19. 459 (1) the RunTime [32885-2667202] CA_encodesPropertyConditionally:type1.RunTime[32885:2667202] CA_CAMLPropertyForKey: The 2017-08-22 13:24:19. 459 (1) the RunTime [32885-2667202] bs_decodedFromData: The 2017-08-22 13:24:19. 460 (1) the RunTime [32885-2667202] bs_objectFromData: The 13:24:19 2017-08-22. 460 (1) the RunTime [32885-2667202] bs_secureObjectFromData: ofClass: The 13:24:19 2017-08-22. 460 (1) the RunTime [32885-2667202] bs_secureObjectFromData: ofClasses: The 13:24:19 2017-08-22. 460 (1) the RunTime [32885-2667202] bs_synchronousWrapper: timeout: The 2017-08-22 13:24:19. 460 (1) the RunTime [32885-2667202] bs_secureDataFromObject: The 2017-08-22 13:24:19. 461 (1) the RunTime [32885-2667202] bs_dataFromObject: The 13:24:19 2017-08-22. 461 (1) the RunTime [32885-2667202] bs_secureDecodedFromData: withAdditionalClasses: The 2017-08-22 13:24:19. 461 (1) the RunTime [32885-2667202] bs_secureDecodedFromData: The 2017-08-22 13:24:19. 506 (1) the RunTime [32885-2667202] replacementObjectForPortCoder: The 2017-08-22 13:24:19. 506 (1) the RunTime [32885-2667202] instanceMethodDescriptionForSelector: The 2017-08-22 13:24:19. 507 (1) the RunTime [32885-2667202] methodDescriptionForSelector: 2017-08-22 13:24:19.507 1.RunTime[32885:2667202] _localClassNameForClass 2017-08-22 13:24:19.507 1.RunTime[32885:2667202] cancelPreviousPerformRequestsWithTarget:selector:object: The 2017-08-22 13:24:19. 507 (1) the RunTime [32885-2667202] cancelPreviousPerformRequestsWithTarget: The 2017-08-22 13:24:19. 507 (1) the RunTime (32885-2667202)setRunTime[32885:2667202] implementsSelector: The 2017-08-22 13:24:19. 508 (1) the RunTime [32885-2667202] instancesImplementSelector: 2017-08-22 13:24:19.508 1.RunTime[32885:2667202] Load 2017-08-22 13:24:19.508 1 2017-08-22 13:24:19.509 1.RunTime[32885:2667202] classForKeyedUnarchiver 2017-08-22 13:24:19.509 1. The RunTime [32885-2667202] classFallbacksForKeyedArchiver 2017-08-22 13:24:19. 509 (1) the RunTime (32885-2667202) 13:24:19 _shouldAddObservationForwardersForKey: 2017-08-22. 509 (1) the RunTime (32885-2667202)setKeys:triggerChangeNotificationsForDependentKey: The 2017-08-22 13:24:19. 510 (1) the RunTime [32885-2667202] automaticallyNotifiesObserversForKey: The 2017-08-22 13:24:19. 510 (1) the RunTime [32885-2667202] _keysForValuesAffectingValueForKey: The 2017-08-22 13:24:19. 510 (1) the RunTime [32885-2667202] keyPathsForValuesAffectingValueForKey: The 13:24:19 2017-08-22. 510 (1) the RunTime [32885-2667202] _createValueGetterWithContainerClassID: key: The 13:24:19 2017-08-22. 511 (1) the RunTime [32885-2667202] _createValueSetterWithContainerClassID: key: The 13:24:19 2017-08-22. 511 (1) the RunTime [32885-2667202] _createMutableOrderedSetValueGetterWithContainerClassID: key: The 13:24:19 2017-08-22. 511 (1) the RunTime [32885-2667202] _createMutableSetValueGetterWithContainerClassID: key: The 13:24:19 2017-08-22. 511 (1) the RunTime [32885-2667202] _createValuePrimitiveGetterWithContainerClassID: key: The 13:24:19 2017-08-22. 512 (1) the RunTime [32885-2667202] _createValuePrimitiveSetterWithContainerClassID: key: The 13:24:19 2017-08-22. 512 (1) the RunTime [32885-2667202] _createOtherValueGetterWithContainerClassID: key: The 13:24:19 2017-08-22. 512 (1) the RunTime [32885-2667202] _createOtherValueSetterWithContainerClassID: key: The 13:24:19 2017-08-22. 512 (1) the RunTime [32885-2667202] _createMutableArrayValueGetterWithContainerClassID: key: The 13:24:19 2017-08-22. 513 (1) the RunTime [32885-2667202] accessInstanceVariablesDirectly 2017-08-22 13:24:19. 513 1.RunTime[32885:2667202] instanceMethodSignatureForSelector: 2017-08-22 13:24:19.513 1.RunTime[32885:2667202] Load 2017-08-22 13:24:19.513 1 The 2017-08-22 13:24:19. 514 (1) the RunTime [32885-2667202] doesNotRecognizeSelector: 2017-08-22 13:24:19.514 1.RunTime[32885:2667202] description 2017-08-22 13:24:19.514 1. 13:24:19 methodSignatureForSelector: 2017-08-22. 514 (1) the RunTime [32885-2667202] __allocWithZone_OA: 2017-08-22 13:24:19.515 1.RunTime[32885:2667202] _copyDescription 2017-08-22 13:24:19.515 1.RunTime[32885:2667202] init 2017-08-22 13:24:19.515 1.RunTime[32885:2667202] Zone 2017-08-22 13:24:19.515 1. 13:24:19 instancesRespondToSelector: 2017-08-22. 516 (1) the RunTime [32885-2667202] instanceMethodForSelector: The 2017-08-22 13:24:19. 516 (1) the RunTime [32885-2667202] isAncestorOfObject: The 2017-08-22 13:24:19. 516 (1) the RunTime [32885-2667202] instanceMethodSignatureForSelector: 2017-08-22 13:24:19.516 1. Load 2017-08-22 13:24:19.517 1.RunTime[32885:2667202] Initialize The 2017-08-22 13:24:19. 517 (1) the RunTime [32885-2667202] resolveInstanceMethod: The 2017-08-22 13:24:19. 517 (1) the RunTime [32885-2667202] resolveClassMethod: Retain 2017-08-22 13:24:19.517 1.RunTime[32885:2667202] Retain 2017-08-22 13:24:19.518 1.RunTime[32885:2667202 2017-08-22 13:24:19.518 1.RunTime[32885:2667202] AutoRelease 2017-08-22 13:24:19.518 1.RunTime[32885:2667202] Taincount 2017-08-22 13:24:19.518 1.RunTime[32885:2667202] Alloc 2017-08-22 13:24:19.519 1.RunTime[32885:2667202] allocWithZone: 2017-08-22 13:24:19.519 1.RunTime[32885:2667202] Dealloc 2017-08-22 13:24:19.519 1.RunTime[32885:2667202] Dealloc 2017-08-22 13:24:19.519 1 2017-08-22 13:24:19.519 1.RunTime[32885:2667202] New 2017-08-22 13:24:19.520 1.RunTime[32885:2667202] forwardInvocation: 2017-08-22 13:24:19.520 1.RunTime[32885:2667202] _retain 2017-08-22 13:24:19.520 1.RunTime[32885:2667202] _isDeallocating 2017-08-22 13:24:19.520 1.RunTime[32885:2667202] retainWeakReference 2017-08-22 13:24:19.521 1.RunTime[32885:2667202] allowsWeakReference 2017-08-22 13:24:19.521 1.RunTime[32885:2667202] The 2017-08-22 13:24:19. 521 (1) the RunTime [32885-2667202] mutableCopyWithZone: The 2017-08-22 13:24:19. 522 (1) the RunTime [32885-2667202] doesNotRecognizeSelector: 2017-08-22 13:24:19.522 1.RunTime[32885:2667202] Description 2017-08-22 13:24:19.522 1.RunTime[32885:2667202 2017-08-22 13:24:19.522 1.RunTime[32885:2667202] mutableCopy 2017-08-22 13:24:19.523 1.RunTime[32885:2667202] 13:24:19 performSelector: withObject: 2017-08-22. 523 (1) the RunTime [32885-2667202] isMemberOfClass: The 2017-08-22 13:24:19. 524 (1) the RunTime (32885-2667202)hashThe 2017-08-22 13:24:19. 524 (1) the RunTime [32885-2667202] isEqual: 2017-08-22 13:24:19.524 1. Selector [32885:2667202] self 2017-08-22 13:24:19.524 1. Selector [32885:2667202] The 2017-08-22 13:24:19. 525 (1) the RunTime [32885-2667202] conformsToProtocol: The 2017-08-22 13:24:19. 525 (1) the RunTime [32885-2667202] methodSignatureForSelector: The 2017-08-22 13:24:19. 525 (1) the RunTime [32885-2667202] forwardingTargetForSelector: The 2017-08-22 13:24:19. 525 (1) the RunTime [32885-2667202] methodForSelector: The 2017-08-22 13:24:19. 526 (1) the RunTime [32885-2667202] performSelector: withObject: withObject: 2017-08-22 13:24:19.526 1.RunTime[32885:2667202] Superclass 2017-08-22 13:24:19.526 1.RunTime[32885:2667202] isSubclassOfClass: 2017-08-22 13:24:19.527 1.RunTime[32885:2667202] Class 2017-08-22 13:24:19.527 1 13:24:19.528 1.RunTime[32885:2667202] debugDescription 2017-08-22 13:24:19.528 1.RunTime[32885:2667202] isProxy The 2017-08-22 13:24:19. 529 (1) the RunTime [32885-2667202] respondsToSelector: The 2017-08-22 13:24:19. 529 (1) the RunTime [32885-2667202] isKindOfClass:Copy the code
Isa supplement
Here’s a sidebar to the isa pointer:
class
theisa
The pointer points to thetaThe metaclass
.The metaclass
theisa
The pointer points to thetaThe root class
.- if
The root class
Or is itThe metaclass
The super class isNSObject
“Then point to yourself. NSObject
There are no superclasses.
The project address
The address of the project: https://github.com/CainRun/iOS-Project-Example/tree/master/RunTime/ to play the iOS development: in the iOS RunTime (a)
Note:RunTimeModel.cpp
In the catalog, I didn’t put it in the project.