The basic concept

The three main characteristics of OC are encapsulation, inheritance and polymorphism

1. Packaging:

  • Member variable encapsulation: setter, getter methods, self call convenient and efficient
  • Encapsulation of common methods: simple and efficient, without concern for internal processes
  • SDK packaging: easy to use, private hiding, high security (won’t leak data and code)

2, inheritance,

  • Duplicate code is extracted: subclasses can have all the member variables and methods in their parent class
  • The relationships between classes are established
  • Each class has a superclass pointer to its parent class
  • The root class of all classes is NSObject for isa pointer queries
  • When calling a method on an object, the method is first searched in the current class. If it cannot be found, the method is searched in the parent class
  • A subclass reimplements a method of its parent class, overwriting the previous method of the parent class.

Disadvantages of inheritance: the coupling is too high (the relationship between classes is too close), there is no multiple inheritance, OC is all single inheritance, multiple inheritance can be simulated by protocol delegate agent; Multiple inheritance of OC can be accomplished by implementing multiple interfaces.

3, polymorphism

For example: -(void) animal:(id); Id is polymorphic, and when passed, the real image of the concrete class is recognized. Runtime is also runtime, which recognizes concrete classes.

  • To use polymorphism you must use inheritance (inheritance is a prerequisite for polymorphism)
  • Animal *aa = [Dog new]; The real image of the object is detected when the method is called
  • Benefits: If a function or method argument uses a superclass type, you can pass in a superclass, subclass object.
  • Limitations: Variables of the parent type cannot call subclass-specific methods directly. They must be cast to subclass-type variables before they can be used.

4. There are three types of property keywords

1. Atomicity (aka thread safety)

There are atomic and nonatomic, acOMic is thread safety, but nonacomic is generally used, because the cost of acomic thread safety is too high, affecting performance, even if we need to ensure thread safety, we can also control through our own code, rather than ACOMIC.

2. Reference count

  • Assign: Used for non-pointer variables, assign basically modifies data types and is managed by the stack area of the system.
  • Weak: Weak reference to an object. The reference count is not increased and the object is not held. When the object disappears, the pointer automatically becomes nil.
  • Copy: Indicates deep copy and shallow copy
  • Shallow copy: A copy of a memory address so that the pointer to the target object points to the same memory space as the original object increases the reference count
  • Deep copy: Copy the contents of an object to create new memory space
  • Strong: retainCount +1 for every reference to this property, which modifies only NSObject objects, not base data types. Is the default modifier for id and object.
  • Unsafe_unretained: NSObject is a predecessor of Week. After iOS5, week has been replaced with unsafe_unretained. However, they are slightly different and not exactly the same. For upper-layer code, we can use week wherever we can use unsafe_unretained. Also note that this modifier modifies a variable that does not belong to the compiler’s memory management object

5. The Category Category

Whether to override a class by inheritance or classification depends on the situation:

  • If the target class has many subclasses and we need to extend the class without affecting the original code, it is better to inherit.
  • If you are just extending the method, the classification is better (no need to involve the original code).

Advantages:

  • Methods in a classification have a higher priority than methods in the original class, that is, if methods in the original class are overridden in the classification, methods in the classification will override methods in the original class. The +(void)load method is a special case that executes in the category after the current class has finished executing.
  • You can use Runtime to swizzling method to handle exception calls.

Disadvantages:

By looking at header files, we can see that many classes in the Cocoa framework implement their functions by category, and you can accidentally override one of these methods, sometimes causing exceptions that you can’t detect.

Other problems

What is the difference between shallow copy and deep copy?

  • Shallow copy: Copies only Pointers to objects that point to the same address, not the reference object itself.
  • Deep copy: Copies the reference object itself. There are two separate objects in memory, and when you modify A, B stays the same. (i.e., B = [A copy];)

Memory management

Case: office lights on and off, someone turned on the light, no one turned off the light; In people plus one, out people minus one; The first person to turn on the lamp holds the lamp, the first person can discard the lamp, and the others are just weak references.

Memory Management Principles

  • 1. You own the generated objects
  • 2. You can hold objects that are not generated by yourself
  • 3. Release objects you hold when you no longer need them
  • 4. Objects that are not owned by you cannot be released (releasing will crash)

Object operations correspond to Objective-C methods

The object operation Objective – C method
Generate and hold objects Alloc, new, copy, mutableCopy
Hold the object Retain (reference count plus 1)
Release object Release (reference count minus 1)
Discarded objects Dealloc (reference count is 0)

