Should I reuse a navigation and table view controller for different data sources? - ios

I am using ECSlidingViewController, a library that gives a side-drawer effect. My application opens to a (navigation controller holding a) table view controller of 'Nearby' results, and the cells segue to a scroll view controller.
The hidden left menu is a table view controller (of different class) with a few options, 2 of which are other table view controllers that will use the same layout, cell prototypes, and detail scroll view as the table view seen on startup.
I would like to know if it would be better design to make a more generic tableView with some sort of property like an enum'd typeOfDisplay, which lets me conditionally manage different nuances like populating cells from server/CoreData, navbar titles, sort order, toggling auto-updating, editability, etc. - OR - if I should make a NavigationController->TableViewController->ScrollViewController for each different view controller (A 'Nearby', 'Featured', and 'Saved')
I'd like to reuse my table view because the cells/display/detail will be identical, but the methods for populating the table are different, and I don't want to make something that's difficult to modify.
Edits -
If you are familiar with table views inside tab-bar contollers, the implementation details should be nearly the same.

It's better to put view configuration into view controller. But there can be ways to reuse the configuration actions.
I have ran into the same situation like yours. And I decided to use Strategy Pattern to refactor my controllers. I put all the data related stuff into a TableDataManager class which conforms to the UITableViewDataSource and UITableViewDelegate protocols and I applied polymorphism to it to configure the data in cells and the appearance of the UITableView under different circumstances at runtime.
All the identical actions are implemented in TableDataManager, and nuances are overridden by subclasses of TableDataManager. By assigning a proper subclass of TableDataManager to a view controller, there is no need for you to copy and paste the identical cells/display/detail actions here and there.
That's my experiences. Hope it will help.

I would recommend you to use different view controllers for different datasources. It sounds good initially to put them all together in one place, but as time goes by, you may need to add different functionalities to each table view, and your view controller will be a horrible mess.

Related

Associating a custom UICollectionViewController with a subview

I have a view controller in my main page, which includes a tableview;
in the row of the tableview, I have dragged and added a collection view.
In the storyboard I can click drag the delegate and data source of the collection view to the main view controller (easy enough).
However I like to bind these to a custom subclass of UICollectionViewController (to have a self contained MVC for collections) and not reply on the main page's view controller. How can I do this? (associate custom controller class with the collection view?)
Would I have to use a container view controller? What is the right approach for something like this?
I am newbie to iOS and would greatly appreciate any guidance.
You could drag a container view into the row, instead of the collection view. Then drag the collection view into the container's associated view controller scene. Change the class (in InterfaceBuilder's identity inspector tab on right) to be your custom view controller class.
--- end of answer ---
Now with that said, consider embracing more of an MVVM approach than MVC. By this I mean simply to not bother splitting out to separate view controllers for the sake of MVC, but instead to keep all your view controllers simple. Have each own one (or more) ViewModels, where all the business logic lives that's associated with that view controller. Each ViewModel (which is just an NSObject or even a Swift struct if you wish) can be independently unit tested without involving any UI at all. The view controllers just literally wire up the data from the ViewModels to the controls & views, and configures the controls & views while relying on the viewModel for any decision-making. It'll radically improve your architecture for minimal effort. Hope this helps!

Is it better to have a viewDidLoad in all view controllers or just in the main view controller have multiple UIViews?

