How to update a variables/UI in a view that was initialized from a separate file?

Lets say I have 3 Files/Classes:


File A (Main View):

File B (functions to Initialize Additional Views):

File C (functions that update the data/labels in the views called from File B into File A):


File A is the main view. I use a generic function from File B called "initHeader()" that initializes a "header view" and adds it to the view in File A. The reason the view is initialized from File B is because there is File A 1 to 50. I didnt want to copy paste the code to initialize the the new view in every version of File A.


After the header is initialized, I will want to update some data in this view. How can I update the data in this view if


1) there is no variable assigned to the new view in File A initialized from File B. I realize I could loop through all subviews in File A to see if a view matches the type of view initialized fomr File B, but I want to update it without having a pointer pointing to the new "header view" variable. Which brings me to

2) What if I want to update the File B view that was added to File A through File C.


In this case:

->File A calls a function from File B to initialize the "header view"

->I want the newly added "header view" to be update with different data (this method will be called from File C so I don't need to have the same function a million times in all the different sub File A files.


If I were to do it all in just one file/class. I could easily do it:

->var headerView = HeaderView()

->headerView.updateAllVariables(fromDataObject: dataObject)


BUT if I wanted to initialize the header view from approximately 50 different classes, I would need to copy and paste the same code to each class. Then if I want to change something it becomes a HUGE headache.


How can I call all those from different files so I literally just write:

->loadHeaderView (from File B)

->updateHeaderView(fromData: dataObject) (from File C)


Hope that makes sense! Do I make the functions in file B return the view after being initialized? Which would make it look something like:


File A:
var headerView = initializeHeaderView() <- From File B

updateView(headerView: headerView, fromData: dataObject) <- From File C

Accepted Reply

Do you have 50 different classes or 50 instances of object of the same class ?


If they are 50 instances of the same class, (that is what I understand) you will have the code once.


However, if they are of different class, you have to replicate in each class… unless you decide to create an intemediate subclass where you implement the function and have all 50 classes inherent from this intermediate class.


Here is the structure


class ViewForDelegation : UIView {

// In a didLoad method


     NotificationCenter.default.addObserver(self, selector: #selector(notification1Action), name:NSNotification.Name(rawValue: notification1Name), object: nil) // object is nil: we don't test you sent the notification ; but we could give an object reference if we wanted to test

     func notification1Action()  {
          propertyInA = //
          // Can be a textField content as well
          textFieldInA.text = "I updated"
     }
}

// Then the 50 classes
class ViewNumber1 : ViewForDelegation {

}

Replies

It is a bit difficult to understand all the explanation, but I hope I catched the essence.


First point: you should not think in term of files but in term of objects. The question is not if a var is declared in a file but if it is declared in a class.


So the question is how to communicate between classes, without creating references of all var in all objects.

I'll handle the case where you want to modify a property (var) propertyInA in class A from a call in class B


You have several mechanisms.

You have several ways to achieve this:

- send notification

- use delegation

- directly set the property : vc1.property = ...., called from vc2 // not very clean design


1. You can use notifications:

you declare, outside classes, the name of notification

let notification1Name = "notification1"       // select an appropritae name for the constant to ease further reading, better than notification1 and notification1Name


- In class A (in the viewDidload for instance), you subscribe to a notification by creating an observer:

       NotificationCenter.default.addObserver(self, selector: #selector(notification1Action), name:NSNotification.Name(rawValue: notification1Name), object: nil) // object is nil: we don't test you sent the notification ; but we could give an object reference if we wanted to test


- in class A, you define the func that will update the var ou outlets you want to modify

func notification1Action()  {
     propertyInA = //
     // Can be a textField content as well
     textFieldInA.text = "I updated"
}

- in class B, you post the notification when you want to update properties of class A

        let nc = NotificationCenter.default
        nc.post(name: Notification.Name(rawValue: notification1Name), object: self)


2. You can use delegation where class B will delegate to class A the update

So if I have 50 classes/views that use the same "textField" class. I will need to have the function "notification1Action()" in all 50 classes? I understand the usage of notifications/delegate (and prefer delegates), but I was trying to avoid repeating the same function in every view.

Do you have 50 different classes or 50 instances of object of the same class ?


If they are 50 instances of the same class, (that is what I understand) you will have the code once.


However, if they are of different class, you have to replicate in each class… unless you decide to create an intemediate subclass where you implement the function and have all 50 classes inherent from this intermediate class.


Here is the structure


class ViewForDelegation : UIView {

// In a didLoad method


     NotificationCenter.default.addObserver(self, selector: #selector(notification1Action), name:NSNotification.Name(rawValue: notification1Name), object: nil) // object is nil: we don't test you sent the notification ; but we could give an object reference if we wanted to test

     func notification1Action()  {
          propertyInA = //
          // Can be a textField content as well
          textFieldInA.text = "I updated"
     }
}

// Then the 50 classes
class ViewNumber1 : ViewForDelegation {

}

Yes they are different classes. For example, HomeMenu/Chat Room/Game Start/Game/Game Finished/Game Leaderboards... all of these will need to load a "Game Header" view that will display username & gold amount (as an example) and will need to be updated with the correct gold amount (if it changes).