The best implementation of a tableview in Model View Controller - swift

What is the best implementation of a tableview in Model View Controller?
I'm developing my app without storyboard, all programmatically .
Is it possible to implement a TableView in a UIView? I tried it, but If I implement the TableView in a view, when the controller recives a button action, I can't modify or access to the tableView of the View...
After that, I tried to implement the tableView in a ViewController and it works perfectly, but I don't know if this is a good implementation because I found the same problem when I wanted to implement a TextView/TextField with a Piker, for example.
My goal was to had a clean code of viewController with a views and controllers (of buttons etc) and now I find myself with a uiviewController with the view and multiples components when I wanted the components were in the corresponding views.
Thank you very much!

It is all possible, and the problems you are running into are not because of it being something that you should not do, but that it is something that inherently works slightly differently than before. To answer your question directly, I would implement the tableView as the modal view controller directly, either as a UITableViewController or a UIViewController that inherits the table views delegate and datasource (this method being chosen if you don't want the table view to use up the entirety of the modal view controller's space).
TableViews are simple to use, but understanding every detail of how they work will make you far stronger and able to use them in any of these scenarios. I am not going to write you a guide on their use, butcontinue studying them before you declare that anything "can not be done".
Knowing what classes to implement the delegate methods becomes very important during these different scenarios. It is often easiest to use textfields delegate's implementation in UITableViewCell's subclass rather than in the UIViewController they are in. This allows for a more modular creation.
I find that working with the storyboard allows for a much quicker learning curve, and also a time saver. The one excuse I will give you for working without a storyboard is if you have an extremely slow computer.

Related

Reuse a custom UITableView in different UIViewControllers

I'm developing an iPhone app for iOS 5.1. I built a UIViewController which has a UITableView with a UISearchDisplayController and other views, all somehow related to the table. The UIVIewController is the delegate and the datasource of the table, and makes some customizations (graphical and business-related) to the table and search display controller. So far, everything was OK.
The problem is that now I want to put this same table (maybe with a different sublist of elements, of the same type) in different controllers (different screens of the app). I tried to add the tableView of my controller as a subview in other controllers, but it doesn't work. I tried to rebuild my table as a subclass of UIView (instead of UIViewController) and add it as a subview, but it neither worked (it loaded the view from a NIB file, but all its properties, including the IBOutlets, where nil or 0x000000).
After searching a lot, I didn't find any example of how to reuse a tableview in different controllers. Any hint? Any example? Should I build it as a UIViewController or as a UIView? Which class should be the delegate of the table and searchdisplay, keeping in mind that most of the logic I want to reuse is the code in the delegates?
Thank you all in advance
Wouldn't the easiest solution be to create your own Datasource class (maybe as a singleton) and then reuse this with the other controller? This way, your way of getting and managing the data is abstracted from the way of displaying it. Just the way it should be.
This is what MVC is all about.

How do I set up several custom UIViewControllers under one central view controller programmatically?

Being new to Xcode and Objective-C I find it hard to get my head around the Interface builder and Objective-C when doing things that are following the basic pattern. I have created a subclass of UIViewController that I want to instantiate several times to make a grid with each row being controlled by an instance of this class. So there will be one root view controller (with navigation etc) that should include/genereate all the instances of the custom sub-viewcontroller.
Now what would be the best way to do this? All examples I can find are about navigation, where one view should replace another, but I want to have all the viewcontrollers visible on the same "page". Do I need to create a nib file for the custom controller at all? I have also been thinking about using the UITableView somehow but inserting my custom viewcontroller in every row.
Any help greatly appreciated!
Apple's documentation recommends using one view controller per screen. It is possible to decompose your interface and use multiple view controllers on one screen if you have a good reason to do it, but Apple hasn't really designed their frameworks to support this, so you'll run into pitfalls if you don't know what you're doing.
In this case, I question whether each row of your grid really needs its own view controller. I find it hard to imagine a case where this would be the best choice, although it's hard to say for sure without knowing more about your app. Some things to consider:
What is your custom controller doing? Is it mostly changing the visual appearance of its corresponding grid row? If so, perhaps it would be more appropriate to subclass the UIView itself.
If this object is really behaving as a controller and not a view, consider implementing it as a subclass of NSObject rather than subclassing UIViewController. The UIViewController for your screen can capture events and delegate them to the appropriate custom controller object, or your custom views can capture their own events and notify their associated controllers of those events directly using a delegate pattern.
If you're sure you have a valid reason to implement these objects as UIViewController subclasses, check out my answer to this question.

