52 prepared with high efficient method iOS OS X code (Matt Galloway a) reading notes (a) Effective Objective-C 2.0

Chapter One: Familiar Objective-C

Article 1: Understanding the Objective-Corigin of language

Rule 2: In the class header file to minimize the introduction of other headers

background:

Use #import "ClassName.h"can be introduced into all the details of interfaces to other files.

problem:
  1. .h header file when compiling a use of certain types of documents need not know all the details of this class, only need to know this class is like.
  2. A header file the header file is introduced B, C header file header file A is introduced, all of the content B will be incorporated with the file header. If this process continues, we will have to introduce many never use the content, which of course increases the compilation time.
Solution:
  1. Use @class ClassName"forward declaration" (forward declaring), there is only a statement of this class, no specific details, you can solve the problem.

    Unless absolutely necessary, do not include headers. In general, you should use the header file a class forward declaration to mention other classes, and those classes introducing header in the implementation file. This will minimize the coupling between classes (coupling).

    Inheritance and comply with agreements not to use forward declarations. Sometimes you can not use the forward declaration, for example, to declare that a class follows an agreement. In this case, try to "follow a certain kind of agreement" this statement to "classify" in. If not, put the protocol in a single header file, then introduced.

    Forward declaration of action:

    1. Never use to prevent the introduction of content, reducing the header file reference details.
    2. Problem-solving two classes refer to each other.
  2. The timing of the introduction of the first document to delay as much as possible, do have introduced only when needed, thus reducing the number of documents required for the introduction of the first class of users.

Article 3: The method of multi-literal syntax, which is equivalent to less

Use literal syntax (literal syntax) can reduce the length of the source code to make it more readable.

Article 4: multi-type constant, less #definepreprocessing directives

problem:

#defineNo constants defined in the type of information, the compiler will perform accordingly find and replace operations before compilation. Even if someone redefines the constant value, the compiler does not generate a warning message, which will lead to inconsistent application of constant values.

Solution:
  • Defined "visible only within a compilation unit in the variable" static const used in the implementation file. Since these constants not in the global symbol table, so no need to prefix their name. Code is implemented as follows:
// .h 文件
@interface 类名: 父类名
...
@end

// .m 文件
// 类内使用
static const 类型 常量名 = 常量值;

@implementation 类名
...
@end

  • Use extern in the header file to declare global variables and define its value in the associated implementation file. This constant to appear in the global symbol table, so the name should be distinguished, usually prefixed with the class name associated with it.
// .h 文件

// 类外可用声明
extern 类名 const 常量名;

@interface 类名: 父类名
...
@end

// .m 文件
// 类外可用声明
类名 const 常量名 = 常量;

@implementation 类名
...
@end

Constant is the name commonly used nomenclature:

  1. Only within the class, the letters on the front k.
  2. Can also be used outside the class, the class name to the most prefix.

Article 5: enumeration indicates the status, options, status codes

  1. Use enumeration, since these values ​​to friendly names.
  2. The enumeration value is defined as a power of 2, a multi-enumerated options can be used simultaneously, can be combined by a bitwise OR operation.
  3. When enumeration is defined, which specifies the type of underlying data, ease of handling.
  4. In the process of enumeration types switchdo not realize statement defaultbranch, the ease of adding new enumeration, the compiler error, know where you want to modify.

Chapter II: Object, messages, run

Article 6: Understanding the "Properties" concept

Article 7: Direct access instance variables as far as possible inside the object

