Obj-C: I'm trying to understang delegates, but

2019-09-22 00:15发布

问题:

I saw the example with Flower an MyGarden, but when I try to make something similar it doesn't work. My code:

ClassA.h:

#import <Foundation/Foundation.h>

@protocol CommDelegate <NSObject>
@required
-(void)funcB;
@end

@interface ClassA : NSObject
{
    id <CommDelegate> delegate;
}
@property (retain) id delegate;
-(void)funcB;
@end

ClassA.m

#import "ClassA.h"

@implementation ClassA
-(void) start
{
    [[self delegate] funcB];
}
@end

ClassB.h

#import <Foundation/Foundation.h>
#import "ClassA.h"

@interface ClassB : NSObject <CommDelegate>
@end

ClassB.m

#import "ClassB.h"

@implementation ClassB
-(void)funcB
{
    NSLog(@"HELLO!");
}
@end

And in main I'm doing:

ClassA* classa = [[ClassA alloc] init];
[classa start];

Could someone help me, and tell what I'm doing wrong?

回答1:

Delegation overview summary:

  1. Create a @protocol which is the methods that you wish to be callable from the delegator but are provided by your delegate.
  2. Add delegate @property in delegator's public @interface.
  3. Use delegate property inside delegator's implementation e.g. result = [self.delegate methodInProtocol]
  4. Set the delegate property somewhere in the delegate's @implementation: delegator.delegate = self;
  5. Implement the protocol method(s) in the delegate (include <> on @interface)

The delegate is just a pointer to an object that will implement the necessary methods for you. In your case, I think you want classA to be able to call a funcB method, but for that funcB to be implemented by someone else.

There needs to be a delegate property in the class that wants to have another class implement these methods and then in the class that is to be the delegate, it should set the delegate property to self.

As others have noted, you don't set your delegate. Somewhere in classB you need a

ClassA.delegate = self;


回答2:

ClassA* classa = [[ClassA alloc] init];
[classa start];

It appears that you need to set classa's delegate. Normally, you'd expect the call to -start to invoke the delegate method, but classa doesn't have a delegate here. Do this:

ClassB* classb = [[ClassB alloc] init];
ClassA* classa = [[ClassA alloc] init];
classa.delegate = classb;
[classa start];


回答3:

  1. You never set the delegate
  2. You generally assign delegates rather than retain them to avoid retain cycles. (The object that assigns the delegate usually will have a strong reference to the objecte and is responsible for setting the delegate to nil when done)

#import <Foundation/Foundation.h>
@protocol CommDelegate <NSObject>
@required
-(void)funcB;
@end

@interface ClassA : NSObject
{
    id <CommDelegate> delegate;
}
@property (assign) id delegate; //assign
-(void)funcB;
@end

This is the important part:

ClassA* classa = [[ClassA alloc] init]; //Consider creating an init method that accepts the delegate
classa.delegate = self; //Assuming self conforms to CommDelegate
[classa start];