Must a view controller always have a delegate in iPhone apps?

I'm learning how to develop my own iPhone apps but I'm having a tough time understanding certain concepts.
First, am i right to say that for every view, there must be a view controller for it? And for every view controller, must there be a delegate for it?
Also, what is the role of mainWindow.nib? Most of the tutorials that i've read don't seem to touch that nib at all. What always happens is the setting up of a NavigationController as the root controller, which pushes another ViewController onto the stack and this ViewController will have another nib associated with it.
So can i assume that i can safely ignore the main window nib?
It's all about MVC (Model View Controller), innit?
The Model, well that's up to you - what does your app do? Think of it as the backend, the engine of your app, free of the cruft of font size decisions and touch events.
The View, Apple pretty much wrote that for you. You use their Textfields and tables and imageViews. You assemble them together using Interface Builder into your GUI (packaged as a .nib). You rarely, if ever need to subclass the standard view elements (in a game you want a custom View to draw to, as all your drawing is probably custom). You can break different parts of your GUI into different .nib files if this helps you manage them. It's entirely up to you.
The Controller, so you have probably got some work todo to enable your GUI to represent your model. You need Some Controllers. How many? However many is manageable by you. If you had a view containing 2 subviews would they each need a view controller? Nah, probably not. How complicated is your code to hook up the view to the model?
Some GUI patterns are so common that Apple even wrote the Controller code for you. EG the controller for a UINavigationBar, UINavigationController. So, if your app has hierarchical views that you need to navigate around and you need to display a navigation bar you can use an instance of UINavigationController instead of writing your own class. Yay!
Surely tho, the UINavigationController code (or any other viewController) can't magically know how to integrate with our model, with our view, can it? NO, it can't. In general in Cocoa if there is some class of object that mostly works off the shelf but also has optionally configurable behavoir - allowing us to tailor it to our needs - it is done by Delegation. ie Instead of subclassing UINavigationController we tell the specific instance of it where to find (for want of a better term) it's custom behavoir.
Why? Let's say you have a navigationController, a tableView and a textfield. UINavigationController mostly take care of your navigation needs but you have to have a crazy QUACK sound play each time the user moves to a new view. UITableView is mostly exactly everything you need from a table, EXCEPT you really want the third row in the table on the front page be twice the height of the other rows. And the standard, off -the-shelf UITextField pretty much takes care of your textfield needs EXCEPT you need your textfield to only be editable when the user is facing North. One way to handle this would be to create 3 new classes, a custom UINavigationController, a custom tableView and a custom textfield, and to use these instead. With delegation we could use the classes as they are and have one object be the delegate of all 3 instances - much cleaner.
Delegation is mostly optional, the docs will tell you when, and it's down to you and whether you need that custom behavoir.

Why shouldn't a UITableViewController manage part of a window in Cocoa Touch?