For now I have a single login view controller that hide and adds subviews dynamically based on user interaction. Is it better to have multiple UIViews with one view controller, or multiple view controllers?
The benefit of having children UIViewControllers would be if you needed to care about the view lifecycle in any of the children. For instance, if in some of your subviews (child views) you needed to know if it appeared to trigger some logic, then it would be good to use children UIViewControllers.
Another reason might be, if you wanted to use view controller transitions within your custom container, as described by Apple in the UIViewController class reference:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/instm/UIViewController/transitionFromViewController:toViewController:duration:options:animations:completion:
But, to me it doesn't sound like you would need this, it sounds like you would just show/hide your views, or otherwise animate them.
But if your views don't care about any of that, and just need to render UI elements, I'd say using children UIViewControllers adds additional complexity without much benefit.
This is under the assumption that either way, all your views are living on the single UIViewController's view. If you are pushing and popping view controllers inside a UINavigationController, or presenting ViewControllers modally, you definitely should use UIViewControllers for that.
Also, you definitely shouldn't put all your view code inside that single view controller. You should use subclasses of UIView, or some other mechanism of making sure you separate your components.
For example you might have:
LoginViewController - organizes and hides and shows the individual views
SignInView - shows the sign in form
RegisterView - shows the register form
...etc
Of course its better to have multiple view controllers for many reasons:
Each view controller has its own code/logic/functionality.
Better for memory management. Once you're done from a view controller, system will automatically deallocates it from memory. Using multiple views will be overload in your system when some views are not used.
Better organisation for your project. You will just present/dismiss/push/pop view controllers and pass data between each other. Instead you will deal with horrible logic for hiding and showing UIViews.
Using one view controller will have a massive amount of code which in long term the project will be an impossible mission to manage.
Having multiple view controllers is better in the sense that you would have more ease at coding them individually. Also Navigation will be good which is good for User Experience.
Memory Management will be efficient.
The MVC architecture(Model View Controller) will instead become Massive View Controller which will be a headache while debugging.
Check out this answer for more clarity. I think you are confused between ViewController and View.
Check out the accepted answer of this question in the link. Hope it helps.
About viewController's "viewDidLoad" and "viewWillAppear" methods

Changing a Table View Controller to a View Controller

I have a Table View Controller that displays information using JSON. I want to change the styling of my app, and I don't want it to have that "table" view that it has now. Whats the easiest way to change my Table View Controller to a regular View Controller, the biggest problem I have is that the code uses a tableView and I dont know how to get it to work as a regular view controller.
I using a Storyboard with a TableViewController thats linked to a controller called UpcomingReleasesViewController.
I want my app:
To look like this:
My original answer was assuming you just wanted to convert from a UITableViewController to a UIViewController. Looking at your screen snapshots, I infer you really want to switch from a UITableViewController to a UICollectionViewController (which is an iOS 6 feature than allows you to do precisely what you want).
In that case, change your base class to UICollectionViewController, and replace your UITableViewDataSource methods with UICollectionViewDataSource methods. And then redesign your scene using a Collection View Controller.
See the Collection View Programming Guide for more information. Or see WWDC 2012 sessions Introducing Collection Views or Advanced Collection Views and Building Custom Layouts.
If you need to support iOS versions prior to 6, then you have to do this collection view style coding yourself manually, putting your image views on a scroll view and using a standard UIViewController. It require more effort than using a collection view, but can be done.
Original answer:
If this view controller will have a table view on it, but you just want to add more controls to the scene? If so, just change the view controller's base class from UITableViewController to UIViewController, create the new scene, add a table view to it, and specify the table view's delegate and data source to be the view controller:
Also, make sure you define an IBOutlet for your table view (and if you call it tableView, that will minimize any coding changes needed).
If you do that, you can quickly convert a UITableViewController based controller to a UIViewController with minimal code changes.
If you're looking to make something like your new UI mockup, look into UICollectionView. You'll see many of the same concepts (i.e. dataSource, delegate method signatures are similar) that are used in UITableViews used in the collectionView API.

Creating a multi column tableview/collectionview IOS

I need to create a multiple columned table which has independent scrolling for each view. Each column will contain sections that can be expanded to hold line items. All columns may not contain an equal number of sections. I was wondering what will be the best way to approach this.
I would recommend have each table view be contained in their own UITableViewController. Then you can use a container controller to display each table view controller in as subviews.
See: Creating Custom Container View Controllers
The advantage of this approach is that you can create a generic container view that only needs to worry about the location and sizing of the sub-view controllers. Each sub-view controller could worry about their own content. Thus you could have sub-view controllers be table view controllers, navigation view controllers or whatever you need at the time.
It sounds as though your columns won't really have anything to do with one another.
If so, just create three tableViews, and give each their own datasource and delegate.

Using multiple nib files with a single view controller?

