The call to find objects and object methods in iOS is itself addressing. The stack area is opened from high addresses to low addresses, and the heap area is opened from low addresses to high addresses. Stack area is continuous. Why is it continuous? Because, a stack pointer needs to open up an 8-byte area, which holds the address of the “value”, can be consecutively arranged. The heap is discontinuous because the heap object initialization follows the principle of “memory” alignment. About classes and objects, generally thought the nature of the object is come out by type of new structure and a memory area, in fact, from the application point of view, class is also a structure, the object after the initialization is opened up a memory area, but the object can be understood as action to save the data, if you want it to invoke a method, In fact, it is to find its corresponding class address, the class address is stored in the object isa pointer, by accessing the method set below the class structure to find and call the matching method. For obtaining the attribute value of the object, memory offset operation should be carried out according to the memory sort determined after compilation, and the corresponding pointer should be found for value operation.

Where does the object’s ISA point to?

Let’s start with the following code:

Person * p = [[Person alloc] init]; NSLog(@"p object stack address =%p",&p); NSLog(@"p object heap address =%p",p); NSLog (@ p = % @ "object", p); Class cls = [Person class]; NSLog(@"class stack address %@", CLS);Copy the code

Print the following:

It can be clearly seen that the printing result of pointer information, memory information and class information of p object is very clear.

However, CLS prints only the class name, not the address.

So, using the console output:

Explain the specific meaning of the output respectively:

1. The memory address held by the CLS pointer, here understood as the first address of the Person class.

2. The address to which the ISA pointer to the p object points.

3. CLS storage object is printed directly here, there is no output object address, here the object refers to the class.

4. Print CLS pointer stack address.

As you can see above, the isa pointer to the object points to the same address as the first address of the class.

So, if there is an attribute under Person, the address of the attribute will be offset by 8 bytes from the ISA address.

Declare a name attribute under Person

@property (nonatomic,strong) NSString * name;
Copy the code

Print the following:

As you can see, the name attribute is indeed offset by 8 bytes, which is only the internal address used to store the concrete name object.

Here is clear, the declaration of the variable p in the stack, and it is just a pile of region object’s first address, and other attributes of the objects of this pointer will be under the first address of the current object, in turn, increasing 8 bytes configuration, so, the nature of the program is the process of addressing, here, there is no need to wonder, Is the pointer on the stack.

Second, the offset of the pointer

Let’s start with a little bit of code

Person * p = [[Person alloc] init]; NSLog(@"p object stack address =%p",&p); NSLog(@"p object heap address =%p",p); NSLog (@ p = % @ "object", p); Class cls = [Person class]; NSLog(@"class stack address %@", CLS); void *kc = &cls; [( __bridge id)kc addObject:@"111"];Copy the code

The Person object is received with a pointer to void*, which can be interpreted as an ID. At the end of the code, you can see that the program calls the array-add-object method. Note that this method is not declared or implemented in the Person object.

The error is that the Person class object did not find the addObject method. At compile time, the program does not know the type of the object, so it is ok to call the existing method, when the runtime error is reported, in fact, it is easy to understand, by thinking about a understanding, the runtime to select the ISA address, in the class structure can not find the method is also abnormal.

Let’s modify the code so that this KC executes a method declared and existing by the Person class.

Call showNameAddress on both p and KC

Print the following:

Analyze:

The name pointer address (3) printed immediately after the p object is the 8-byte offset of the ISA pointer to the P object, which is well understood here.

Kc immediately prints the heap address (5) of name, which is the isa pointer to the p object (2), and the stack address (4) of name, which is the stack address of the P object (1). Why is that?

Let’s see how the program assigns stack addresses to p, CLS and kc variables during execution.

The stack address of the three temporary variables is consecutive, and the first address is high, and the second address is low.

When kc executes the showNameAddress method, it is actually the first address of CLS class that executes the instance method. Since the first address of CLS class is consistent with the ISA address of p instance object, it will not crash when finding and executing the method.

ShowNameAddress specifies that the current printed entry pointer is offset by 8 bytes of stack information, so that the CLS stack pointer is forced to offset by 8 bytes of stack information. It’s natural to find a pointer to the temporary variable p.

Is this where the above question becomes clear?

Of course, if there is more than one attribute, then an object calling an attribute will offset the 8-byte unit-multiples in the order in which the attribute was declared. Therefore, the process of obtaining object properties and addressing method calls is presented to the programmer in OC code, while the offset value of pointer is determined after the program is compiled. It does not care what object is currently called in the stack information at run time, just so arbitrary.

Don’t laugh at bad code.