0

I'm new to using delegates in Swift, and I can't seem to figure out how to communicate with my View Controller from a different class. Specifically, I call the custom class's functions from my App Delegate, and then from within that custom class, I call a function within my View Controller. My basic setup, following this question, is:

AppDelegate.swift:

var customClass = customClass()
func applicationDidFinishLaunching(aNotification: NSNotification) {
    customClass.customFunction()
}

CustomClass.swift:

weak var delegate: ViewControllerDelegate?
func customFunction() {
    delegate?.delegateMethod(data)
}

ViewController.swift:

protocol ViewControllerDelegate: class {
    func customFunction(data: AnyObject)
}
class ViewController: NSViewController, ViewControllerDelegate
    func customFunction(data: AnyObject){
        println("called")
    }
}

However, delegate is always nil. I am assuming this is either because the ViewControllerDelegate protocol never gets initialized or because I never set the delegate of the actual NSViewController? I know I'm missing something obvious/straightfoward, however I have yet to see what that is.

Community
  • 1
  • 1
Charlie
  • 11,380
  • 19
  • 83
  • 138

1 Answers1

1

Your question is hard to answers because you have completely misunderstood the point of a protocol.

A protocol is a type which is used to define functionality. A class that conforms to this protocol provides the specified functionality, by implementing the required methods.

You can not initialize a protocol.

So if your CustomClass looks like this:

class CustomClass {
    weak var delegate: ViewControllerDelegate?
    func customFunction() {
        delegate?.delegateMethod(data)
    }
}

Why do you expect that delegate has suddenly a value?

Of course you have to set delegate to something first. The delegate must set delegate. If you want a ViewController instance to be the delegate, it must assign itself to delegate.

This for instance will work.

protocol ViewControllerDelegate {
    func delegateMethod(data: AnyObject) //I renamed this because in   
    //CustomClass you are trying to call `delegateMethod` on the delegate
}
class CustomClass {
    weak var delegate: ViewControllerDelegate?
    func customFunction() {
        delegate?.delegateMethod(data)
    }
}
class ViewController: NSViewController, ViewControllerDelegate

    var customClass = CustomClass()

    func viewDidLoad(){
        customClass.delegate = self
        customClass.customFunction() 
    }

    func delegateMethod(data: AnyObject){
        println("called")
    }
}

Read more about delegation here.

idmean
  • 14,540
  • 9
  • 54
  • 83
  • `you have completely misunderstood the point of a protocol` I apologize! Thanks for the answer though. One more question: if I initialize the custom class from the AppDelegate, what's the best way to get the already initialized instance of it in the ViewController when setting the delegate? As of now, since I initialize it in my AppDelegate as a variable, I reference it in my ViewController by `let customeClass = (NSApplication.sharedApplication().delegate as! AppDelegate).customClass` but this seems prone to failure... – Charlie Jun 06 '15 at 14:51
  • @Charlie I already expected that question . It is possible (and not wrong) to reference the instance like you showed in your comment. But there are better ways (up to my opinion): Make CustomClass a singleton class; or declare a global variable above app delegate. – idmean Jun 06 '15 at 14:55
  • Would it be poor practice then to make a custom class `GlobalManager` that has something like `static let customClass = CustomClass()` in it, which I can then reference all the time? – Charlie Jun 06 '15 at 14:59
  • @Charlie Not at all! But you don’t have to create a own class you can just create a global by putting `let customClass = CustomClass()` anywhere outside a class. However your solution may be better because it protects against unintended shadowing of a global variable. – idmean Jun 06 '15 at 15:01