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

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.

Related

MVC: Is a custom UITableViewCell a view or controller or both?

I used to consider a CustomUITableViewCell.xib as the view and the corresponding CustomUITableViewCell.swift class as the controller of a table view cell.
Is this correct? A youtube video I stumbled upon considers the class as the view: https://youtu.be/n06RE9A_8Ks?t=177
Edit:
To clarify the question: Which one of the following is the view and controller? Are both considered the view?
CustomUITableViewCell.xib
CustomUITableViewCell.swift
I'd absolutely consider it a "view" (in terms of MVC). It's of the group of logic that (along with the .xib) handles 1 particular view of information, rather than orchestrating some aspect of the general logic of the app.
I also consider a UIViewController as belonging to the "view" part of MVC for the same reason. Of course, if you put far more business logic into your view controllers than that which is necessary to support the single view, then your view controller is some mix of MVC. For example, if your view controller chooses what scene of the app comes next, your view controller then participates in controller logic and it's not really following MVC. Your view controller is forced to do a lot of single view-related work, though, because there's a single view it's responsible for and that the view-work is more practically done in the UIViewController rather than the UIView.
So when you ask about a cell view class's stance in MVC, if it's doing single view work, then it's a "View". If you mix in controller work or model work, then you've muddied up the separation of responsibilities that MVC espouses.
In my personal opinion it is a view. It should be handling only UI components in the class. Think of both files as a complete view. One cannot be without the other. Thus I consider them one.

How to share controller amongst different iOS views

I am coming from a C# wpf background where you can have one ViewModel handling multiple Views. This is a great way to share data amongst unrelated views. However I can't figure out how to do the same thing in iOS, as you seem to need a Controller for each View.
What I am trying to achieve is to have a sign up sequence where the user populates 5 screens of data one by one. I was going to use a PageViewController for this and each click on Next would transfer them to the next page in the sequence. All the while, adding all their input data to a parent model object which stayed around for all five screens, at the end you can submit the whole lot to the database to sign up.
The only way I can see so far to do this is to create five separate ViewControllers, one for each screen of the sign up, and create the navigation logic to display them as you click through. However this a) seems overkill and b) means each subsequent screen and viewcontroller doesn't know about the information the user entered in the previous steps.
What is the correct way to do this in iOS?
You can do it in many ways. If you like to use UIPageViewController, you can actually have one view controller for all steps of the sign up process.
A main view controller would implement protocol UIPageViewControllerDataSource. It has two required methods, which return an instance of a content view controller. These instances can be of any UIViewController subclass, so you could have five separate view controller classes or you could have five instances of the same class.
Xcode has a project template "Page-Based Application". It might be a good sample code for you. There is one class DataViewController and it is instantiated for each page. If your case is really simple then this might be the best solution.
If you use multiple view controllers, you can pass data between them by overriding the method prepareForSegue(segue:sender:). The UIStoryboardSegue object has access to the destination view controller, you can cast it and set up the properties. (I am assuming you are using storyboards and segues.)
Another approach would be not to use UIPageViewController and implement the whole process within one view controller. There could be one view with five container subviews. Initially the first one would be shown, then the second one, and so on. This requires manual implementation of navigation between those steps, but gives a lot of flexibility. It's also more aligned with MVVM, because there is one-to-one mapping between a ViewModel and ViewController.
In general, iOS apps have lots of view controllers. It doesn't seem an overkill for me to use five in your case. It might be more code, but it's less complexity.

What should be in View Controllers and what should be in Views?

