## object, message, runtime

### Understand the concept of “attribute” attributes of the basic use of attributes not to describe attributes

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

Attribute attributes are classified into four categories ####1, atomic When setting @property attributes of member variables, the default is atomic, providing multithreading safety. In a multithreaded environment, atomic manipulation is necessary, otherwise incorrect results may be caused. With atomic, the setter function looks like this:

{lock} 
  if(property ! = newValue) { [property release]; property = [newValue retain]; } {unlock}Copy the code

Nonatomic disables multithreading, variable protection, and improves performance. Atomic is a thread-protection technique used by Objc, basically, to prevent data errors from being read by another thread while the write is incomplete. This mechanism is resource-intensive, so nonatomic programming is a good choice ona small device like the iPhone if you don’t use communication between multiple threads. Indicates that accessors are not atomic operations, whereas by default accessors are atomic operations. That is, in a multithreaded environment, the parsed accessor provides a secure access to the property, and the return value from the accessor or set value from the setter can be done in one go, even if it is being accessed by another thread. If you do not specify nonatomic, in a self-managed memory environment, the parsed accessor retains and automatically releases the returned value. If nonatomic is specified, the accessor simply returns the value. When developing iOS applications, you should use nonatomic properties because atomic properties can seriously affect performance. ####2. Read/write permission ReadWrite automatically generates getter/setter methods readOnly Only getter methods ####3 Setup methods only perform simple assignments for scalar types (CGFloat&&NSIntger, etc.). Strong Indicates that the property defines an “ownership relationship.” The new value is retained, the old value is released, and the new value is set to weak. This indicates that the property defines a “non-ownership relationship”. Assigns neither new values nor old ones, just like assign. However, when the object to which the attribute refers is destroyed, the value of the attribute is also nil; Unsafe_unretained this attribute has the same semantics as assign, but applies to the object type. It conveys a “non-ownership relationship” (” no reservation “). When the target object is destroyed, the property value is not deleted, different from weak. Copy is similar to strong. However, the setting method does not keep the new value, but copies it. This property is often used to protect encapsulation when the attribute type is NSString, because the new value passed to the setting method might point to an instance of the NSMutableString class. This class is a subclass of NSString and represents a modifiable string, in which case if the string is not copied, the value of the string may be changed without the object’s knowledge after the property is set.

The weak attribute is assigned to nil when the object it points to disappears (i.e., the memory reference count is 0). Sending messages to the weak attribute does not result in a wild pointer crash.

How to set weak to nil automatically? The Runtime lays out the registered classes and puts weak objects into a hash table. If the reference count of this object is 0, dealloc will be dealloc. If the memory address of the weak object is A, then a will be searched in the weak table, find all the weak objects with a as the key, and set to nil.

#### @property declared nsStrings (or NSArray, NSDictionary) often use the copy keyword. Why? What problems might arise if you use the strong keyword instead?

Because a parent pointer can point to a subclass object, the purpose of using copy is to keep the properties of this object unaffected by the outside world. Whether I am passed a mutable object or an immutable object, I am holding an immutable copy. If we use strong, the property may point to a mutable object, and if the mutable object is modified externally, the property will be affected.

The copy attribute expresses ownership similar to that of strong. However, the setting method does not keep the new value, but “copies” it. This property is often used to protect encapsulation when the attribute type is NSString, because the new value passed to the setting method might point to an instance of the NSMutableString class. This class is a subclass of NSString and represents a string whose value can be modified. If you do not copy the string, the value of the string may be changed without the object’s knowledge after the property is set. So make a copy of a string that is immutable, to make sure that string values in objects don’t change unintentionally. As long as the object used to implement a property is mutable, you should make a copy when setting the value of a new property.

Try to access instance variables directly from within the object

Access to instance variables is faster because it does not go through ObjC’s method dispatch. In this case, the code generated by the compiler directly accesses the chunk of memory that holds the object instance variable. If you need to use KVO or lazy load, you still have to use properties. When reading data inside an object, you should read it directly from the instance variable. When writing data, you should write it from the property. In the initializer and dealloc methods, you should always read and write data directly from instance variables. A lazy initialization technique is sometimes used to configure a piece of data, in which case properties are required to read the data. The NSObject protocol has two key methods for determining isotropy:

-(Bool)isEqual:(id)object;
-(NSUInteger)hash;
Copy the code

To check the equality of objects, provide the isEqual: and hash methods. The same object must have the same hash code, but two objects with the same hash code may not have the same hash code. Instead of blindly monitoring each attribute individually, you should tailor your testing plan to your specific needs. When writing hash methods, use algorithms that are fast and have a low probability of hash code collisions.

### Understand the role of objc_msgSend

id returnValue = [someObject messageName:parameter];
Copy the code

SomeObject is called receiver, messageName is called selector, and the combination of selector and parameter is called Message. When the compiler sees the message, it converts it into a standard C function call, as follows

id returnValue = objc_msgSend(someObject,@selector(messageName:) parameter);
Copy the code

The message consists of a receiver, selector, and parameters. “Sending a message” to an object is equivalent to calling a method on that object. All messages sent to an object are processed by the dynamic message dispatch system, which detects the corresponding method and executes its code.

What is message forwarding? When an object receives an undecipherable message, the message forwarding mechanism is initiated.

Message forwarding is divided into two phases. The first phase asks the recipient’s class to see if it can add a method dynamically, and handles the current “unknown selector,” which is called “dynamic method resolution.” The second phase involves the “complete message forwarding mechanism”. If the runtime system has completed the first phase, then the receiver itself can no longer respond to messages containing that selector by dynamically adding a method. At this point, the run-time system requests the receiver to handle the method calls associated with the message by other means. Break it down into two steps: First, let the receiver see if any other objects can process the message. If so, the run-time system forwards the message to that receiver, and the message forwarding ends. If there is no standby receiver, the full message forwarding mechanism is started, and the run-time system encapsulates all the details of the message into the NSInvocation object, giving the receiver one last chance to resolve the message that is currently unprocessed.

In the Runtime, you can add or replace the corresponding implementation of a selector to a class. Using another implementation to replace the original method implementation is a process called Method Swizzling, and developers often use this technique to add functionality to the original view. In general, you need to modify method implementations in the Runtime only when debugging programs, and this practice should not be abused.