I have a view that contains a UITableView and a UILabel which works perfectly as far as I can tell. I really don't want to manage the UIView and UITableView with the same controller as the UITableViewController handles a lot of housekeeping and according to the documentation:
If the view to be managed is a
composite view in which a table view
is one of multiple subviews, you must
use a custom subclass of
UIViewController to manage the table
view (and other views). Do not use a
UITableViewController object because
this controller class sizes the table
view to fill the screen between the
navigation bar and the tab bar (if
either are present).
Why does Apple warn against using it and what will happen if I ignore this warning?
Update: Originally I quoted the following from the Apple Documentation:
You should not use view
controllers to manage views that fill
only a part of their window—that is,
only part of the area defined by the
application content rectangle. If you
want to have an interface composed of
several smaller views, embed them all
in a single root view and manage that
view with your view controller.
While this issue is probably related to why UITableViewController was designed to be fullscreen, it isn't exactly the same issue.
The major practical reason to use only one view controller per screen is because that is the only way to manage navigation.
For example, suppose you have screen that has two separate view controllers and you load it with the navigation controller. Which of the two view controllers do you push and how do you load and reference the second one? (Not to mention the overhead of coordinating the two separate controllers simultaneously.)
I don't think using a single custom controller is a big of a hassle as you think.
Remember, there is no need for the TableviewDataSource and the TableViewDelegate to be in the actual controller. The Apple templates just do that for convenience. You can put the methods implementing both protocol in one class or separate them each into there own class. Then you simply link them up with the table in your custom controller. That way, all the custom controller has to do is manage the frame of tableview itself. All the configuration and data management will be in separate and self-contained objects. The custom control can easily message them if you need data from the other UI elements.
This kind of flexibility, customization and encapsulation is why the delegate design pattern is used in the first place. You can customize the heck out of anything without having to create one monster class that does everything. Instead, you just pop in a delegate module and go.
Edit01: Response to comment
If I understand your layout correctly, your problem is that the UITableViewController is hardwired to set the table to fill the available view. Most of the time the tableview is the top view itself and that works. The main function of the UITableViewController is to position the table so if you're using a non-standard layout, you don't need it. You can just use a generic view controller and let the nib set the table's frame (or do it programmatically). Like I said, its easy to think that the delegate and datasource methods have to be in the controller but they don't. You should just get rid of the tableViewController all together because it serves no purpose in your particular design.
To me, the important detail in Apple's documentation is that they advise you not to use "view controllers [i.e., instances of UIViewController or its subclasses] to manage views that fill only a part of their window". There is nothing wrong with using several (custom) controllers for non-fullscreen views, they just should not be UIViewController objects.
UIViewController expects that its view takes up the entire screen and if it doesn't, you might get strange results. The view controller resizes the view to fit the window (minus navigation bars and toolbars) when it appears, it manages device orientation (which is hard to apply correctly if its view does not take up the entire screen) etc. So given how UIViewController works, I think there is merit to Apple's advice.
However, that doesn't mean that you can't write your own controller classes to manage your subviews. Besides the things I mentioned above, interacting with tab bar and navigation controllers, and receiving memory warnings, there isn't really much that UIViewController does. You could just write your custom controller class (subclassed from NSObject), instantiate it in your "normal" fullscreen view controller and let it handle the interaction with your view.
The only problem I see is the responder chain. A view controller is part of the responder chain so that touch events that your views don't handle get forwarded to the view controller. As I see it, there is no easy way to place your custom controller in the responder chain. I don't know if this is relevant for you. If you can manage interaction with your view with the target-action mechanism, it wouldn't matter.
I have an application where I did use 2 separate UIViewController subclasses below another view controller to manage a table view and a toolbar. It 'kind of' works, but I got myself into a massive pickle as a result and now realize that I should not be using UIViewController subclasses for the sub controllers because they contain behavior that I don't need and that gets in the way.
The sort of things that went wrong, tended to be:
Strange resizing of the views when coming back from sub navigation and geometry calculations being different between viewWillLoad and viewDidLoad etc.
Difficulty in handling low memory warnings when I freed the subview controllers when I shouldn't have done.
Its the expectation that UIViewController subclasses won't be used like this, and the way they handle events, using the navigation controller etc that made trying to use more than one UIViewController subclass for the same page tricky because you end up spending more time circumventing their behaviour in this context.
In my opinion, The Apple Way is to provide you the "one" solution. This served the end-users very well. No choice, no headache.
We are programmers and we want to and need to customize. However, in some cases, Apple still doesn't want us to do too many changes. For example, the height of tab bar, tool bar and nav bar, some default sizes of the UI components(table view), some default behaviors, etc.. And when designing a framework and a suite of APIs, they need to nail down some decisions. Even if it's a very good and flexible design, there is always one programmer in the world wants to do something different and find it difficult to achieve against the design.
In short, you want a table view and a label on the same screen, but they don't think so. :)