Background
I'm using interface builder to create the UI for an app I'm working on. The app has a single screen that displays a series of buttons. Clicking on a button displays an associated view which overlays the buttons. Clicking another button hides the previous overlay view and displays another one.
Too make managing the UI easier in IB I've decided to create multiple nib files for each sub view that is to appear when clicking the relevant button. I'm then loading the sub view's nib file in the view controller's viewDidLoad method using the UINib class.
The idea behind this was to avoid having multiple views stacked on top of each other in a single nib file as this would be hard to manipulate in IB. I could have created all the views in code but this would require a lot of tedious coding as the layouts of each sub view are quite complex (with multiple child views).
Example code loading a sub view from a nib file.
- (void)viewDidLoad
{
UINib *aSubViewNib = [UINib nibWithNibName:#"aSubView" bundle:nil];
NSArray *bundleObjects = [aSubViewNib instantiateWithOwner:self options:nil];
// get root view from bundle array
UIView *aSubView = [bundleObjects objectAtIndex:0];
[self.view addSubview:aSubView];
...
The code above is repeated for the other views.
To summarise I have a single screen iPhone app that has layered views that are shown/hidden by clicking buttons. This is achieved with a single view controller with an associated nib file and a series of additional nib files for the sub views which are loaded in the view controller's viewDidLoad method.
Questions!
Sorry for the long introduction but I wanted to be very clear what it is I am doing.
Is my approach bad or unusual?
Are there any potential issues to doing it this way?
What have other people done when they need a dynamic interface and
still want to keep everything in Interface Builder?
Notes
Before anyone asks why don't I just display the sub views on a new screen and use the navigation bar, let me say that I have very good reasons and I do understand iOS UI guidelines. The above use case is not exactly my use case but it's one that clearly describes the problem without getting bogged down in my development app.
Also I know I could have written all the sub views as code but each sub view has a complex layout of child views and it would be a lot of code and messing around to try and get them looking right.
Thanks in advance.
There isn't necessarily a 1-to-1 relationship between view controllers and views. Most views contain many subviews, which are views themselves, so this literally doesn't make sense.
However, depending on the complexity of the views (including their content), you may want separate view controllers... or not.
For example, if you have two sbuviews that are each tableViews, you may want to have one view controller for each tableView. This is because each tableView is looking at the same delegate methods, and if they are in the same viewController, then the delegate methods have to differentiate between the tableViews. The delegate methods have signatures that allow this, but, in my experience, it can really make for a messy code design that is hard to follow and hard to manage.
On the other hand, you may have two tables that are managed by the same viewController, where one table is filled with meaningful data and the other is simply a place holder (as when the data source is empty). One might be visible while the other is not. Why make you life complicated by creating two view controllers when both are driven by the same data source (the model)?
In my mind, it comes down to how difficult it is to follow and manage the code. If the complexity of using a single view controller becomes burdensome, consider using more view controllers.
UPDATE
By the way, I have an example that I am currently working with that may illustrate a similar situation. In the InAppSettingsKit, that a lot of developers use, there are several xib files for pieces of the main view. You can look at the structure here on github. There is one main view controllers and several xib files. (There is also what I would call a "helper" view controller and an email composer view controller.) In this example, the xib files may be used multiple times to specify the layout of table view cells. There is no view controller for each xib file, though. (The documentation for InAppSettingsKit is sparse, so these things may not be obvious just by taking a quick look at it.)
Every View should have a corresponding UIViewController. Using one ViewController to "Control" more than one view breaks the MVC paradigm. "Controlling" multiple "views" from one controller will make it much harder to change one thing without breaking something else. The choices you make on how to present the content to the end user will be different for every individual. So if you say a NavigationController won't work in your case, maybe a Modal view is the answer or, you might just instantiate your custom UIViewControllers and add them to your view ([addSubview:]), if thats the road you want, but like I said, it would be beneficial for you to make a "controller" for each view object along with the corresponding xib. If you need information sent back, use a delegate or use Notifications to send the message back to the parent view. I learned the hard way that not following MVC paradigm, will make you life miserable. Try and keep your code as decoupled as possible. And read up on the MVC design pattern, you won't regret it.
actually its possible to do this.
Open your .xib file,select File’s Owner(in placeholder) -> "identity inspector" (utilities) -> change class name to your controller classname -> press control and drag file's owner placeholder to View object, select "view" in dialog.
Now you can customize your view.
p.s. you can use the same outlets as first xib, you need only to drag them to the new xib(+control sure).
here is an explained tutorial:
http://irawd.wordpress.com/2013/09/05/how-to-link-a-xib-file-to-a-class-and-use-2-xib-files-for-iphone4-and-iphone5/

Resources