I am at the beginning of developing an iOS app I am having trouble understanding the MVC (Model-View-Controller) design pattern. I thought I had it down but the more I read the more confused I get. I don't know if this should be an iOS specific question or if the same goes for every use of MVC. I am not using storyboards btw, I want to do it all programmatically.
I believe I understand the basic relationship between Controllers and Models, it's the separation of Views and Controllers that I don't get. Let's say I want to create a UIButton and display it on the screen. Should I initiate the button in the Controller or the View? The controller is responsible for what should be displayed, correct? Wouldn't you just call on a View to display that and not worry about creating the button in the Controller? From what I understand, View Controllers are just Controllers and should therefore control the View, not be the View. It seems like most people do just about everything in the View Controllers. I guess my question boils down to what code goes where?
UIViewController is controller part in the MVC pattern of code.
M(Model)
C(ontroller)
V(View)
Controllers handle navigation between different views , etc.
From here you can get more idea : view and viewcontroller
A view is an object that is drawn to the screen. It may also contain other views (subviews) that are inside it and move with it. Views can get touch events and change their visual state in response. Views are dumb, and do not know about the structure of your application, and are simply told to display themselves in some state.
A view controller is not drawable to the screen directly, it manages a group of view objects. View controllers usually have a single view with many subviews. The view controller manages the state of these views. A view controller is smart, and has knowledge of your application's inner workings. It tells the dumb view objects what to do and how to show themselves.
A view controller is the glue between you overall application and the screen. It controls the views that it owns according to the logic of your application
About View Controllers
View controllers are a vital link between an app’s data and its visual appearance. Whenever an iOS app displays a user interface, the displayed content is managed by a view controller or a group of view controllers coordinating with each other. Therefore, view controllers provide the skeletal framework on which you build your apps.
iOS provides many built-in view controller classes to support standard user interface pieces, such as navigation and tab bars. As part of developing an app, you also implement one or more custom controllers to display the content specific to your app.
Not sure about any iOS specifics but from a PHP standpoint controllers are there to get any data that is needed for the view (via models) and then pass that data to the view.
The view is there to render things to the screen only and should have no logic in it.
So from a website point of view if you wanted to display a users name on the screen:
The controller would request the username from the model
The model would get the username and return it to the controller
The controller would then pass the username to the view
And the view would then render the username.
Hope that helps.
To be not specific, but on a upper layer, you can say as following :
You can put controller code in class extending UIViewControllers
You can put view code in class extending UIView
You can put model code in class extending NSObject

transitionFromView:toView:duration:options:completion: confusion

I am trying to utilize transitionFromView:toView:duration:options:completion: but in uiview class reference this point is confusing me. What it means?
This method modifies the views in their view hierarchy only. It does
not modify your application’s view controllers in any way. For
example, if you use this method to change the root view displayed by a
view controller, it is your responsibility to update the view
controller appropriately to handle the change.
Please view the sample project https://anonfiles.com/file/521cbb41b086eae987fe27eb98278aba
In this project I just called transitionFromView:toView:duration:options:completion: and everything is working fine and did nothing what is mentioned in the above point.
You are more likely asking for an explanation of Apple's documentation than a specific question, if I understand your posting correctly.
Nevertheless I'll give you this explanation and I hope, it will help you:
You write:
Everything is working fine..
and that is, because you a doing well here!
According to the MVC design pattern (Model-View-Controller), you are using the classes UIViewController (the "C") and UIView (the "V") in your code.
A view contains the visual representation of objects (like labels, buttons, subviews, ...) without an logic for their behavior.
A viewcontroller provides the logic, e. g. IBAction methods and any other methods that you may implement.
Each UIViewController has its own "view" property containing the view, whose behavior the controller does manage. This view normally contains additional views, e. g. labels, images and buttons. They are subviews and are stored in the view's "subviews" array property. Btw, each view has such a subviews property - that is, how we can implement complex view hierarchies.
In your situation (multiple subviews that are managed by one common viewcontroller), the method
transitionFromView:toView:duration:options:completion:
hides "fromView" and unhides "toView" with the support of animations. It is a transition between to views. The paragraph from the documentation shall prepare you as a developer, that this method only manages the change of the visual representation and does not provide additional "services" for your view controller for the further management for the participating views.
That means, that you have to manage e. g. the state of the views (which view actually provides interaction for the user) by your own code. It seems to me, that you have managed this well!
In a wider scope, iOS supports UIViewController container as well - they can contain child view controllers (which again contain their view with its subviews). In such an architecture, there is another transition method from the SDK,
transitionFromViewController:toViewController:duration:options:animations:completion:
which allows you to implement transitions not between two views, but between two view controllers.
I hope this is not too much text and helps to make things clearer for you.