Related release functions: AutoRelease, NSAutoreleasePool, @autoreleasepool

Using the autoRelease method, you can retrieve the object’s existence, but do not hold the object itself (obj does not immediately release it, but registers it with autoreleasePool).

Rules of use function in ARC environment

  • Cannot use retain, release, retainCount, autorelease
  • NSAllocateObject and NSDeallocateObject cannot be used
  • Memory management naming rules must be followed (hump naming)
  • Do not call dealloc explicitly
  • Use @autoRelease instead of NSAutoreleasePool
  • Unusable areas (NSZone)
  • Object variables cannot be members of C struct/union
  • Explicitly convert “id” and “void *”

An operation that increases the object reference count

    1. New, alloc, retain, copy, and mutableCopy
    1. Add a control to the view with addView. The control’s reference count is +1.
    1. When you add an object to an array, the object’s reference count is added to the array by +1.
    1. Attribute assignment, which makes the object’s reference count +1;
    1. Xib controls that, when associated with code, make the reference count of the object +1;
    1. The push operation increases the object’s reference count.

ARC and MRC

  • Using MRC code in ARC environment, use -fno-objc-ARC conversion
  • Using ARC code in MRC environment, use -fobjC-ARC conversion

Ownership modifier

  • __strong modifier
  • __weak modifier
  • __unsafe_unretained modifier (used in MRC environments)
  • The __autoreleasing modifier (used in ARC)
  1. The __strong modifier is the default modifier for ID types and object types, and is generally implicit;

id obj = [[NSObject alloc] init]; Id __strong obj = [[NSObject alloc] init];

  1. __weak resolves modifiers for loop references, preventing memory leaks. When holding a weak reference to an object, if the object is deprecated, the weak reference is automatically invalidated and is assigned nil, so the object is no longer held.

  2. __unsafe_unretained and retained as _ _weak is the same as the __unsafe_unretained and retained variable. As a result, the generated object is released immediately.

  3. __autoRELEASING implicit modifiers: objects that are not self-generated and can be held by themselves are registered with the automatic release pool.

The process by which an object is not held when it is released

  • 1. Objc_release
  • 2) Dealloc = 0
  • 3. _objc_rootDealloc
  • Object_dispose (dispose)
  • 5. Objc_destructInstance
  • Objc_clear_deallocating (Clear)

When the object is abandoned, the action of objc_clear_dealLocating is last called (related table SideTables)

  • 1, obtain the record of abandoned object (address is key value) from weak table. address= h(key)
  • 2. Assign nil to all addresses with _ _weak modifier variables included in the record.
  • Delete the weak table from the weak table.
  • 4, Delete the obsolete object from the reference count table (address is the key value).

other

  • Memory leak: Objects that should be deprecated continue to exist beyond their lifetime.
  • Wild pointer: The pointer variable is uninitialized and its value is random; Pointer is not null after being freed, pointing to non-existent memory.
  • Dangling pointer: Points to an object that once existed but no longer exists.
  • Tagged Pointer is a special “Pointer” that stores not an address but real data and some additional information. (Special explanation will be made later)
  • Isa pointer: Isa pointer to NONPOINTER_ISA, which indicates the class type to which the object belongs and some additional information.

Flag Pointer: Tagged Pointer

See apple’s description of Tagged Pointer’s features:

  • Tagged Pointer is used to store small objects, such as NSNumber, NSDate, and NSString.
  • The Tagged Pointer value is no longer an address, but a real value. It’s not really an object anymore, it’s just a normal variable in an object’s skin. Therefore, its memory is not stored in the heap and does not require malloc and free.
  • It is three times more efficient in memory reading and 10 times faster in creation

For example, the output class of NSString is NSTaggedPointerString. If the string length is less than 9, iOS uses Tagged Pointer for optimization. A string doesn’t really become an __NSCFString until the string length is greater than 9.

Note: This does not change for strings created using the @”” symbol or constant strings, but for string objects created using NSString methods such as stringWithFormat.

