Keeping an updated model class and accessing it from multiple view controllers in Swift? - ios

I am making an app with swift and xcode. In it I have a model class with user's information in it. I want to display some of that information with one view controller, update/change that information in another, and keep all of the views up-to-date with whatever is in the model class.
I was told using a singleton could work but is not recommended. Is there a better, more accepted way of accessing the model class from multiple view controllers without a segue between them (I am using a tabBarViewController)?

If you want to go "pure" that is follow Apple Best practices where a View Controller is never hard-coded to a global model (more of a pain than is worth, practically, in my opinion):
Subclass UITabBarController to contain the model instance as a stored property (perhaps private(set) is the best access level here, but however you want to expose it safely to other classes -- PUBLICLY EXPOSED AS A PROTOCOL TYPE ONLY OF COURSE.)
Don't forget to set the identity class of your Storyboard Tab VC to this new subclass otherwise your sexy code will not run.
In your (hopefully base class to all child tab VCs) View Controller class, hook into didMoveToParentViewController(parent: UIViewController). Gently downcast (as?) to the UITabBar subclass above, and extract the model, and copy the reference into your local stored property. It will happen exactly at the right time, just as you land into the soft arms of your parent VC.
Happiness!

You can try KVO mechanism. By which if you change a model variable's value that will reflect in another controller. For your reference
https://www.appcoda.com/understanding-key-value-observing-coding/

Related

Can you make a Swift Protocol that forces the view controller to fire specific custom NSNotifications?

This is a design pattern question.
I have a 'framework' I'm building, and depending on the current displayed ViewController the framework needs to inject a UIButton into that ViewControllers view.
I don't want the ViewControllers to 'know' explicitly about the 'framework', so I was initially using the delegate pattern but that required a 'over-seer' to ensure that when only specific view controllers were loaded, that they knew about the 'framework'.
However, it occurred to me if I could, via a protocol, ensure that all delete ViewControllers fired off the same two custom NSNotifications i.e. subscribeToRequestButton and unsubscribeForButton, then the 'framework' would listen out for those, and upon receiving them, have the view controller object passed to it (via the Notification) so that it can inject the button.
Thereby preventing the view controller from knowing about or having a reference to the 'framework'; it just knows, if it want's that button, to fire those two notifications, and ensure that it implements a method for when that button is touched.
Is this possible or is there a better approach?
The key problems are that
a) I cannot have the View Controllers that need the button know about the framework; as they never have the opportunity to have a reference to is passed to them by some manager class, and
b) The framework doesn't know about the view controllers existence until it receives a notification that is needs to inject a button into something.
EDIT:
I'll just use a singleton pattern with a few public accessor methods for passing data in or querying.

Who should create the ViewModel in iOS MVVM?

I am trying to develop a simple app to understand MVVM but I don't get it really well. I've read some articles, but they are a bit different:
View in different class MVVM
In this example the view is not the ViewController itself, it is a class that contains all the details of the view and it is an abstraction for the VC.
The ViewController creates the ViewModel with some data the it retrieve from DB, Network..
The ViewController talks with the model and manage the ViewModel to update the view.
ViewController is the view MVVM
In this example, the viewController is the view, it does not need other class. The viewModel is not created by the viewController, and the ViewModel of the next ViewController is created by a ViewModel. The ViewModel also has an instances of the Model, so if it needs to retrieve some data, it has instances of the DB, Network..
I don't understand well some things. If the viewModel is retrieving data from Network with asynchronous tasks and I want to display an spinner and get data for fulfil the view. Should I user blocks, KVO or delegates? If I use delegates, the view implements ViewModelDelegate Methods, would be that correct? Am I coupling view with viewModel? I am confused at this point.
If I have a firstViewModel that creates a new secondViewModel for a new pushed SecondViewController,and FirstViewController has to update its view before the user pops the pushed SecondViewController. In this case firstViewModel has to observe secondViewModel and notify the changes to firstViewController once popped, doesn't it?
I also have a question about ViewController creation. ViewControllers are the attendants of next ViewControllers creation? If I create an object that manages ViewControllers creation and navigation should I pass this object over viewModels?
I know they are very similar, but I am confused about which way I should implement and how. There isn't much information and examples about iOS MVVM.
I am not using Reactive Cocoa yet because I want to understand this pattern well first. Though it is in my TO-DO list.
Thank you!
It really depends on why you're using MVVM. I'm doing it right in the middle of the two cases you mention, actually. Here's the two reasons for MVVM usage:
First, you may be using MVVM because you want to organize your code in a way that pulls the logic out of the VC and keeps it clean. In this case, you're using a ViewModel in good OOP form and it's perfectly find to have the VC create it.
On the other hand, you may be intending on UI testing your VC's and therefore want to introduce mock ViewModels. In this case, you want to be handing the ViewModel to the VC. (i.e. dependency injection)
In my view, either is justifiable. You might even have multiple needs in one app. Therefore, I keep things flexible. My approach is to create the VM in the viewDidLoad() method of the VC only if it doesn't exist yet. This allows me to use my normal VM and to do create it (neatly) in my VC, but if I ever need to override it (unit testing, UI testing, alternate view style), I can, too.
The issue comes from the fact Cocoa apps, are by definition using MVC, and you have to try and make MVVM work with the underlying ViewController structure.
I haven't looked at MVVM in iOS, but have done a bit using Xamarin.Forms, where the View is just the XAML code, the view model interacts with the View and the Model. Under Cocoa apps, it doesn't really matter too much how you do the ViewModel part, but looking at your links, I think the second approach is closer to a purer MVVM approach.
I suggest you download the code in the link and have a look to get a greater understanding?

