How to migrate data between views using Tab Bar Controller (Swift)

Asked

Viewed 191 times

0

I have a Tab Bar Controller with three buttons. How do I take an array, loaded from data stored in Core Data, from a view (button 1) to another view (button 2)?

2 answers

0

Okay, there are some ways to do this.

I think the best one is that you create a class that will be shared across all of your app views. This class can store data structures and methods that are general to the app and for which there is a big chance you need to call in various places.

In order to share an instance it is necessary to create a "static" property (it is a variable associated with the class) that can be called from anywhere.

I have a habit of calling this shared class Appmodel, or Businessmodel, or Gamemodel, because I usually use it to store all the data relating to the app model, regardless of views and viewControllers.

For example:

class AppModel {
    static let sharedInstance = AppModel()
    var sharedArray: [String]?
}

Create this class in your own file, for example Appmodel.Swift.

In this class we create the shared variable sharedInstance. Anywhere in the app you can call Appmode.sharedInstance you will receive the same instance.

In this way, in the tab 1 you can edit sharedArray as follows:

AppModel.sharedInstance.sharedArray = ["1", "2", "3"]

And in tab 2 you can access the data using

AppModel.sharedInstance.sharedArray

Another way (which I don’t prefer) is for you to navigate through Tabcontroller to access the data. I find this approach bad because it breaks if you make any change in the structure of the app, but for the sake of completeness I describe below.

Suppose you have a tabBar controller with two tabs, each tab containing a custom viewController called for example Custom1viewcontroller and Custom2viewcontroller, each containing a property called "array" and you want to copy this array from tab 1 to tab 2.

if let viewControllers = tabBarController?.viewControllers {
    if let c1vc = viewControllers[0] as? Custom1ViewController, let c2vc = viewControllers[1] as? Custom2ViewController {
        c2vc.array = c1vc.array    
}

The problem is that if for example you put a Uinavigationcontroller as root from a tab, you need to navigate to the first view controller from that navigation controller to access your Custom1viewcontroller. For example:

if let viewControllers = tabBarController?.viewControllers {
        if let nvc = viewControllers[0] as? UINavigationController, let c1vc = nvc.viewControllers.first {    
}

and it gets worse if you need to access data even more internal to the class hierarchy.

Bottom line: Use a shared class! :-)

  • I chose to use the Appmodel class, however I am having fatal error: unexpectedly found nil while unwrapping an Optional value.

  • How do I boot ?

  • Hi Adriano. Since I declared sharedArray optional, you always need to use or ? notation (for example: Appmodel.sharedInstance.sharedArray?[0]) or use if Let (if Let array = Appmodel.sharedInstance.sharedArray {} ). Of course, you will only be able to use this array after you have assigned some value to it in the first tab. Otherwise, you can change the statement to var sharedArray = String in the Appmodel class.

0

I suggest that:

  1. This data is persistently saved somewhere where both environments have access (e.g.: Coredata, Sqlite, Realm, Userdefaults, Property Lists, etc)
  2. That you use Key-Value Observing to do so (is an intelligent way to indirectly observe the changes of one object and inform the other). More about KVO: http://nshipster.com/key-value-observing/
  3. Use the Notificationcenter to report these changes (works like KVO). More about Notification Center: http://nshipster.com/nsnotification-and-nsnotificationcenter/

Any of these ways you preserve the encapsulation of your code, which will make it clean.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.