Source code parsing for Aspects is going to be covered in two articles, one on parsing and the second on why the author did it. This is the source code process analysis

Source connection Aspects

Source analysis of Aspects (a) Source analysis of Aspects of the hundred thousand why (two)

Process:

In the method foo that replaces A

  1. Generates A subclass B of A named A__Aspects_

  2. Replace B’s forwardInvocation: the implementation is __ASPECTS_ARE_BEING_CALLED__

  3. Replace B’s -(Class) Class and + (Class) Class implementations, and return A Class

  4. Add a method implementation named foo_aspects_ to B that implements method foo and replace the implementation of source method foo with _objc_msgForward

  5. When the foo method is called after the hook, jump to

    __ASPECTS_ARE_BEING_CALLED__
    Copy the code

    To deal with

    1. Foo -> _objc_msgForward -> __ASPECTS_ARE_BEING_CALLED__

Main members:

AspectsContainer (Stores all sliced Objects/classes)

Bind to self via an associative object with key aspects__foo

NSArray<AspectIdentifier *> *beforeAspects

NSArray<AspectIdentifier *> *insteadAspects

NSArray<AspectIdentifier *> *afterAspects
Copy the code

AspectIdentifier

Store block signatures and check whether the number of parameters exceeds the original method

Add to AspectContainner according to option

Perform [blockInvocation invokeWithTarget: ` ` self * * * * ` `. Block];

AspectTracker

There is a singleton swizzledClassesDict where key is class

AspectInfo (callback assembly storage information)

Contains the signature and instance of the original method, and the callback uses storage parameters

Flow chart & reference relationships

Detail implementation (worth learning) :

  1. Find the block signature by the flags of the different blocks

    signature
    Copy the code
    1. Understand block structure composition and detailed operation
  2. Why isa disallowedSelectorList a singleton

    1. The blacklist is global. If the blacklist is a singleton, you do not need to create it every time
  3. Enumerator bit operation

    1. Used for filtering
  4. Why replace

    forwardInvocation
    Copy the code
    1. Message is sent
    + (BOOL)resolveClassMethod:(SEL) SEL OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0); - (id) forwardingTargetForSelector: (SEL) aSelector OBJC_AVAILABLE (10.5, 2.0, 9.0, 1.0, 2.0); - (void)forwardInvocation:(NSInvocation *)anInvocation OBJC_SWIFT_UNAVAILABLE("");Copy the code
    1. Direct calls and better calls
  5. Hooked check:

    1. Whether the parent/subclass has been replaced, whether it has been replaced (loop call)
    2. Block parameter length
  6. Why singletons are used for whitelist. Why is the whitelist set

    1. Avoid errors and illogic
    2. Because the whole thing repeated calls, repeated generation, wasted performance
  7. The hook of the class method using a structure similar to KVO

    1. Avoid interfering with the original class implementation
  8. Why is id returned

    1. Screen out details. Give you what you want

Remark:

Official signature Type Encodings document