NSString *strS = @"123456789"; NSLog(@"%@ : %p",strS.class,strS); strS = [NSString stringWithFormat:@"1"]; NSLog(@"%@ : %p",strS.class,strS); strS = [NSString stringWithUTF8String:"1234567"]; strS = [NSString stringWithUTF8String:"abcdabc"]; //7 NSLog(@"%@ : %p",strS.class,strS); strS = [NSString stringWithUTF8String:"abcdabcd"]; //8 strS = [NSString stringWithUTF8String:"teeeeeeet"]; //9 NSLog(@"%@ : %p",strS.class,strS); strS = [NSString stringWithUTF8String:"eeeeeeeeee"]; //10 strS = [NSString stringWithUTF8String:"eeeeeeeeeee"]; //11 NSLog(@"%@ : %p",strS.class,strS); strS = [NSString stringWithUTF8String:"eeeeeeeeeeee"]; //12 NSLog(@"%@ : %p",strS.class,strS); Result: __NSCFConstantString: 0x10C843820 NSTaggedPointerString: 0xA000000000000311 NSTaggedPointerString: 0xa636261646362617 NSTaggedPointerString : 0xa040000000000049 NSTaggedPointerString : 0xa00000000000000b __NSCFString : 0x6000000315c0Copy the code

Isa pointer (NONPOINTER_ISA)

  • Isa: isa pointer to the Class type of an object.
  • NonPointer_isa: Isa pointer to an object that indicates the class type to which the object belongs and some additional information.

If the ISA pointer represents only types, it is obviously also a huge waste of memory. So, just like tagged Pointer, Apple optimized the ISA pointer as well. The content of isa pointer becomes more rich, in addition to indicating which class the object belongs to, but also attached “reference count” extra_rc, whether there is weak reference flag weakly_referenced, whether there is additional object flag flag has_ASsoc and other information. (rc: Reference counter reference count)

/ / -- -- -- -- -- -- -- a consortium (definition) -- -- -- -- -- -- -- the union isa_t {isa_t () {} / / 1 isa_t constructor (uintptr_t value) : bits (value) {} / / 2 Class constructor CLS. // Uintptr_t bits; // Member 2 (occupying 64-bit memory space) #if SUPPORT_PACKED_ISA #if __arm64__ # define ISA_MASK 0x0000000ffffffff8ULL # define ISA_MAGIC_MASK 0x000003f000000001ULL # define ISA_MAGIC_VALUE 0x000001a000000001ULL struct { From low to high is nonpointer to extra_rc. The: after the member indicates how many bits the member occupies. uintptr_t nonpointer : 1; // (low) note: the flag bit indicates whether isa_t * isa real pointer!! uintptr_t has_assoc : 1; // Uintptr_t has_cxx_dtor: 1; uintptr_t shiftcls : 33; // MACH_VM_MAX_ADDRESS 0x1000000000 uintptr_t magic : 6; uintptr_t weakly_referenced : 1; // Weak reference uintptr_t deallocating: 1; uintptr_t has_sidetable_rc : 1; 1 uintptr_t extra_rc: 19; # define RC_ONE (1ULL<<45) # define RC_HALF (1ULL<<18)}; }Copy the code

Reference count table relationships

In most cases, simply using the optimized ISA_T to record the object’s reference count is sufficient. SideTable is used only when the 19-bit EXTRA_RC can’t hold that much reference count.

SideTable: is a global reference count table that records reference counts for all objects.

Let’s talk about the relationship between these four data structures. In the Runtime memory space, SideTables is an 8-element hash array that stores the SideTable. The hash key of SideTables is the address of an object obj. Table1 = h(address1), so we can say that an OBj corresponds to a SideTable. But one SideTable is going to have multiple OBJs. Since there are only 64 sidetables, many OBJs share the same SideTable.

  • Spinlock_t slock: spinlock used to lock/unlock SideTable.
  • RefcountMap Refcnts: Hash table with DisguisedPtr< OBJC_object > as key, used to store the reference count of the OC object (used only when THE ISA optimization is disabled or the ISA_T reference count overruns in the ISA optimization case).
  • Weak_table_t Weak_TABLE: Hash table that stores weak reference Pointers to objects. Is the core data structure of OC Weak function implementation.
struct weak_table_t { weak_entry_t *weak_entries; // Save all weak Pointers to the specified object size_t num_entries; // Uintptr_t mask; // Uintptr_t max_hash_displacement; // Maximum offset of hash key};Copy the code

The refcents is a hash map. The key is the address of obJ, and the value is the reference count of obJ. ReferenceCount = h (address)

Weak_table stores the address of pointer that weakly references OBj, which is essentially a hash table with OBJ address as key and the address of pointer that weakly references OBj as value. The node type of the hash table is Weak_entry_t. ObjPointer = h (address)