Are custom protocol methods supposed to work in ANY view controller?

I have a delegate method that works perfectly between a child view and its parent view. However, I have another delegate method that does not work between another child view and the just mentioned child view.


It has always been my belief that a delegate method should work between any and all views, not just between child view's and their parent views. If this is correct, then my code is flawed (shudders ...).


Any comments or suggestions will be most welcome.


Thanks.

Can you explain what you mean by "between"? The standard delegate pattern is more like "hanging off the side of", rather than "sitting between". Perhaps a short code fragment to show what you're doing.


In general, though, a delegate pattern be used anywhere. One thing to be careful of is that in Swift 4, methods in Obj-C classes are not automatically @objc, so it's possible via some trivial omission to fail to conform to a protocol.

Thanks for your comments.


Here is a link to a graphic that shows what I am trying to accomplish.


http://doggonegoodapps.com/page/page-2/


I will add my code in a few.

I just made a comment but it is being moderated probably because I included a link to a graphic.


I will add my code in a minute.


Thanks for your help.

Here's the link again:

doggonegoodapps.com/page/page-2/


doggonegoodapps dot com / page /page-2 /

This is my code from view-a:


/
protocol DetailViewControllerDelegate: class {
    func updateTipData(foodnDrinkData: String?, taxData: String?,
                            tipData: String?, splitData: String?)
}
weak var delegate: DetailViewControllerDelegate?


func updateTipTextFields(){ /
        print("\nIN   Detail-VC   >   updateTipTextFields().................................................\n")
   
        delegate?.updateTipData(foodnDrinkData: detailFoodnDrinkTextField?.text,
                               taxData: detailTaxTextField?.text,
                               tipData: detailTipPercentTextField?.text,
                               splitData: detailSplitTextField?.text)
   
        print("\n               EXIT   Detail-VC   >   updateTipTextFields().................................................\n")
    }

The updateTipData() method is triggered in textFieldDidEndEditing(). All of the above code resides in the DetailViewController class. (view-a in the graphic)


The following code is in the TipperoniViewController: (view-A in the graphic)

class TipperoniViewController: UIViewController, UITextFieldDelegate, DetailViewControllerDelegate {


So now the TipperoniViewController class conforms to the DetailViewControllerDelegate protocol.

And here is the protocol delegate pattern method:


func updateTipData(foodnDrinkData: String?, taxData: String?,
                            tipData: String?, splitData: String?) {
        print("\nIN     Tip-VC   >  updateTipData(...) .................................................YES! NO! \n")

        foodnDrinkTextField.text = foodnDrinkData
        taxTextField.text = taxData
        tipTextField.text = tipData
        splitTextField.text = splitData

        saveUserData()

        print("\n               EXIT    Tip-VC  >  updateTipData(...) .......................................  YES! NO!\n")
    }

As noted earlier, this code works perfectly. What follows is the code that does not work.


Here is view-b's code:

protocol SetTipPrefViewControllerDelegate: class {
    func updateTipPrefValue(tipData: String?)
}
class SetTipPrefViewController: UIViewController, UITextFieldDelegate {
    weak var delegate: SetTipPrefViewControllerDelegate?
func updateUserTipPrefValue(){

        print("\nIN    >    SetTipPrefViewController   >   updateUserTipPrefValue() ................ 5-6-7 ... ?-?-?\n")
    
        delegate?.updateTipPrefValue(tipData: tipPrefTextField?.text)
    }

The latter method is triggered in the textFieldDidEndEditing() method.


Here is view-a's code:

class DetailViewController: UIViewController, UITextFieldDelegate, SetTipPrefViewControllerDelegate {


And here is the protocol pattern method triggered in view-a:

func updateTipPrefValue(tipData: String?) {
  
        print("\nIN   >   DetailViewController   >    updateTipPrefValue(...) .........................3-3-3-3-3-3-3\n")
  
        detailTipPercentTextField.text = tipData
             }






I
safdaI



I'm stuck here and cannot add non-code text.  Thanks for your help.

Trying the link again:


doggonegoodapps dot com / page /page-2 /


I hope you can make that work.


Back to the code issue: It seems to me that my code is correct for both protocol pattern methods, but the second method refuses to work. So, perhaps what you noted, I did omit some minor code that is preventing this method from working. I do know that textFieldDidEndEditing() does trigger the method that calls the protocol method, but the protocol method does not trigger the protocol method in view-a.


Thanks again for your help.

Since you're using a tab bar, each of the four segues coming out of the tab bar controller is a different view hierarchy, and there's nothing obvious that ensures that views on different branches all exist at the same time.


I still think your mental picture of "between" is problematic. What object has a "delegate" property? View-A or view-a? What is the actual delegate object? Is view-b an object with "delegate" property, or is it a delegate, or where do it get a delegate from?


The delegate pattern is a way of more-or-less subclassing a utility class without actually adding code to it. Instead, you add a delegate to the utility class, and supply the additional functionality in the delegate. Typically, only the utility class uses the delegate, but it's certainly possible for a third class to use the delegate via the utility class.


Can you express your design in terms of "… has a delegate", "… is a delegate of …", and "… uses the delegate of …"? I think that's where the answer lies.

Rings a bell - have we discussed view hierarchies and 'order or containment' for your app(s) before/yet?

Accepted Answer

What's the current state of this? Have you made any progress?


Now that your code is posted, I partially understand the delegate relationships you're trying to use. However you gave code for view-a twice and view-A twice, but didn't mention view-b or view-B.


Based on what I see, I would make two comments:


— I think you might be better off using notifications rather than delegation. Your code seems to be telling the delegate to update something, and it might be simpler to post a notification that saying that something update-worthy happened, and let other objects (the ones you're turning into delegates) observe that notification.


— I think you might be twisting the MVC design pattern a little (although it's hard to tell with only fragments of your code). It's kind of a "code smell" to be passing information across hierarchy boundaries like this. In the MVC design pattern, it would be more usual for the detail view controller to make changes (or cause changes to be made) to the data model, without needing to be aware that any other view controller depends on those changes. Any other view controller that does need the updated information should then observe the data model using KVO, or watch for notifications that are issues when the model changes.


That would decouple your view-a subhierarchy from your view-b subhiearchy, and that would likely make the code easier to write.

Please accept my apology for my slow response to your detailed post. I have been away for a few days. I returned yesterday.


Today, I have done a lot of work on this and I now I think I understand what my problem is: Because there is no segue between my source VC and its detination VC, I cannot notify the source VC who its delegate is as would be possible using prepare-for-segue(). Because of this, there is no connection and thus, no data can possibly be sent.


I will have to create my "segue" programmatically and that is what I am now working on.


It is late where I am at, so will probably return to this issue on Monday.

I resolved all of my data passing issues using a class structure. The app works perfectly and I have learned a ton of useful information in the process.


Thanks to all who have tried to help me with this issue.

So don't forget your duty: close the thread by marking Quincey answer as correct.

Got it! Thanks.

Are custom protocol methods supposed to work in ANY view controller?
 
 
Q