Summary of ios low-level articles
1. Introduction of Clang
Clang is a lightweight compiler for C, C++, and Objective-C.
Clang will support its normal lambda expressions, simplified handling of return types, and better handling of constexpr keywords.
It is almost completely compatible with the GNU C specification (although there are some incompatibilities, including slightly different options for compiling commands) and adds additional syntactically,
For example, C function overloading (which modifiers functions with __attribute__((overloadable))).
2. Clang compilation of the OC object
2.1 Creating a Console project
2.2 Define class HTPerson and object Person in main.m
@interface HTPerson : NSObject
@property(nonatomic.strong)NSString *name;
@end
@implementation HTPerson
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
HTPerson *person = [[HTPerson alloc]init];
NSLog(@"Hello, World!");
}
return 0;
}
Copy the code
2.3. The terminal uses Clang to compile main.m to generate main. CPP
clang -rewrite-objc main.m -o main.cpp
Copy the code
UIKit error problem added conditional compilation
Clang-rewrite-objc-fobjc-arc-fobjc-runtime = ios-13.0.0-isysroot / Applications/Xcode. App/Contents/Developer/Platforms/iPhoneSimulator platform/Developer/SDKs/iPhoneSimulator13.0. The SDK main.mCopy the code
Xcode is installed with the xcrun command, which is a bit of a wrapper around clang to make it easier to use
- The emulator can be used:
xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
Copy the code
- Mobile phone can be used
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main- arm64.cpp
Copy the code
2.4 Open main. CPP and find the HTPerson class
You can see that the HTPerson class is encoded as a struct, and in OC the class is essentially a struct.
- Member variables of struct
Struct NSObject_IMPL NSObject_IVARS and attribute _name defined in the HTPerson class.
Struct NSObject_IMPL NSObject_IVARS (struct NSObject_IMPL)
-
Member functions of struct
Setter for attribute name: _I_HTPerson_setName_
Getter method for property name: _I_HTPerson_name–>objc_setProperty
Note: All setter methods for a property go into the objc_setProperty method
#ifndef _REWRITER_typedef_HTPerson
#define _REWRITER_typedef_HTPerson
typedef struct objc_object HTPerson;
typedef struct {} _objc_exc_HTPerson;
#endif
extern "C" unsigned long OBJC_IVAR_$_HTPerson$_name;
struct HTPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSString *_name;
};
// @property(nonatomic,copy)NSString *name;
/* @end */
// @implementation HTPerson
static NSString * _I_HTPerson_name(HTPerson * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_HTPerson$_name)); }
extern "C" __declspec(dllimport) void objc_setProperty (id, SEL, long, id, bool.bool);
static void _I_HTPerson_setName_(HTPerson * self, SEL _cmd, NSString *name) { objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct HTPerson, _name), (id)name, 0.1); }
Copy the code
All set methods in OC are going to get objc_setProperty–>reallySetProperty
reallySetProperty
From the.cpp code, you can see the OC code
HTPerson *person = [HTPerson alloc];
Copy the code
The compiler can replace this with C++ code:
HTPerson *person = ((HTPerson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("HTPerson"), sel_registerName("alloc"));
//HTPerson *person = objc_msgSend(objc_getClass("HTPerson"), sel_registerName("alloc"));
Copy the code
Where self,_cmd are the two default parameters of the underlying message id(message receiver) and SEL(message number)
Objc_msgSend can continue to add parameters to the end, but we need to turn off strict checking for compilation parameters
2.5 Object method calls
HTPerson *person = [HTPerson alloc];
objc_msgSend(person,sel_registerName("sayNB"));
[person sayNB];
Copy the code
Note:
- 1) To call objc_msgSend directly, you need to import header files
#import <objc/message.h>
- 2) Target –> Build Setting –> search MSG — will
Enable strict checking of obc_msgSend calls Changes from YES to NO
, or objc_msgSend will report an error
2.6 Object method calls (methods inherited from the parent class) : objc_msgSendSuper
HTPerson *person = [HTPerson alloc];
HTTeacher *teacher = [HTTeacher alloc];
[person sayHello];
struct objc_super lgsuper;
lgsuper.receiver = person; // The recipient of the message is person
lgsuper.super_class = [HTTeacher class]; // Specify the parent class
objc_msgSendSuper(&lgsuper, sel_registerName("sayHello"));
Copy the code