-1

EDIT: edited for clarity

Disclaimer: I'm new and pretty bad. But I have tried very hard and read lots of stuff to figure this out, but I have not...

I think my whole delegate pattern would work, except I can't figure out how to set the delegate property of ViewController to self in the MatchLetter class. The reason is because I can't figure out how to call code there. It's not a view controller, so viewDidLoad or prepareForSegue won't work.

This is what I've got:

ViewController.h

#import <UIKit/UIKit.h>

@class ViewController;
@protocol letterMatchProtocol <NSObject>
- (BOOL) isLetterMatch:(char) firstLetter;
@end

@interface ViewController : UIViewController
@property (nonatomic, weak) id <letterMatchProtocol> delegate;
@end

ViewController.m

#import "ViewController.h"

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

char c = 'a';

// This is the method I want to delegate to MatchLetter, to have a BOOL returned
BOOL returnValue = [self.delegate isLetterMatch:c];
}

@end

MatchLetter.h

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

@interface Delegate : NSObject <letterMatchProtocol>
@end

MatchLetter.m

#import "MatchLetter.h"

@implementation Delegate

// this is the code I think I need to run here, to set the delegate property...

// ViewController *viewController = [ViewController new];
// viewController.delegate = self;

// ... so that isLetterMatch can be run here from ViewController.m
// But I don't know where to put this code, or how to get it to run before the ViewController
// especially since there are no segues or views to load.

- (BOOL) isLetterMatch:(char)firstLetter {

if (firstLetter == 'a') {
    return YES;
}
else {
        return NO;
    }
}

@end

Can somebody please tell me the best way to proceed? Thanks for reading

Paul Pan
  • 76
  • 9
  • 1
    Where is the code that actually creates an instance of `ViewController`? Typically you would set its `delegate` at that time. – rmaddy Dec 17 '14 at 23:06
  • 2
    FYI - Naming your class `Delegate` is a bad idea. You will likely have other "delegate" classes. Give it a more descriptive name. – rmaddy Dec 17 '14 at 23:07
  • Why isn't your view controller the delegate? The correct approach is usually to make the view controller be the delegate. – Abhi Beckert Dec 17 '14 at 23:57
  • "I think I understand that you have to set the delegate as self in the actual delegate class, not an instance of the class." ???? What do you perceive as being the difference? (And you don't set `delegate` in the delegate class, you set it in the class being served by the delegate.) – Hot Licks Dec 18 '14 at 00:01
  • rmaddy, thanks for the suggestion. I added the code to create an instance of ViewController, commented out, in MatchLetter.m. I don't know which method to call it in, or even how to get into the MatchLetter.m. That's my real question – Paul Pan Dec 18 '14 at 17:37
  • Abhi Beckert, the class which is the delegate, MatchLetter, will just be holding data, so probably not appropriate for it to be a view controller – Paul Pan Dec 18 '14 at 17:39

1 Answers1

1

You asked "Where to set delegate = self? Or should I just use a different design pattern?".

Answer: Don't. An object should never be it's own delegate.

Your code is quite a mess.

Don't name a class "Delegate". A delegate is a design pattern. The whole point of a delegate is that any object that conforms to a particular protocol ("speaks the language") can serve as the delegate. You don't need to know what class of object is serving as the delegate, but only that it speaks the language you need.

An analogy: When you call the operator, you don't care who is working the operator desk. You don't care about his/her gender, religion, ethnic background, how tall they are, etc. You just care that they speak your language.

Likewise, when you set up a delegate, it doesn't matter what type of object gets set as the delegate. All that matters is that the object that is the delegate conforms to the protocol for that delegate.

A table view can have ANY object serve as it's delegate, as long as that object conforms to the UITableViewDelegate protocol. You usually make you view controller be the table view's delegate, but you don't have to. You could create a custom class that manages your table views, and have it be the delegate. There is no "TableViewDelegate" object class. There is instead a UITableViewDelegate protocol, and any object that conforms to the protocol can act as a table view's delegate.

Edit: Your question is confusing. I think what you're proposing is that your Delegate class would create a view controller and make itself the delegate for the view controller.

If that's what you are talking about, your thinking is backwards. The view controller is using the Delegate class as a helper class. Any given instance of a view controller class can create an instance of the Delegate class and set it as it's delegate if it desires. You might have 3 instances of ViewController at one time, each with it's own instance of your Delegate class.

Thus, the ViewController object is the one that should create and set up an instance of Delegate if it needs one:

- (void) viewDidLoad;
{
  self.delegate = [[Delegate alloc] init];
  //other setup here
}
Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • I only named the class Delegate as a description. I didn't think it would cause so much confusion. It is the ViewController's delegate property I'm trying to set as self in the (now renamed) MatchLetter class. I'm aware a delegate is not an object besides the @property one creates. I've cleaned up my question for clarity. I hope you will take a minute to understand what I mean – Paul Pan Dec 18 '14 at 17:47
  • The fact remains that an object should never, ever be it's own delegate. That's like trying to do open heart surgery on yourself. It tends to cause problems. – Duncan C Dec 18 '14 at 20:29
  • You're right. Unfortunately what you're right about is of no help to me because that's not what I'm trying to do – Paul Pan Dec 19 '14 at 01:45
  • I'm sure you know what you're talking about, but I don't get it, and it seems to contradict this SO answer (the brief one): http://stackoverflow.com/questions/626898/how-do-i-create-delegates-in-objective-c so I'm moving on for now. Thanks for your effort – Paul Pan Dec 19 '14 at 18:25
  • You said "... it seems to contradict this SO answer ..." Not really, no. In the accepted answer to that question, a third object creates a delegate object for NSWindow and assigns it. Note that the delegate object doesn't create the object that it is a delegate to. Do you have a specific goal in mind, or are you just doing thought exercises to try to understand the different Cocoa design patterns? – Duncan C Dec 19 '14 at 18:32
  • I figured out how to make the code run from my initial question. I _did_ just need to create a method which would be called in MatchLetter.m, within which an instance of ViewController's delegate property is set to self. Then in ViewController.m, when the protocol method isLetterMatch is called on the delegate, it runs in MatchLetter.m. I ended up using an arbitrary method in ViewController's viewDidLoad to call one in MatchLetter.m to set the delegate. Now functionality from the ViewController class is handled by the MatchLetter class, which is what I wanted to do. – Paul Pan Jan 06 '15 at 17:45