An overview of the

The last article covered AOP concepts and some application examples, and SFAspect implements AOP based on message forwarding. This article focuses on the implementation of SFAspect

Implementation principle of AOP

  • Pre knowledge: Runtime
  • How to hook with Runtime
  • Perform hook operations
  • Hook undoing and class destruction
  • Other details

runtime

SFAspect is realized based on message forwarding in Runtime. Because runtime involves a lot of knowledge points, it will be analyzed in another article

  • Rumtime overview
  • Message sending and message forwarding mechanisms

The iOS Runtime provides an overview of object-oriented basics like OC and the flow of messaging mechanisms

In objC library source analysis (3)- method call – message sending and objC library source analysis (3)- method call – message forwarding, from objC source code detailed analysis of message sending and message forwarding process


How to hook with Runtime

Function calls in Objective-C are actually function calls converted to the objc_msgSend family, which is message sending,

Objc_msgSend () is called with the recipient object target and method name sel and the parameters. In the objc_msgSend function back to find the method cache, to see if the class cache exists sel corresponding method IMP. If not, lookUpImpOrForward() is executed to find the IMP corresponding to sel.

LookUpImpOrForward () looks for the IMP of the method. If it can’t find the method, it goes to dynamic parsing. If it still can’t find the method, the IMP of sel is set to _objc_msgForward and stored in the method cache. Set IMP to forward_IMP, which means the method call is about to enter the message forwarding process.

Forward process has two step 1 for alternative execution object, also is called forwardingTargetForSelector method 2 if could not find the object, alternative execution will internal digestion, Call methodSignatureForSelector access method signatures and call forwardInvocation perform custom operations

SFAspect is implemented by setting the IMP corresponding to sel of the called method as _objc_msgForward, so that the called method enters the message forwarding process. And in the custom methodSignatureForSelector and forwardInvocation custom operations to achieve AOP functionality. The following figure

Through the method of exchange to be realized for the class to add custom methodSignatureForSelector and forwardInvocation method, and then in a custom forwardInvocation perform the operation, we need to implement the hooks in the OC.


Perform hook operations

As mentioned above, the custom forwardInvocation will work, so how to use the custom forwardInvocation?

  1. encapsulation

When we first call hookSel or hookAllClassSel, we wrap the contents of hookSel and hookAllClassSel (the hook object, hook ID, priority, sel, and action block) into a SFAspectModel object

  1. The binding

Add the SFAspectModel object to the SFAspectContainer of the hook object. SFAspectContainer is a container class that manages all the hook content of the hook object. SFAspectContainer is bound to the object’s class by dynamically binding objc_setAssociatedObject (to a class if the object is an instance, or to its corresponding metaclass if the object is a class)

  1. operation

When the hook method is called, the message forwarding flow is started and the custom forwardInvocation is executed. Pick the SFAspectContainer from the hook in the custom forwardInvocation, pick the SFAspectModel from the container, and pick the SFAspectModel operation block

The relationship of the above three steps is shown below

Hook a method by forcing the method call into message forwarding and the above steps.

In SFAspect, you can hook all instances of a class through hookAllSel, and you can hook an object through hookSel.

  • For an object that hooks all instances of a class, the steps in the diagram are performed in the class of the object
  • Hook an object by dynamically generating a subclass, pointing the object’s ISA pointer to the new subclass (the same way KVO does), and then doing the above operations in the subclass

Hook undo subsequent operations and class restore

  • Stop subsequent operations

SFAspect can stop subsequent operations by calling SFAspectModel’s stop method. In fact, the implementation is very simple, that is, by throwing an exception. When we hook a method, we use a try catch without a hook operation, as shown in the figure below

When the stop invocation is called, an Error is raised, and when the catch Error occurs, the forwardInvocation is exited

  • About class reduction

When we call the removeHook method, we check the SFAspectModel of the sel hook object in the SFAspectContainer of the object’s class. If so, we delete it. When the SFAspectContainer is empty, it is destroyed. And at the same time to reset the hook method, methodSignatureForSelector and forwardInvocation method,


Other details

Some details in the article did not raise the price to, such as hook priority control, dynamic generation of subclass release, lock operation code is not much, if interested in children can download the source code to see