UITableView vs UITableViewController

Can someone explain to me the advantages of a UITableViewController over a UITableView? Generally, I use the controller but the basic table view seems a lot more flexible.
I always use UITableView. I never use UITableViewController.
Using UITableViewController is confusing. Each controller is supposed to do one screen except container controllers.
Well, UITableViewController is a controller and most of the time, a tableView is simply not the only thing there.
If you look at documentation:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewController_Class/Reference/Reference.html
UITableViewController provide very little new interface compared to UITableView. None of which is essential.
– initWithStyle:
(duh? I initiate my tableView in nib and I customized a lot anyway)
Getting the Table View
tableView property
(the original tableView)
Configuring the Table Behavior
clearsSelectionOnViewWillAppear property
(okay, just put some code on ViewWillAppear)
Refreshing the Table View
refreshControl property
[tableView reload]?
So you see,
So unless you want your code to look neater (and not much more), there is no reason to use UITableViewController, that I know of.
I don't think you understand your own question.
The UITableViewController is a controller.
The UITableView is a view.
One isn't better than the other, they're completely different objects, used for completely different things.
I'd spend some time learning the Model-View-Controller pattern so prevalent throuought Cocoa and the iPhone SDK.
The Model-View-Controller Design Pattern
The idea is that ViewControllers hold a tree of subviews (and sub viewcontrollers) and manages dispatching events to/from its subviews. For example, you might have a view that holds an image, and that view lives in a view controller that handles orientation changes and memory warnings, etc.
This is one thing I find very confusing about Cocoa: Apple's implementation of MVC (or at least the terminology they use) is questionable. In Cocoa, most views are themselves actually acting in some capacity as controllers insofar as the MVC pattern defines them (just look at UITableView--most of its methods are actually controller methods). Therefore you have Apple's additional concept of a view controller on top of what is already to some extent a controller. The fact that you don't even need to use UITableViewController at all (even with data binding) basically proves that the view is acting as its own controller. In MVC, you can't have a view bound to a model without a controller (that's the whole point of the controller in MVC).
It appears to Apple's developers, that a "view controller" (e.g. UITableViewController) is really more of a slightly higher-level helper/manager class that manages the more low-level UITableView class and enables a few key additional capabilities that pertain more to how the table view interfaces with the general UI of the app.
Additionally, it appears that Apple intends for a view controller to actually be more of a screen controller, recommending only one view controller per screen (presumably meaning you can't nest view controllers). I maintain that calling this concept a view controller is a misnomer.
Please don't hesitate to correct me on this anyone, I'm still very new to Obj-C/Cocoa myself.
UITableView is a view and UITableViewController is a controller that has UITableView as its root view.
So, by using UITableViewController:
You have one root view that is UITableView itself. So it takes less memory than UITableView with a UIView as parent view in its controller.
It provides you with a ready-to-use template, if you needed a controller and a UITableView as its main display view.
Static table views are only valid when embedded in UITableViewController instances.
The link above returns a "Page Not Found." For some reason, even the corrected link returns a "Page Not Found" when hyperlinked (perhaps Apple doesn't allow linking into their developer site).
To find the relevant information, go to Apple's Developer Connection (http://developer.apple.com/index.html) and search on "cocoa model-view-controller design pattern".
In the table of results, select the "Cocoa Fundamentals Guide: Cocoa Design Patterns." On that page scroll down the Table of Contents on the left side until you see the item "The Model-View-Controller Design Pattern." Select that item to read more details about that particular design pattern.