Article 8: Understand "Object equivalence" concept

  1. == Comparison operators are two pointers per se is not the object to which it refers.
  2. NSObjectProtocol declared isEqualmethod of determining the equality of two objects. isEqualThe default implementation: if and only if its "pointer value" completely equal, the two objects are equal.
  3. Equivalence class having a specific determination method. NSString: isEqualToString: NSArray: isEqualToArray: NSDIctionary: isEqualToDictionary:If the object is not to compare corresponding type, it will throw an exception, crash.
  4. Equivalence determination is performed depending on the depth of the object under test. Comparative array of the same number of objects, the objects corresponding positions are equal, equal to the array, which is called "depth equivalence determination." For performance, we recommend decreasing depth as possible.
  5. Equivalence class variable container after the determination of an object into a container, and modify its contents, it will be difficult to predict the behavior of the latter, it is recommended not to do so.

Article 9: The "class family mode" hide implementation details

Class model family : the use of inheritance, to achieve sub-class variety of functions, the parent class to create some subclasses by setting different types, to perform their respective functions. Role: The implementation details hidden behind a simple set of common interfaces. It should be noted that what is true is that type instance creation, we need to know

New Cocoain NSArraythis subclass class family, you need to follow a few rules:

  1. Subclass should inherit from the abstract base class class family.
  2. Subclasses should define its own data storage. NSArrayItself is only the cladding on the outside of other hidden object, it only defines the interface for all arrays are required to have.
  3. Need to override the method specified in the superclass subclass should override the document. In each of the abstract base class, there are some methods Subclasses must override.

Article 10: Existing associated object class is used to store custom data

Related information stored in the object:

  1. Inherited from a subclass of the class the object belongs, and then modify the subclass object.
  2. By "associated objects" characteristic of an object related to a number of other objects that are distinguished by a "key."
The associated object method:
  • And a given key storage policy settings associated object is an object value

    objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)
    

    Parameter Description:

    • object Source object associated with it.
    • keyAssociated key. Typically use static global variables do key.
    • valueAssociated with keythe corresponding value. Chuan nilcan remove the existing association.
    • policyThe associated storage strategy, which is corresponding to the memory management semantics, an enumeration.
      objc_AssociationPolicyEnumeration value as follows: | association type | @property equivalent properties | | --- | --- | OBJC_ASSOCIATION_ASSIGN | assign | OBJC_ASSOCIATION_RETAIN_NONATOMIC | nonatomic, retain | OBJC_ASSOCIATION_COPY_NONATOMIC | nonatomic, copy | OBJC_ASSOCIATION_RETAIN | retain | OBJC_ASSOCIATION_COPY | copy |
  • Gets an object corresponding to a value associated with an object from the given key.

    objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
    
  • Remove all objects associated with the specified object.

    objc_removeAssociatedObjects(id _Nonnull object)
    

Note: only when other methods are not feasible before considering using it. If the abuse, would soon make the code out of control, making it difficult to debug.

Article 11: Understanding objc_msgSendthe role of

OC Method Invocation

Code:

id returnValue = [someObject messageName: paramter];

Code Description:

  • someObject recipient.
  • messageName Select son.

And selecting sub-parameters collectively referred to as "message"

Underlying C code implementation:

id returnValue = objc_msgSend(someObject, @selector(messageName:), paramter);
Messaging mechanism core function

Prototype code:

void objc_msgSend(id self, SEL cmd, ...)

This is a "function variable number of parameters", two or more acceptable parameters. Parameter Description:

  • self recipient.
  • cmd Selectors (name of the method).
  • Those subsequent parameters Parameters Message, the sequence unchanged.

Implementation:

graph TD A [objc_msgSend] -> | obtain the recipient and selecting sub | B (receiver) B -> | method of selecting sub-match lookup with the name | C {Method list} C -> | found | D [ The example code] C -> | not found | E {find upwards along the body Inherited} E -> | found | F. [implemented method Code] E -> | not found | G [message forwarding]

Note: The OCmethod call requires many steps, more time-consuming. objc_msgSendThe results will match the cache in the "fast map", each class has such a cache. Although still not as good as "statically bound function call operator" so quickly, but not much slower.

