Because the one-to-many implementation of notification can cause a series of problems such as memory leakage and the coupling relationship is too discrete, we want to implement one-to-many notification by proxy.

Requirement: When multiple classes are subject to a protocol and they implement the same method in the protocol, one of the proxy methods is fired, and all classes will fire the proxy method.

Create a management class for the agent that records the target that implements the class and implements message forwarding.

- (void)addTarget (id)target protcol (id)protocol {if (! [self.refTargets.allKeys containsObject:protocol]) { NSPointerArray *targets = [NSPointerArray weakObjectsPointerArray];  [targets addPointer:(__bridge void * _Nullable)(target)]; [self.refTargets setObject:targets forKey:protocol]; } else { NSPointerArray *targets = [self.refTargets objectForKey:protocol]; if ([targets.allObjects containsObject:target]) { return; } [targets addPointer:(__bridge void * _Nullable)(target)]; }} / / the method signature - (NSMethodSignature *) methodSignatureForSelector: (SEL) aSelector {NSMethodSignature * sig = [super methodSignatureForSelector:aSelector]; if (! sig) { for (id key in self.refTargets.allKeys) { NSPointerArray *targets = [self.refTargets objectForKey:key]; for (id obj in targets) { if ((sig = [obj methodSignatureForSelector:aSelector])) { break; } } } } return sig; } // method - (void)forwardInvocation:(NSString invocation *)anInvocation {for (NSString* key in self.refTargets. AllKeys) { NSPointerArray *targets = [self.refTargets objectForKey:key]; const char *name = [key UTF8String]; Protocol *protocol = objc_getProtocol(name); NSAssert(protocol! =nil, @" nonexistent protocol "); struct objc_method_description protocol_method_description = protocol_getMethodDescription(protocol, anInvocation.selector, YES, YES); if (protocol_method_description.name! =nil) { for (id obj in targets) { if ([obj respondsToSelector:anInvocation.selector]) { [anInvocation invokeWithTarget:obj]; }}}}} // Remove a target class - (void)removeProtocol:(id)protocol{if ([self.reftargets. AllKeys containsObject:protocol]) { [_refTargets removeObjectForKey:protocol]; }} // removeAll target classes - (void)removeAll{[self.refTargets removeAllObjects]; } / / whether to segment the target class is to implement the agreement - (BOOL) respondsToSelector: (SEL) aSelector {the if ([super respondsToSelector: aSelector]) {return YES; } for (id key in self.refTargets.allKeys) { NSPointerArray *targets = [self.refTargets objectForKey:key]; for (id obj in targets) { if ([obj respondsToSelector:aSelector]) { return YES; } } } return NO; }Copy the code