4

I have one UIViewController and UIView(As Component). Below is code for the component.

class ProcessingProgressIndicator: UIView {

   var progressView: UIProgressView!

   func changeProgress(_ progress: Float) {
      progressView.progress = progress
   }
}

So I use this component in multiple controllers. So when I need to change the value of progress I have used as below in my controller.

 myProgressView.changeProgress(progress)

So to make the component Protocol Oriented I added below to code.

protocol ProgressUpdateable {
    func updateWith(progressView: ProcessingProgressIndicator,progress: Float)
}

extension ProgressUpdateable {
    func updateWith(progressView: ProcessingProgressIndicator,progress: Float) {
        // Method gets called and can change progress
    }
}

So from my controller, I call method as below

updateWith(progressView: progressView,progress: progressData.progress)

This is how I made it protocol oriented.

So my question is that: Is it correct way of implementation?

I need to pass the object of progressView can I get rid of it?

Parth Adroja
  • 13,198
  • 5
  • 37
  • 71
  • You would need to make your custom component, conform to the protocol and then use it to call the method. Where is the confusion? – Puneet Sharma Feb 15 '17 at 06:23
  • Can you describe how to do make it conform to protocol? – Parth Adroja Feb 15 '17 at 06:27
  • @parth Adroja make sure your first controller knows about the second controller by confirming to its delegate. – Tushar Sharma Feb 15 '17 at 06:29
  • @ParthAdroja Where do you want to update the progress? Does your custom object contains the UIProgressView? When do you update the progress? Is there any function that works inside custom component to update progress variable which in turn is used to update the progress? – KrishnaCA Feb 15 '17 at 06:31
  • class CustomComponent:ProgressUpdateable {func updateWith(progress: Float) {// Update progress of UIProgressView here}} – Puneet Sharma Feb 15 '17 at 06:33
  • @KrishnaCA I want to update value from my controller but not using the object.methodName. And the custom object has UIProgressView not the controller. – Parth Adroja Feb 15 '17 at 06:36
  • @ParthAdroja If the custom object has `UIProgressView`, why do you want to delegate that task to the controller which doesn't own the `UIProgressView`. If the controller owns the `UIProgressView`, then it will be better to delegate the task of updating the `UIProgressView` to the controller. Since the custom object has `UIProgressView`, I believe the current scenario is better way of doing it. – KrishnaCA Feb 15 '17 at 06:40
  • Are you meaning delegation? where is the actual code for increasing the value of `progress`? – Ahmad F Feb 15 '17 at 07:08
  • @ParthAdroja ideal way would be progressView.updateProgress(progress) that you are doing, if you use protocol even then you will call the method same way `progressView.updateProgress(progress)` as `ProgressView(Custom component)` will have to implement the protocol. If you don't want to use object then use `PostNotifications` or `KVO` which would be little overwork for such a case. – Suhit Patil Feb 15 '17 at 07:26
  • @AhmadF Yes I mean delegation, my actual code of updating progress is in component. – Parth Adroja Feb 15 '17 at 07:44
  • Could you add the code that should increment the value of progress in a code snippet? – Ahmad F Feb 15 '17 at 07:47
  • @AhmadF Added code snippet. – Parth Adroja Feb 15 '17 at 07:56

3 Answers3

4

So to make the component Protocol Oriented I added below to code.

protocol ProgressUpdateable {
    func updateWith(progressView: ProcessingProgressIndicator,progress: Float)
}

extension ProgressUpdateable {
    func updateWith(progressView: ProcessingProgressIndicator,progress: Float) {
        // Method gets called and can change progress
    }
}
So from my controller, I call method as below

updateWith(progressView: progressView,progress: progressData.progress)

This is how I made it protocol oriented.

Parth Adroja
  • 13,198
  • 5
  • 37
  • 71
0

What you are talking about is using a Protocols for Delegation.

This is Apple documentation, very well edited I can say, where they explain all about Protocols. Read it all but jump to the Delegation session to see exactly what you are looking for.

pinedax
  • 9,246
  • 2
  • 23
  • 30
0

If your attention is to achieve it via delegation (there are other options, such as returning the progress value in a closure parameter), it should be similar to:

protocol CustomComponentDelegate {
    func customComponentProgressDidStartUpdate(component: UIView, progressValue: Float)
}

class CustomComponent: UIView {

    var delegate:CustomComponentDelegate?

    // ...

    func updateProgressValue(progress: Float) {
        progressView.progress = progress/100.0
        progressLabel.text = "\(Int(progress)) %"

        delegate?.customComponentProgressDidStartUpdate(component: self, progressValue: progressView.progress)
        // or you might want to send (progress/100.0) instead of (progressView.progress)
    }

    // ...
}

I assumed that your custom component is a subclass of UIView, it shouldn't make a difference.

Usage:

class ViewController: UIViewController, CustomComponentDelegate {
    //...

    // or it might be an IBOutlet
    var customComponent: CustomComponent?

    override func viewDidLoad() {
        super.viewDidLoad()

        //...

        customComponent?.delegate = self
    }

    func customComponentProgressDidStartUpdate(component: UIView, progressValue: Float) {
        // do whatever you want with the returned values
    }
}

Note that if updateProgressValue scope updating the progress value as a real-time, then customComponentProgressDidStartUpdate delegate method should be also executed as a real-time.

Also, you might want to check this question/answer for more understanding about what's going on here.

Hope this helped.

Community
  • 1
  • 1
Ahmad F
  • 30,560
  • 17
  • 97
  • 143
  • Actually, this is not I am looking for, your case is like Controller gets back the value from progress. What I am trying to do is like Controller will send the progress value to the component using protocol and there component will do relevant things. Your case is actually reverse then what I want. – Parth Adroja Feb 15 '17 at 09:48
  • So, do you mean that `updateProgressValue` is exist in the controller? and you want to send it to the customView? – Ahmad F Feb 15 '17 at 09:52
  • It's in component and I am using it as object.method but I am looking for some other way to do it. – Parth Adroja Feb 15 '17 at 09:54
  • What if you reversed the relation between them? i.e let the view to trace the ViewController values (ViewControllerDelegate), is that will solve your issue? – Ahmad F Feb 15 '17 at 10:07