Border situation:

  • objc_msgSend_stretReturn message to be sent to a structure , to thereby cross-function processing.
  • objc_msgSend_fpretReturn message to be sent to a float , to thereby deposit processing function.
  • objc_msgSendSuperSuperclass give a message, to thereby deposit processing function. Such [super message:parameter]as: .
Tail call optimization

Objective-CThe method of each object can be seen as a simple Cfunction prototype is as follows:

<return_type> Class_selector(id self, SEL _cmd, ...)

The prototype and objc_msgSendfunction much like to take advantage of " call optimization tail " technology. Order " Skip way to achieve " with this operation simpler.

Use: last operation of a function is call another function return value and will not be used for other purposes. Step: The compiler generates the instruction code modulation transferred to another desired function, people will not push a new "stack frame" to the call stack. Do not optimize consequences:

  1. Each call Objective-Cbefore the method, you need to call the objc_msgSendfunction ready "stack frame", can be seen in the "stack trace" in.
  2. "Stack overflow" phenomenon occurs prematurely.

Article 12: to understand the message forwarding mechanism

Message forwarding: The first stage: Dynamic Analytical Method: consult a recipient (belonging to the class), to see whether it can dynamically add a method to deal with this the "unknown selectors." The second stage: 1. backup receiver: Please recipient to see if there are no other objects (backup receivers) can handle this news. 2. The complete message forwarding mechanism: the runtime system and put all the details related messages are encapsulated into NSInvocationan object, to give the recipient last chance to make it to settle the current message has not been processed.

Dynamic method resolution

Whether a new example of a method for selecting sub-processing, call as follows:

// 实例方法
+ (BOOL)resolveInstanceMethod:(SEL)selector
// 类方法
+ (BOOL)resolveClassMethod:(SEL)selector

Use provided: a method for implementing the relevant code has been written, just like when running a dynamic insertion into the class.

Dynamic method of adding function is as follows:

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

Parameter Description:

  • cls Add method of the class
  • name Method name to be added
  • imp Function pointer to the method (C language) to be added.
  • typeMethod to be added "type code" .
Backup receiver

Are there other object processing this message, call as follows:

- (id)forwardingTargetForSelector:(SEL)selector

If the backup objects found, the method returns to backup objects, otherwise, returns nil.

Note: We can not operate this step through the forwarded message.

The complete message forwarding mechanism

Creating NSInvocationobject that contains selectors , goals and parameters .

News dispatch call as follows:

- (void)forwardInvocation:(NSInvocation *)invocation

If it is found not a calling operation processing by the class, then looking up until NSObject. If the last call NSObjectof the method, the method will continue to call doesNotRecognizeSelector:to throw an exception, indicating selection of sub ultimately failed to be processed.

to sum up:

FIG full message forwarding process is as follows:

Recipients have the opportunity to handle the message at each step. The next step, the greater cost of processing messages.

Message forwarding Code: https://github.com/AlonerOwl/Runtime/tree/master/Runtime/MessageSend

Section 13: The "method of formulation (method swizzling) technology" debugging "black box approach"

Function pointer (IMP):id (*IMP)(id, SEL, ...)

Method Table: a set consisting of a function pointer.

The method of operation of the class table:

  • New selectors
    BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
    
    Article 12've said.
  • A method of changing the corresponding selectors achieved
  • Switching two selectors are mapped pointer, i.e. two exchange methods. Methods swap function:
    func method_exchangeImplementations(_ m1: Method, _ m2: Method)
    
    Parameters: two methods to be exchanged to achieve acquisition method implemented functions:
    Method class_getInstanceMethod(Class cls, SEL name)
    

这个方法可以为那些 “完全不知道具体实现” 的黑盒方法增加日志记录功能,这非常有助于程序调试。 若是滥用,反而会令代码变的不易读懂且难于维护。

method swizzling代码:https://github.com/AlonerOwl/Runtime/tree/master/Runtime/MethodSwizzling

Guess you like

Origin www.cnblogs.com/gfxxbk/p/12095998.html