I’ll start with an example of NSProxy use.

Example of using NSProxy

@interface BDWeakProxy : NSProxy

@property (nonatomic, weak) id target;

@end

@implementation BDWeakProxy

- (instancetype)initWithTarget:(id)target {
    self.target = target;
    return self;
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:self.target];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    return [self.target methodSignatureForSelector:sel];
}

@end

Copy the code

According to the official documentation, by overriding these two methods, you can use BDWeakProxy to forward messages to Target.

But what about NSObject?

@interface BDWeakProxy : NSObject

@property (nonatomic, weak) id target;

@end

@implementation BDWeakProxy

- (instancetype)initWithTarget:(id)target {
	self = [super init];
    if (self) {
        self.target = target;
    }
    return self;
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:self.target];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    return [self.target methodSignatureForSelector:sel];
}

@end

Copy the code

Can also do message forwarding, what is the difference between the two?

NSProxy is different

  1. NSProxyClass is notinitmethods
  2. NSProxyIs an abstract class, and the parent class is notNSObject
  3. Some of theNSObjectIn some waysNSProxyDo not implement
  4. NSProxyThe message forwarding mechanism of

The message forwarding mechanism for a general object is shown below.

There is no need to explain the message forwarding mechanism. The two examples above finally use the message forwarding mechanism, and the message is forwarded to target in the last step.

As mentioned in this article, a proxy class that inherits from NSObject does not automatically forward respondsToSelector: and isKindOfClass: methods, whereas a proxy class that inherits from NSProxy does. The other interfaces defined in the test behave the same.

Practical reasons:

  1. NSProxyDo not implementrespondsToSelector:andisKindOfClass:These two methods are therefore forwarded.
  2. NSObjectThere are implementation.

NSProxy message forwarding mechanism

The focus is on the NSProxy approach.

NS_ROOT_CLASS
@interface NSProxy <NSObject> {
    Class	isa;
}

+ (id)alloc;
+ (id)allocWithZone:(nullable NSZone *)zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
+ (Class)class;

- (void)forwardInvocation:(NSInvocation *)invocation;
- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel NS_SWIFT_UNAVAILABLE("NSInvocation and related APIs not available");
- (void)dealloc;
- (void)finalize;
@property (readonly, copy) NSString *description;
@property (readonly, copy) NSString *debugDescription;
+ (BOOL)respondsToSelector:(SEL)aSelector;

- (BOOL)allowsWeakReference NS_UNAVAILABLE;
- (BOOL)retainWeakReference NS_UNAVAILABLE;
@end
Copy the code
  1. NSProxyandNSObjectThe same isNS_ROOT_CLASS, which is the root class
  2. NSProxyIs to realize the@protocol NSObject“Rather than inheritance@interface NSObject
  3. NSProxyInstead of the first and second steps of message forwarding, go straight to the third step,NSProxyThere is no corresponding method implemented

In fact, NSProxy does not implement any instance methods, although the – (Class) Class method is implemented.

This makes the

  1. NSProxyIt’s pure, it’s clean, it’s notNSObjectThere are many categories, many ways not to forward
  2. NSProxyMethod is little, alwaysNSProxyMethods that are not implemented can be forwarded, which means that almost any method can be forwarded
  3. NSProxyProxy classes can be designed to be more pure

The purpose of the NSProxy

  1. AOP
  2. The proxy pattern, the Decorator pattern, and here is a simple demo for reference
  3. Multiple inheritance, which simulates multiple inheritance by referencing multiple targets.