iOS MVC architecture - separate view other than the view of view controller

Overview
I am doing an iOS project using the MVC architecture. Pardon my ignorance, I am just confused, I am looking for a good design.
The view I am planning to use will have some buttons on it and some labels and text fields. My view wouldn't need any custom
implementation of drawRect.
All my logic as to what needs to be done when a button is pressed or event occurs is in my view controller
I have a couple of doubts:
for the above scenario, is it still better (good practice) to create a separate view (a view other than view controller's view) ? If so why ?
Other than drawing and displaying the view (in my project, I don't have much of it) what else should a view's implementation code
contain ?
I would like to disable a set of buttons when the user touches on a textfield and the keyboard comes up.
a) So should I place this logic of disabling some buttons in the separate view's implementation (view created in question 1) ?
b) From my parent view (view created in question 1), can I create outlets to the buttons (which are subviews) to disable some of the buttons ? I am not able to do this. Or should I use the method subviews and loop through the button that i am looking for ?
My understanding
Model contains the data
View is responsible for displaying and shouldn't contain business
logic.
View controller is the only one to interact between the model and the view and contains the business logic
There's no need to create a separate view -- the view controller's view (usually just a plain UIView) can certainly contain your buttons and text fields. If you did want to put some of those in a separate container (perhaps so that you could move them as a group), you could use a plain old UIView for that.
Views are responders, so UIView subclasses can override the touch handling methods if you want to do any special touch handling.
a) It's common to put the code that manages views (such as disabling buttons) in the view controller. b) Again, you'd normally put the outlets for your buttons in the view controller.
When people talk about "business logic" they usually mean the logic that's required to maintain and operate on the data that the application deals with. That sort of thing is often best placed in the model. On the other hand, code that manages views, such as enabling or disabling buttons or moving data from the model into views (or vice versa) belongs in the view controller.
Q1. for the above scenario, is it still better (good practice) to create a separate view (a view other than view controller's view) ? If so why ?
If you create your view by Interface Builder, that's a separate view I think. ;) But if you try to create a view hierarchy programmatically without using a n/xib, you can put all your view layouts in loadView method, and populate the data in viewDidLoad, that's what the View-Controller does. And also, you can create a UIView class to implement the layout of the view, just like n/xib, but programmatically.
As the DOC said,
... One can merge the MVC roles played by an object, making an object, for example, fulfill both the controller and view roles—in which case, it would be called a view controller. ...
... A view controller is a controller that concerns itself mostly with the view layer. It “owns” the interface (the views); its primary responsibilities are to manage the interface and communicate with the model. Action methods concerned with data displayed in a view are typically implemented in a view controller. An NSWindowController object (also part of the document architecture) is an example of a view controller. ...
The MVC in Cocoa is a litte different as what you known. You can refer the official doc HERE.
Q2. Other than drawing and displaying the view (in my project, I don't have much of it) what else should a view's implementation code contain ?
You can customize your view, e.g., set text color or font style for your button, etc.
Q3.a. So should I place this logic of disabling some buttons in the separate view's implementation (view created in question 1)
It is better to put logic in controller (or view-controller), just as MVC prefer.
Q3.b. From my parent view (view created in question 1), can I create outlets to the buttons (which are subviews) to disable some of the buttons ? I am not able to do this. Or should I use the method subviews and loop through the button that i am looking for ?
You can set tag (setTag:) for your buttons and get the right one you want. But keep in mind, firstly you need to let the button shown to parent.

Resources