I'm working on figuring out mvvmcross and if I can use it for an iPhone (and eventually iPad and Android) app I'm going to develop. The MVVM pattern is really powerful and works great for me, but I have several views where I need to add a navigation control that will allow the user to jump to several different other views and I'm wondering what's the best way to do it.
Right now, I've created a NavigationControlViewModel which exposes a collection of NavigationLinkViewModel which have a link text property and a command that will show the appropriate view. But to add this to a view for, say, MyViewModel is a little tricky. Right now what I've done is add the NavigationControlViewModel to MyViewModel so that I can bind it in MyView:
private NavigationControlViewModel _nav;
public NavigationControlViewModel Navigation {
get {
_nav = _nav ?? new NavigationControlViewModel (Mvx.Resolve<INavigationService> ());
return _nav;
}
}
This works, but doesn't seem as nicely contained as I'd like to be. I still need to add controls to MyView for the NavigationControlViewModel and then add it to every other view that needs it (as well as adding it to their view models).
What would be the best practice for handling this sort of thing in iOS and MVVM?
I've seen the video on using a split view, but I'm not sure if that's the best approach. I need a vertical split and I only need it on some views, not every view.
For sharing the navigation mechanism between view models, I guess you can use either aggregation as you have done NavigationControlViewModel or you can use inheritance with all the navigation items in a BaseViewModel class.
I personally would happily use either of those but would make sure to expose all my Navigation options as ICommands - simply because that's the way .Net-style data-binding generally expects 'action hooks' to be presented. Note that there is a reflection way of generating ICommand's - see http://slodge.blogspot.co.uk/2013/03/fixing-mvvm-commands-making-hot-tuna.html
For actually presenting the ViewModel via a View on the screen... I'd encourage you to believe that you can do whatever you and your UX/design team want to.
Some of the standard presentation approaches are available via: UINavgiationController, UISplitViewController, UITabBarViewController, UIPopupView and PresentModalViewController - and you are free to use these and to combine them together - e.g. you can have a navigation controller which two layers deep shows a modal view which contains a split view with two children...
Beyond the standard approaches, there are plenty of other UI design paradigms that people have selected:
flyout and flyunder views - like the hamburger menu
the Twitter iPad stacked view approach - like https://github.com/steipete/PSStackedView
heads up display views (dialogs)
continuous scrolled views
... plenty more - see http://pttrns.com/categories/13-navigations
By default, MvvmCross provides you with a 'whole page' presenter which presents every View-ViewModel pair the same way inside a UINavigationController. As you've seen in the N+1 video you mention, you can easily override that behaviour and you can then choose to present View-ViewModel pairs in any way you like - e.g. you can choose to present some whole page, some using a fly out, and then some using tabs.
Because an IMvxTouchView presenter is just C# code, and because we devs love writing C# code, we can implement whatever wonderful logic we want to within a presenter including code that tests what is currently being shown in order to determine where to show the next page.
I can't comment on what 'best practice' is for making a design look nice.
But I do believe that if you stick with showing your view models via ShowViewModel then that will allow you the most flexibility in what presentation strategy to use on each platform.
Some more on presenters is available via http://slodge.blogspot.co.uk/2013/06/presenter-roundup.html
Related
I'm trying to understand how to properly implement MVC in swift. Heres my scenario:
I have a signup page with 9 UITextFields, and they're all being made programmatically, and therefore being anchored to the view programmatically. As you can imagine this would be a lot of repetitive code to have in the SignupViewController class file.
Is the convention when following MVC to keep the setup of these text fields in the SignupViewController file, or are you supposed to have a separate file such as SignupView that contains all the text field setup code?
Even though UIViewController has the word "controller" in it, I believe the majority of iOS devs these days assign the UIViewController to the "View" side of MVC. The UIViewController is chiefly specific to a particular view only, plus may manage its subviews as well (until this gets too messy and a container view is added to allow for a nested UIViewController).
In MVC on iOS, the view controller can easily become polluted with business logic, model management, etc... which is why many people jokingly refer to "MVC" in iOS as "Massive View Controller". To combat this, consider using an MVVM architecture instead, which not only keeps the VCs small, but also moves the business logic out to a separate "sidecar" coupled to that ViewController, called a ViewModel. This allows the business logic to be unit tested without any UI involved, making testing much more reliable and easier to read and maintain. With that said, the creation of these 9 controls would still belong in the ViewController.
As for programmatically adding UITextFields to your view vs viewController, if this is to be done just for this single scene, then I'd stick it into the viewController. If you expect to want to reuse the set of them in other scenes, then making a custom view or control containing them would be better, like is typically done for custom cells of a table.
Finally, consider simply using a Nib or Storyboard to layout your scene. Apple has provided so much power to layout and maintain scenes via nibs and storyboards that you're really missing out to go the programmatic route. I find it very rare that I side with programmatic approach. The auto-layout warnings in InterfaceBuilder alone are worth gold to me, and as Apple continues to raise the bar and change layout rules, I can't imagine trying to keep up programmatically when I can't afford to test every device and iOS version combination. And yes, it's possible to do MVVM with dependency injection and storyboards. I do it daily.
Answer to your question is that it has nothing to do with MVC .
AS iOS/Mac developers, we use Interface builder and auto_layout to achieve most UI #IBOUtlet/ #IBAction. This is the V side of MVC.
Typically, If you have data, database, json or whatever formats, you need to model them and handle logics. That'M of MVC.
The C(Controller) side of MVC is a kind of glue between M and V. In most cases of mobile , you can think Controllers are all C you need.
So controller class is the only portion you need to put code to simplify everything.
In your case, 9 UITextfields should be ideally put into V side job. Please don't write code for them unless there is no better way to do.
I don't agree with above statement about using Interface Builder... I prefer to write most of my views in code and also set the anchors that way as well.
to minimize the file you can create an extension of the ViewController in a separate file to contain all of this code.
so for SignupViewController you would create a new file called SignupViewController+SetupUI.swift.
import UIKit
extension SignupViewController {
// add your setup methods here
// as just an FYI you can call the methods you create from your
// SignupViewController file just like you would any other method.
}
you can read more about extensions here.
After reading about good practices to write maintainable and readable code you should do the whole design in interface builder. If you get good understanding of constraints you don't need to write any code to setup design in your view controller. The ViewController.swift file should not be used to fetch-handle data or to setup the UI. It should just be responsible to display and update values which are fetched and get handled in a separate ViewControllerDatasource.swift file. So to sum up, view controller does not have any logic implemented it just handles the show data and the design updates(not setup). I hope i helped you with your question.
I have a quick question in regards to my app that I am developing for school. In my app we have 5 unique games that the user can play. However, each game has 2 modes, normal and hard. What is the best way about going to do this. Currently I have my first game as two separate view controllers and are called based on the difficulty that is wanted(one called normal_cstars and hard_cstars). I am wondering if this is efficient because each view controller has a .h, .m, and a .xib. Is it possible to have a view controller that has two separate views and how would you go about accomplishing this.
Thanks,
Ryan Wong
Of course. You can pick which one of the two views you display inside your viewcontrollers. Just send self.view in the view controller to be the view you'd like to use.
One way to architect this is to have two separate view classes that share the same controls. The controls are all handled by the view controller while the views each draw their own layout.
And don't be worried about sharing subviews among the two main views -- or you can keep your two view controllers, and just have shared classes that make up the views and controls of each view controller's presentation. Just because you have two view controllers doesn't mean you have to have redundancy code. Split things out into separate classes, from your animated views to your controls.
There are a lot of other possibilities. Look at some of Apple's samples to see how multiple view controllers are used.
Do you really think that you need two separate views? (I am not sure about your game though)
Since game modes are Model specific, a model with behaviour "Normal" or "Hard" will actually render the game in a view.
If near future, if you want to implement a mode "Easy" then you end up with another view controller and might encounter code redundancy.
Solution I would think:
Create a inheritance over composition pattern for your model objects.
A view controller will be much more generic and tells view to render based on the mode
Now the base class of the model will implement generic methods and since the model has mode as composition, the view will render the game objects based on it.
Advantages? - well we have not violated the Open-Closed Principle.
And again there are various design patterns out there to achieve this. Its up to you to decide which suits the best for the requirements.
I went through lot of similar questions but still have not clearly understood this.
In terms of better design - what is right way - creating all the UIButtons, UILabels etc in the view controller itself and then add them as subviews, or should I create a custom view (#interface MyView : UIView) with all the required buttons/labels etc and then assign that view to the view property of View controller? I am not using interface builder.
Is there any real need/advantage of creating a custom view like this or adding everything in view controller itself should be okay/good idea? Sorry I am very new to iOS app development :-)
If someone could explain it to me - would be really helpful.
Some advantages of subclassing a view are:
Code separation. If you have a complex view and want to keep your viewcontroller clean, subclass and separate it out.
Reuse. If you reuse the view anywhere else it is possible with minimal effort when the view is it's own class.
You can choose what setup and methods to expose for setup
Some disadvantages of subclassing a view are:
View no longer will have access to view controller ivars.
View controller will no longer have direct manipulation on the view
You are constrained to what the view publicly exposes in terms of setup and config (may be a good thing).
Overall, there is no single best answer, it all depends on your setup and how you like to keep your project organized.
My non-answer : the answer lies in between these 2 opposite sides :
putting verything in the view Controller, using just basic views
using very elaborate views that abstract away some tedious graphic work.
To get an idea of what I'm talking about : one might implement a UITableView behaviour directly into a UIViewController with just a UIScrollView, and handle all the indexPath computation (depending on the amount of scrolling), views recycling, etc... in this very viewController.
But, as lists are a common way to visually display information, all this 'recycling view', 'setting content for currently displayed cells' has been moved into a custom view class : UITableView, and delegate and datasource patterns have been use to make this class behavior easily customizable.
Creating abstractions has its advantages and disadvantages.
I try to do things incrementally :
hold the most you can in viewController
when code becomes too complex, or if you see yourself needind the same kind of 'component' elsewhere : the create a custom view, and try to define its API (what properties it exposes, what implementation it hides)
View controllers are a nice way of separating the things that a view must do in the strict sense (handle input, render output) from the larger hierarchy, manipulation, and information routing of views around it, which the view controller coordinates.
Striking the right balance depends on a number of localized factors. A view which contains a label and an image (like a cell) could certainly "own" its subviews and appear to the controller like one container unit. But note in this case that the subviews are also supporting the input/rendering of the "cell" unit.
In that sense, if you have a large canvas with a set of actual controls that are "on top" of that canvas but not necessarily "owned" by it, the view controller would probably want to create and attach these into the view hierarchy.
If I want to build a generic UI Component (one that will handle its own view and logic, data source,
etc), is it a good practice to subclass UIViewController?
I would say no. But it depends. If your component manages other view controllers or has/will have any kind of logic that's not specific to a view (e.g. navigation logic, business logic etc) , then you should subclass a view controller. Then again that makes it more than an UI component.
Otherwise, you should subclass an UIView, like Apple does with many components, including UITableView (speaking of datasource), GLKView, UICollectionView.
My overly simplistic answer is "no, when building a generic component do not automatically start with a UIViewController subclass". However that alone is not a useful answer and in some cases a UIViewController subclass is exactly the right solution.
Instead let's consider how to decide what your component should be. I think the best way to figure that out is to answer three questions:
What is this component responsible for?
How do you want to interact with it?
What are its dependencies?
In all cases we can try to start as simple as possible and add complexity only when the answers to those questions require it.
Could this component just be a function? No objects, no classes, if all you want to add is some behavior then maybe all we need is a function. If this behavior only applies to specific existing types then maybe we need a category on an existing class.
Not enough to cover what we want to do? Ok, I guess we might be talking about a new type so let's create a class. Can it just be a subclass of NSObject?
Want to display something in a view? Ok, then we at least have a UIView subclass, maybe a UIControl subclass if it is more interactive.
The view needs some data to back it? No problem sounds like we now need two pieces; a view to display data and a data source to provide it. Here the view shouldn't need to know who creates and owns this data source. As long as one was provided to the view we can use it, anything else is outside of the view's area of responsibility. Similarly we might add a delegate to notify some other object of interactions with the view.
If we still haven't covered all of this component's responsibilities then maybe we need yet another piece, something in the controller layer to manage our view. We're still not (yet) talking about a UIViewController though! It's fine to have a "controller" or "service" that is a NSObject subclass. If all this piece needs to do is manage network connections, or map NSFetchedResultController results to our view's data source protocol and update the view, or just provide a convenient implementation of the most common mapping of model objects to the view's data source then a simple "controller" object is still all we need.
Still not enough? Finally we get to the point where we consider providing a UIViewController subclass. Maybe we want to allow users of the component to just present a modal view controller to hand off responsibility for an interaction (send an email, compose a tweet). Maybe there's a common set of default behaviors we want to provide that are tied to view controller life cycle events (UITableViewController flashing scroll bars in -viewDidAppear:).
Build your component from the pieces you need to support the behaviors you want to provide but keep it as small and simple as possible.
Yes, it's good practice in many cases. The iOS SDK contain many examples of UIViewController subclasses. A few of them contain only a small amount of generic behavior and are essentially useless without customization:
GLKViewController
UICollectionViewController
UITableViewController
And some of them provide significant generic behavior but are still mainly containers for your own view controllers:
UINavigationController
UIPageViewController
UISplitViewController
UITabBarController
But most of them are essentially complete packages with little or no need (or ability) to customize their behavior:
ABNewPersonViewController
ABPersonViewController
ABUnknownPersonViewController
EKCalendarChooser
EKEventEditViewController
EKEventViewController
GKAchievementViewController
GKFriendRequestComposeViewController
GKGameCenterViewController
GKLeaderboardViewController
GKMatchmakerViewController
GKTurnBasedMatchmakerViewController
MFMailComposeViewController
MFMessageComposeViewController
MPMediaPickerController
MPMoviePlayerViewController
PKAddPassesViewController
QLPreviewController
SKStoreProductViewController
SLComposeViewController
TWTweetComposeViewController
UIActivityViewController
UIImagePickerController
UIReferenceLibraryViewController
UIVideoEditorController
If you think about what all of these have in common, you may conclude that they all have two things in common:
Each has a specific model (in the MVC sense) that it interacts with, and that model is not specific to your app. The models vary widely (UIVideoEditorController's model is a single video; UIImagePickerController's model is the entire photo library; GKAchievementViewController's model is a database possibly on an Apple server in “the cloud”), in some cases you provide the model (or some properties of the model) up front, and in some cases you receive the model (or a fragment of it) at the end. But in every case, the view controller handles all the interaction between the user and the model with little or no ongoing help from your app.
Each provides its own view hierarchy, with little or no customization required (or even permitted).
In other words, each of these view controllers isn't just the “C” of an MVC pattern. It's the tip of an entire MVC iceberg.
If your component is also an MVC iceberg, then exposing the tip of your iceberg as a UIViewController subclass is quite appropriate.
It depends on the iOS version you used.
A. prior to iOS 5.0, It's not a good practice, and not recommend.
B. start with iOS 5.0, It's just ok.
subclass a view controller for a UI component (UIView), , that means you wanna use the view controller life cycle method, to manage the user interaction and view display procedure, data model etc. So, if the life cycle method can not easily automatic called, the view controller is not that meaningful.
start with iOS 5.0, it's possible to create custom view controller container, so, it's ok to build custom generic ui component with view controller to add as a child view controller.
prior to iOS 5.0. Subclass a UIView with custom delegate protocol is the right way. one other thing is about the code organize. put the all custom delegate method to another custom class, not in the view controller, in the view controller just init a delegate class instance, and set this to the view delegate property.
At the moment I'm using a Singleton class to do some work but I'm wondering if there is something better.
I have an app that has a completely dynamic work flow. It uses a navigation controller but the order of the view controllers depends entirely on some data that is downloaded from our server.
The entire workflow is downloaded and saved in an array.
The "main menu" screen of the app has several choices (settings, recent, etc...) these are fixed but one of them is the dynamic one. It always starts with the same type of view controller but from then on it depends on what you choose.
Description
There are 4 different types of these dynamic controllers.
Table View Controller with single selection and detail indicators.
Table View Controller with multiple selection and checkmarks.
View Controller with a text field and keyboard.
View Controller (with other related VCs) used for searching for accounts on the server.
When you press the option "New Event" on the main menu the menu then goes off to the singleton (EventManager) and tells it to start a new event.
The singleton then pushes a single selection dynamic view on the nav controller and gives it the initial options.
From here on the singleton picks up all the selections and works out what type of view is required next.
I hope this is making sense
Anyway, I don't like the singleton pattern here as I don't think it should be a singleton.
What I would like is a class that I can create from a ViewController and this class will then control the pushing and popping and flow of data between a load of different view controllers. Then when you go back to the main menu this class can go away so I create a new class each time.
Is there a pattern that I can look at that will do this? Or should I stick with a singleton like I am now?
I hope this makes sense.
EDIT
Could I use a UIPageViewController for this? Then the datasource/delegate object of the UIPageViewController will take the place of the Singleton I am currently using... or something?
ADDING PHOTO FROM TWITTER REQUEST
Each VC along the flow has no idea what cam before it or what comes next. All they do is call back to the singleton to say "This value was selected" or "This text was entered" etc...
The singleton then stores that info and works out what comes next and pushes the next VC onto the stack.
It needs to be able to move back along the stack so the user can go back to change something etc...
It's all working as it is I just don't like the use of the singleton.
Lots of comments here in order of importance.
Everything you've described here sounds really good, even down to the naming. "EventManager" sort of sounds like it manages all "events" in the system (so I'd expect there to be a class called Event, but that's a tiny quibble and the name is likely still very good). There are other good designs, but I wouldn't have any problem with yours.
I agree that this does look like a good fit for UIPageViewController. You should certainly investigate that to see if it's the right fit. It's always nice to use a built-in controller if you can.
There's no reason to strongly avoid singletons. They are a natural part of iOS development and fairly common in good Cocoa design. They should be "shared" singletons generally (never create "strict" singletons that override +allocWithZone:). This just creates an easy-to-access instance rather than a true "singleton." This is the way things like NSNotificationCenter work and is often a very good pattern.
Singletons are best when many random pieces of the system need to access them directly and passing them around to everyone would be a lot of overhead (especially if many of the pieces you'd have to pass the object to don't need it themselves). Again, think NSNotificationCenter. If the users of it are mostly contiguous (i.e. most objects you would pass it to actually need it themselves), then just create one at the start of the program and pass it around. That sounds like your situation, so your intuition about it seems good. Just de-singleton it and pass it. Easy change.
But I'd definitely dig into UIPageViewController. It could match your problem very well.