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 — willEnable 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