I would like a custom, resuable subview that can know about the model and lifecycle events

I come from an ASP.NET background so I'm not sure if there is a way to do this in iOS. Essentially, we have a design paradigm in our app where you can either have a single item in your model or multiple items. Depending on which one, different subviews are hidden/shown.
I have already created a custom subview that inherits from UIView which handles this with the help of a delegate to get some information from the ViewController. I have implemented it on multiple screens which works fine. However, the separate view controllers are duplicating a ton of code such as when to update the model, what to do when the model is updated, etc. Essentially, stuff that the view controller should do. It would be great to keep this code in one place as opposed to the different ViewControllers.
I know I can have my custom subview's class inherit from a UIViewController, but I also need the ability to have additional views above or below the reusable one. What are my options for this? In ASP.NET you can just create a user control which knows about the page lifecycle and can know about the model.
"I know I can have my custom subview's class inherit from a UIViewController" -- no, you can't do this. A view can't inherit from UIViewController, and in Apple's MVC paradigm, a view shouldn't know anything about the model. Without knowing more about what you're doing, I would say one thing you can do is to make a base view controller class that your other controllers inherit from to cut down on the amount of duplicated code. Since the controller mediates between the model and the view, you should have the controller tell the view which of its subviews to show or hide, based on the model.

How can viewControllerWithRestorationIdentifierPath:coder: find an existing instance?

The docs on viewControllerWithRestorationIdentifierPath:coder: say:
Your implementation of this method should create (or find) the
corresponding view controller object and return it... It is not always
necessary to create a new view controller object in your
implementation of this method. You can also return an existing view
controller object that was created by another means. For example, if
the view controller had already been loaded from a storyboard file,
you would return that object rather than create a new one. [My italics.]
This has always seemed like complete nonsense to me. This is a class method! We don't have any access to any instances at this moment — unless we create one. I'd be grateful if someone can explain to me how on earth a class method can find or know about "the view controller that has already been loaded from a storyboard file".
EDIT: To earn the bounty you must show me an actual case, from your own app, of the class method viewControllerWithRestorationIdentifierPath:coder: being used to "return an existing view controller object that was created by another means."
The most common example of this I can think of is any of the view controllers that are owned by the App Delegate. This is traditionally a tab bar controller or a navigation controller in traditional apps, but sometimes it can be something completely custom, which is when this functionality might be useful.
Since the UIApplication is pretty much a singleton and has one delegate, it means your App Delegate has global state, which makes it accessible from anywhere, including in class methods with: [[UIApplication sharedApplication] delegate].
Of course, any singleton is accessible from anywhere and a common pattern (but one I personally dislike) is to have a NavigationManager singleton which manages any global view controller transitions, so in this case you'd be able to access the existing instances as well.

The Proper Way to Store and Access Objects in Memory on the iPhone

I'm new to programming in iOS and I'm trying to figure out what the widely accepted "proper" way to store objects in memory is?
In my program I have a couple view controllers in a navigation controller and then on the lowermost view I have a modal view controller.
I have a class of object that I archive in a file and unarchive when I need to change the objects member variables. I need to be able to access and change these objects that I have archived from all of my view controllers.
Is the proper way to do this by unarchiving and then archiving the data in each view controller or is there a better way?
Multiple view controllers (that is classes deriving from UIViewController) is really frowned upon. A view controller should control the screen (or in rare cases such as the iPad split view, there can be two). If you need multiple classes to manage different subviews, thats fine, just don't inherit from UIViewController.
Depending on your application, you can keep your data in:
A singleton
In the application delegate (somewhat frowned upon)
As an object passed amongst the view controllers in your navigation hierarchy (makes sense in a document or file based application)

Resources