The essence of an object is a structure. This can be verified by compiled c++ code, first using the Clang command to get the compiled CPP file.

Clang

Clang-rewrite-objc main.m -o main. CPP compiles the object file into a c++ file

Problems encountered

The following error was encountered during compilation:

The solution

UIKit cannot be found. For this problem, we can use the following command to solve it:

-clang-rewrite-objc-fobjc-arc-fobjc-Runtime =ios-13.0.0 -isysroot / Applications/Xcode. App/Contents/Developer/Platforms/iPhoneSimulator platform/Developer/SDKs/iPhoneSimulator14.3. The SDK main.mCopy the code

Or use XCRun, which is even cleaner. Xcode is installed with the xcrun command, which is a bit more wrapped around clang to make it easier to use.

// emulator xcrun-sdk iphonesimulator clang-arch arm64-rewrite-objc main.m -o main-xx.cppCopy the code
// xcrun-sdk iphoneOS clang-arch arm64-rewrite-objc main.m -o main-xx.cppCopy the code

If the output is successful, but the output location of the corresponding file is not found, you can search the file, and then right-click and select “Show in upper folder” to find the specific location.

The validation process

Customize a JLObject class in main.m:

@interface JLObject : NSObject @property (nonatomic, strong) NSString *name; @end // Enter NSObject and you can see that its member contains an ISA pointer. @interface NSObject <NSObject> { ... Class isa OBJC_ISA_AVAILABILITY; . }Copy the code

Output the CPP file of main.m through clang command, open the file to check the output content, and find tens of thousands of lines of code, so we need to search to find our customized class, and intercept the code as follows.

. typedef struct objc_object JLObject; . struct JLObject_IMPL { struct NSObject_IMPL NSObject_IVARS; NSString *_name; }; // @property (nonatomic, strong) NSString *name; . typedef struct objc_object NSObject; struct NSObject_IMPL { Class isa; }; . struct objc_object { Class _Nonnull isa __attribute__((deprecated)); }; .Copy the code

JLObject_IMPL contains a member ISA inherited from NSObject_IMPL (NSObject) and a custom member name.

Conclusion: Objects are structures in nature.

Id type

  • Why can an ID modify an object?
  • Why is * not needed when id decorates an object?
JLObject * obj = [[JLObject alloc]init];
id objc1 = [[JLObject alloc]init];
Copy the code

Class and ID are Pointers to the structure of objC_Object.

typedef struct objc_object *id;
typedef struct objc_object JLObject;
Copy the code

As you can see from the compiled code, JLObject is the objC_Object structure and ID is the pointer to the objC_Object structure.

The structure of an object in memory

I met a problem and deepened my understanding of the nature of the object in the process of analysis. Here I will analyze it through this problem.

The problem

As shown, can obj2 call methods? Can I access member variables?

@interface JLObject : NSObject
@property (nonatomic, strong) NSString *name;
@end

@implementation JLObject
-(void)sayHello{
    NSLog(@"%s - %@",__func__,self.name);
}
@end
Copy the code

The results of

  • Call methods: Obj2 can call the sayHello method
  • Property: Obj:

    prints obj:

Analysis of the

1. The first thing we need to know is that properties and member variables reside in the space created by objects, and methods reside in class/metaclass objects.

2. All the object stores on the stack isa pointer to the starting address of the object in the heap. This address stores the isa pointer to the starting address of the class object.

  • When accessing properties (member variables), the structure pointer is used to get the starting address of the structure, and then the memory translation is used to access the specific member variable.
  • When accessing a method, you need to use the structure pointer to get the starting address of the structure, which stores the ISA pointer, then use the ISA pointer to get the first address of the class in the heap, and then use memory translation and hash to find the corresponding method.

3. In the basic principle of iOS alloc, we know that there are three important steps to create an object: calculate the size of memory, open up space, and assign isa pointer.

  • Isa isa pointer to the first address of a class object, and obj1 isa pointer to the first address of a class object, so we can assume that obj1 to obj2 is close to isa.
Calculate the size of memory required Open the space Assign isa pointer
obj true true true
obj2 false false true

conclusion

Based on the above information, we know that:

  • Obj2 has access to class objects through obj1, so methods can be called.
  • Obj2 has no space to store/access properties or member variables,
  • When obj2 accesses name, it will get the address obj2 points to, obj1, and then shift it 8 bits to obj1’s addressobj(0x7~b0 = 0x7~a8 + 8)The location of the. So it will print out<JLObject: 0x6~b0>

supplement

Structure of obJ in memory:

Obj2’s in-memory structure: