1. Combination mode

MethodA (methodB); methodA (methodB); methodA (methodB);

@interface ClassA : NSObject { } - (void)methodA; @interface ClassB: NSObject {} - (void)methodB; MethodA, methodb@interface ClassC: NSObject {ClassA *a; ClassB *b; } -(id)initWithA:(ClassA *)A b:(ClassB *)B; -(void)methodA; -(void)methodB; @implementation ClassC -(id)initWithA:(ClassA *)A b:(ClassB *) b {A =[[ClassA alloc] initWithClassA: A]; //[A copy]; b=[[ClassB alloc] initWithClassB: B]; //[B copy]; } -(void)methodA{ [a methodA]; } -(void)methodB{ [b methodB]; }Copy the code

2, protocol

Set ClassA delegate and ClasssB delegate and implement methods methodA in ClassA and methodB in ClasssB. ClassC complies with both protocols.

@protocol <NSObject> - (void) Program; @protocol Draw <NSObject> - (void) Draw; @protocol Sing <NSObject> - (void) Sing; @end // A Programmer who knew nothing at first // learned multiple skills @interface Programmer: NSObject <Draw, Sing> @end@interface Programmer () <Program> @implementation Programmer - (void)program {NSLog(@"I'm writing bugs!"); ); } - (void)draw { NSLog(@"I can draw"); } - (void)sing { NSLog(@"Lalalallalalala"); } @endCopy the code

3, classification,

Its Runtime nature gives it some advantages over protocols.

  • You can add methods to a class;
  • You can add instances to classes (via Runtime), which is not possible with the protocol;
  • Classification is easy to manage.
#import "Programmer. H "@property (nonatomic, assign) NSString *motto; // Declare public method - (void)draw; - (void)sing; @end #import <objc/runtime.h> @implementation Programmer (Program) - (void)setMotto:(NSString *)motto { objc_setAssociatedObject(self, &kMottoKey, motto, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (NSString *)motto { return objc_getAssociatedObject(self, &kMottoKey); } // private method - (void)program {NSLog(@"I'm writing bugs!" ); } // implement public method - (void)draw {NSLog(@"I can draw"); } - (void)sing { NSLog(@"Lalalalallalala"); } @endCopy the code

Message forwarding is also the dark magic of the Runtime. One of its uses is to implement multiple inheritance. When a message is sent and no corresponding method can be found, the following process is performed.

(1) Dynamic method resolution: use resolveInstanceMethod: to check whether @dynamic method is added dynamically.

(2) direct message forwarding: do not change the original method signature, direct check forwardingTargetForSelector: whether, if return not nil and the self, the forward message directly to the returned object.

(3) the standard message forwarding: first processing method call forwarding message again, rewrite methodSignatureForSelector: and forwardInvocation: method, the former is used to create a suitable method for the message sign, the latter is to forward the message to other objects.

Direct message forwarding:

/*  Programmer实现文件  */
@implementation Programmer

// 通过消息转发实现多继承
- (id)forwardingTargetForSelector:(SEL)aSelector {
    Singer *singer = [[Singer alloc] init];
    Artist *artist = [[Artist alloc] init];
    
    if ([singer respondsToSelector:aSelector]) {
        return singer;
    }
    else if ([artist respondsToSelector:aSelector]) {
        return artist;
    }
    return nil;
}
@end

/*  Artist代码  */
@interface Artist : NSObject
// 画家可以绘画
- (void)draw;
@end

@implementation Artist
- (void)draw {
    NSLog(@"I can draw");
}
@end

/*  Singer代码  */
@interface Singer : NSObject
// 歌手会唱歌
- (void)sing;
@end

@implementation Singer
- (void)sing {
    NSLog(@"Lalalalalala");
}
@end
Copy the code

By forwarding messages directly to other types of objects, we achieve multiple inheritance. The result is singing and drawing

Programmer *programmer = [[Programmer alloc] init]; // Using NSSelectorFromString in performSelector causes a warning // You can disable the warning by setting it not to detect memory leaks in performSelector performSelector:NSSelectorFromString(@"sing") withObject:nil]; // This can be done by typing strong, without warning [(Artist *)programmer draw];Copy the code

With message forwarding, we make it dynamic and really hand off methods to other classes rather than protocols or classes that need to be implemented themselves. Message forwarding also gives us the flexibility to declare sing and draw methods in the Programer class, but to call them via type coercion without exposing these interfaces.

Standard message forwarding:

Standard message forwarding is more advanced than direct message forwarding. Programmers can control the forwarding process and realize the forwarding of multiple objects. Direct message forwarding can only directly forward the method to another object.

@interface Programmer () {// For frequent use, we can create member instance Singer *_singer; Artist *_artist; } @end @implementation Programmer - (instancetype)init { if (self = [super init]) { _singer = [[Singer alloc] init]; _artist = [[Artist alloc] init]; } return self; } / / before forwarding messages to method signature again - (NSMethodSignature *) methodSignatureForSelector aSelector: (SEL) {/ / try to realize the method signature NSMethodSignature *signature = [super methodSignatureForSelector:aSelector]; If (signature == nil) {if (signature == nil) {if (signature == nil) { And through its create method signature if ([_singer respondsToSelector: aSelector]) {signature = [_singer methodSignatureForSelector: aSelector]; } else if ([_artist respondsToSelector:aSelector]) { signature = [_artist methodSignatureForSelector:aSelector]; } } return signature; } // after the method is signed, the message will be sent - (void)forwardInvocation:(NSInvocation *)anInvocation {SEL SEL = [anInvocation selector]; // Determine which class implements this method if ([_singer respondsToSelector:sel]) {[ansinger invokeWithTarget:_singer]; } else if ([_artist respondsToSelector:sel]) { [anInvocation invokeWithTarget:_artist]; }} @end /* Singer and Artist implement the same code as above */Copy the code

The call is executed normally. Standard message forwarding is not really necessary to implement multiple inheritance and can be used to its advantage when we need to process messages.

methods Add attributes Add methods Inherits the implementation of the parent class
Protocol (Protocol) a. low a.
Classification (Catagory) low low a.
forward low low low
  • Properties of classification are implemented through Runtime associated objects, and properties of message forwarding are implemented in a similar way.
  • Classification and message forwarding are closer to true multi-inheritance and are easy to manage, adding and deleting parent classes is easy.