Delegation in Swift

This is the second issue in my post "ProgressBar with DispatchQueue", delegation.

I have used delegates with menu items but not program vars.

In the previous post my ViewController has a progress bar but I would like the progress.DoubleValue var to be updated in a remote function, i.e., a function not declared within the ViewController class. (If I moved the function into the ViewController it would double in size.)

How do I create and implement such a delegate? Please give example code. Thanks.

Accepted Reply

Type is NSProgressIndicator

.

a function not declared within the ViewController class.

Where is it declared ?

  • In another VC ? Then see following for delegation.
  • If just in another class, but not a VC, call the func as OtherClass.thefunc() - That's not delegation.

You can read this (old) thread with my answer:

https://forums.developer.apple.com/thread/111569

Here is the pattern. This was to update a UITextField but could be adapted to other objects and to AppKit easily.

  • You have VC1 and VC2 ; you want to update a field in VC1 when you change a text in VC2.
  • Declare a protocol
protocol UpdateVC1 {
    func updateName(newName: String)
}
  • Declare that VC1 conforms to it, and implement it:
  • Set the delegate property of VC2 when you segue
class VC1: UIViewController, UpdateVC1 {
    @IBOutlet weak var userNameField: UITextField!

    func updateName(newName: String) {
        userNameField.text = newName
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destination = segue.destination as? VC2 {
            destination.delegate = self
        }
    }

}
  • In VC2 declare a delegate property:
class VC2: UIViewController {

    var delegate: UpdateVC1?
  • Then, when you change the field with name, invoke the delegate
        delegate?.updateName(newName: name)

Replies

There is no type called "ProgressBar".
Can you give more information?

You have tagged your question with "Swift", so perhaps you mean a UIProgressView, or an NSProgressIndicator?

Type is NSProgressIndicator

.

a function not declared within the ViewController class.

Where is it declared ?

  • In another VC ? Then see following for delegation.
  • If just in another class, but not a VC, call the func as OtherClass.thefunc() - That's not delegation.

You can read this (old) thread with my answer:

https://forums.developer.apple.com/thread/111569

Here is the pattern. This was to update a UITextField but could be adapted to other objects and to AppKit easily.

  • You have VC1 and VC2 ; you want to update a field in VC1 when you change a text in VC2.
  • Declare a protocol
protocol UpdateVC1 {
    func updateName(newName: String)
}
  • Declare that VC1 conforms to it, and implement it:
  • Set the delegate property of VC2 when you segue
class VC1: UIViewController, UpdateVC1 {
    @IBOutlet weak var userNameField: UITextField!

    func updateName(newName: String) {
        userNameField.text = newName
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destination = segue.destination as? VC2 {
            destination.delegate = self
        }
    }

}
  • In VC2 declare a delegate property:
class VC2: UIViewController {

    var delegate: UpdateVC1?
  • Then, when you change the field with name, invoke the delegate
        delegate?.updateName(newName: name)

Sorry, robnotyou, I should have posted the link: https://developer.apple.com/forums/thread/694710 to my previous post where Claude31 contributed heavily. In it Clause31 creates example program with a progressBar within the VC class and thus progressBar.doubleValue is recognized. But in my actual app "remote func" is not in the VC class nor any other class but is just in a separate file, alone, by itself at 800 lines of code. I don't want to fatten my already bloated VC file. The remote function runs many iterations thus the need for a progress indicator. A delegate (if I understand correctly) will update the progressBar.doubleValue even though the delegate itself is changed in the remote func. I hope that is clearer. I may be asking for something that can't be done.

I have dabbled in SwiftUI and what I am asking for in Swift is something analogous to an EnvironmentVariable update scheme, i.e., when the other file changes a value it is reflected in the VC. wherever it is needed.

I don't want to fatten my already bloated VC file.

Personally, I don't care too much about thiat. As long as the pattern (MVC) is correctly implemented and the model related func are kept apart, the number of lines is not that much of a problem. And the animation of the progressIndicator does fits well inside VC.

The point is that you refer to an IBOutlet, hence getting this progressIndicator outside may not be the best.

Did you understand the delegation example or do you miss something ?

  • I didn't mean to abandon this thread, it's just that I've tested the code and discovered the nested for-loops execute over 1.5E14 times and would require over 650,000 days to compute. A progress indicator is moot. I'm looking into whether GPU efforts would even help. It's mostly an issue of getting the results to memory and then storage. Since the memory required is tens of GB if not hundreds of GB, I/O speeds dictate not computational speeds. So I'm also re-thinking compromises. In the mean time, Claud31 did answer my question in a few different ways, so I'll close the thread.

  • @G.U.T.explorer "discovered the nested for-loops execute over 1.5E14 times": that's effectively a lot and we may not have the patience to wait till year 3800 😉. But what loop do you refer to ? In which code precisely ?

Add a Comment

I have migrated my app to SwiftUI and this issue is solved in my post "EnvironmentObject as progressValue in ProgressView()" Thanks

As for my apps "nested for-loops" I am pursuing DispatchQueue with multiple cpu's. See my post: "precompiler test for cpu count". My six cpu Mini now requires three months of computations, not a thousand years.