1. Review

In previous posts, I have looked at the underlying structure of the OC class and looked at the main internal member variables (ISA /bits) in detail. In the last two blog posts, we have done a more detailed analysis of caches in the class. Looking at the assembly at breakpoints later, you can see that there is a cache read process, objc_msgSend and cache_getImp, that precedes the INSERT method call process. And that’s where the Runtime comes in, because it’s all connected.

2. Runtime

2.1 What is Runtime

Runtime translates as runtime, which corresponds to compile time. Most iOS developers have heard the word Runtime and know runtime. But just stay on the surface, just know, and did not go deep to explore and analysis.

OC language is a dynamic language, has three characteristics of dynamic language: dynamic typing, dynamic binding, dynamic loading. The underlying implementation is the familiar yet unfamiliar Runtime.

  • The runtimeIs an object-oriented programming language (object-oriented programming) runtime environment. The runtime indicates which program is running at a given time. Runtime is the phase of a computer program’s life cycle. Other phases include compile time, link time, and load time. Simply put, code runs and is loaded into memory. Your code is dead on disk until it is loaded into memory. It becomes alive only when it is stored in memory.
  • Compile timeAs the name implies, while compiling. What is calledcompile? A compiler helps you translate the source code into binary code that the machine can understand.
  • (Of course, this is in a general sense, but in fact it may only be translated into some intermediate state of language. Such asJavaonlyJVMIdentifying bytecode,C#Only in theCLRTo identify theMSIL. There are also linkers, assemblers, and we can call them compilers for easier understanding.)
  • It’s simply a matter of doing some translation work at compile time, like checking if you’ve made any careless mistakesThe keyword.
  • Lexical analysisGrammatical analysis and so on. It’s like a teacher checking a student’s essay for typos and bad sentences.
  • The compiler will tell you if it finds something wrong. Use it normallyXcode, the pointbuildSo start compiling.
  • If there’s aerrorsorwarningInformation, that’s all checked out by the compiler. The mistake is calledCompile timeError. The type checking done during this process is calledCompile-time type checkingOr,Static type checking(Static means that the code is not actually running in memory, but is scanned as text).

2.2 Three ways to use runtime

There are three ways to use runtime, and the relationship between the three implementation methods and the compilation layer and the bottom layer is shown in figure

  • Through OC code, such as [JPerson Hello]

  • Through NSObject, such as isKindOfClass

  • This is implemented through Runtime API low-level methods, such as class_getInstanceSize

The compiler in the figure is the compiler, known as LLVM

3. The nature of OC method

In the previous blog iOS development structure of the underlying exploration we know that usually write OC code, the underlying implementation is actually C/C++ code, and then compiled by the compiler LLVM, and finally converted into machine language. Through the source code compiled by clang, understand the nature of OC object (structure), the same, we can also use clang command compiled into main. CPP file, see the nature of the method is what?

3.1 objc_msgSend

  • Before compiling
@interface JPPerson : NSObject
@property (nonatomic.readwrite , copy) NSString *personName;
- (void)superTest;
@end

@implementation JPPerson
- (void)superTest {
	NSLog(@" This is the parent class");
}
@end

@interface JPStudent : JPPerson

@property (nonatomic.readwrite , copy) NSString *studentName;
- (void)test;

@end

@implementation JPStudent
- (void)test {
	NSLog(@"%s",__func__);
}
@end
int main(int argc, const char * argv[]) {
	@autoreleasepool {
		JPStudent *stu = [[JPStudent alloc]init];
		[stu test];
		[stu superTest];
	}
	return 0;
}
Copy the code
  • The compiled
int main(int argc, const char * argv[]) {
 /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
  JPStudent *stu = ((JPStudent *(*)(id, SEL))(void *)objc_msgSend)((id)((JPStudent *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("JPStudent"), sel_registerName("alloc")), sel_registerName("init"));
	 
  ((void(*) (id, SEL))(void *)objc_msgSend)((id)stu, sel_registerName("test"));
  ((void(*) (id, SEL))(void *)objc_msgSend)((id)stu, sel_registerName("superTest"));
 }
 return 0;
}
Copy the code

As can be seen from the above code, the OC method call becomes objc_msgSend, which is also known as message send

We can implement a call to [STu test] by mimicking the objc_msgSend method

As you can see from the output of the console, everything is exactly the same. [stu test] = objc_msgSend(stu,sel_registerName(“test”))

Note:

#import

–> Build Setting –> search MSG –> enable strict checking of obc_msgSend calls –> YES Otherwise, the objc_msgSend parameter will fail.

  • Not import#import <objc/message.h>

  • To enable theobjc_msgSendCall strict check, set toNO

Objc_msgSend (Receiver of message, body of message (SEL + argument))

3.2 objc_msgSendSuper

Above 👆 calls the parent method [stu superTest] in the main function, and objc_msgSendSuper is found in the clang compiled source code.

If our subclass also has a superTest method, but does not implement it, let’s see what happens.

@interface JPPerson : NSObject
@property (nonatomic.readwrite , copy) NSString *personName;
- (void)superTest;
@end

@implementation JPPerson
- (void)superTest {
	NSLog(@"%s",__func__);
}
@end

@interface JPStudent : JPPerson

@property (nonatomic.readwrite , copy) NSString *studentName;
- (void)test;
- (void)superTest;
@end

@implementation JPStudent
- (void)test {
	NSLog(@"%s",__func__);
}
@end

int main(int argc, const char * argv[]) {
	@autoreleasepool {
		JPStudent *stu = [[JPStudent alloc]init];
		[stu test];
		NSLog(@"------- Gorgeous dividing line -----------");
		objc_msgSend(stu,sel_registerName("test"));
		[stu superTest];
	}
	return 0;
}
Copy the code

Print the result

-[JPStudent test] ------- ----------- -[JPStudent test] -[JPPerson superTest] Program ended with exit code:0
Copy the code

Object method calls are actually the implementation methods of the parent class. To verify this statement, we can try the objc_msgSendSuper implementation.

Objc_msgSendSuper method has two parameters (structure, sel), its structure type is the structure object defined by objc_super, and needs to specify the two properties of receiver and super_class, the source code implementation definition is as follows

By looking at Apple’s source code, I found the following method

OBJC_EXPORT id _Nullable
objc_msgSend(id _Nullable self, SEL _Nonnull op, ...)
    OBJC_AVAILABLE(10.0.2.0.9.0.1.0.2.0);
    
OBJC_EXPORT id _Nullable
objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
    OBJC_AVAILABLE(10.0.2.0.9.0.1.0.2.0);
Copy the code

The code modification is as follows:

int main(int argc, const char * argv[]) {
	@autoreleasepool {
		JPStudent *stu = [[JPStudent alloc]init];
		JPPerson *person = [JPPerson alloc];
		[person superTest];

		struct objc_super jpsuper;
		jpsuper.receiver = stu; // The receiver of the message
		jpsuper.super_class = [JPStudent class]; // Tell who the parent class is, change it to [JPPerson Class]
		// The recipient of the message is still your own -> parent -> method found please direct to my father
		objc_msgSendSuper(&jpsuper, sel_registerName("superTest"));
	}
	return 0;
}

Copy the code

Print the result

[26066:278406] -[JPPerson superTest]
[26066:278406] -[JPPerson superTest]
Copy the code

4. To summarize

  • OC calls a method, which essentially sends a message (objc_msgSend)

  • The OC method is called first by looking in the class. If it is not found in the class, it will look in the parent class of the class.

  • The subclass calls the methods of the parent class, and the underlying class calls objc_msgSendSuper

More content continues to be updated

🌹 if you like, click a like 👍 🌹

🌹 think learned can come a wave, collect + attention, comment + forward, lest you can not find me 😁🌹 next time

🌹 welcome everyone to leave a message exchange, criticism and correction, learn from each other 😁, improve themselves 🌹