I am pretty new to iOS. I have some data that is essentially a tree structure which is fetched from an external database so its depth is not defined at compile time for the app. I would like to display this information using UITableViewControllers inside of a UINavigationController. At this stage, I have embedded a UITableViewController in a UINavigationController in my storyboard, and have written a subclass of UITableViewController to display the first level of the tree. How do I programmatically segue to a new instance of the subclass of UITableViewController that I have created while also creating references for prototype cells I have defined in the storyboard. Is it possible to set up this kind of structure in iOS with UITableViewControllers and a UINavigationController?
Any help would be much appreciated.
Thanks!
In your TableView delegate, put some code into the didSelectRowAtIndexPath: method to create a new instance of your tableViewController subclass. Either pass it whatever data it needs to populate its cells, or possibly use your top level TableView delegate/datasource as the delegate/datasource for every new instance (you will have to keep track of where in your data hierarchy). You can then use self.navigationController pushViewController:animated: to transition to the new tableViewController. If you use the same subclass at each level, the cellForRowAtIndexPath: method will use the same cell reuse identifier (unless you code otherwise), so your prototype cells should be used at every level.
Related
I'm learning swift and I have gone through tutorials where some developers delete the View Controller entirely and just drag in a TableViewController and start using that. While other developers in tutorials create a TableView from within the View Controller.
Is it better to delete the View Controller and add a Table View Controller or just work with a TableView within the View Controller?
It is all about the requirement. Both are correct way. Don't be confuse.
When you using TableViewController then it only behaves with the UITableview. i mean controller totally dedicated itself as tableview.
When you using TableView inside UIViewController then you can create whole UI deign in your own way.
Note: As you'r new so I suggest you to go with TableView Inside UIViewController because you can achieve any type of UI with this even you can create ditto functionality(UITableViewController) with this but vice versa not true.
For eg.
tableView inside UIviewController
You can do it in either way. If your viewcontroller is going to have a tableview alone, then u can use a UITableViewController or else use UIViewController and set the delegates and datasource
I'm learning Swift. Sometimes I see that Main.Storyboard is used to set up the tableView delegate and dataSource (ctrl+click and so on). Sometimes I see that it's done through coding instead like so:
// create the variable for the tableview
IBOutlet weak var someTableView : UITableView!
// setup delegate and datasource
sefl.someTableView.delegate = self
self.someTableView.datasource = self
I do understand how it works with second way. But it's difficult to realize how it works through Main.Storyboard with no IBOutlet setup.
Thank you for your responses!
It works exactly the same way :)
Let me refresh the principle:
You have a class, provided by Apple in this case, that has to work for a lot of scenario. Apple decided to use a kind of inversion of control, called delegation, where the workflow is inverted (hence the name) : instead of the view controller giving order to the tableView by calling methods on it, it is the tableView that goes and fetch its orders from the controller by calling methods on it.
In order to achieve this kind of IoC (inversion of control), the TableView MUST know the "address" of the object it has to ask for its order. Like you have to know your boss' email address to ask him stuff. So, the UITableView class as a property called dataSource that means to store that address.
Now as a ViewController programmer, you have to set this property to be the address of the view controller that will give the order to that tableview.
2 ways of doing it :
in code : in the view controller, you have a property pointing to the tableview (if linked from the storyboard, it is called indeed an IBOutlet, but doesn't have to be) and you set it's delegate property to self. (meaning 'hey tableView, your boss is myself)
Or you do it in the storyboard, because the graphic template for the tableView let you ctrl+drag from the tableView to the ViewController and set the datasource connection. In this case it will be the storyboard who will have to find the address of the tableView (since it is the one creating it, it's kinda easy) and setting it's delegate property to be the address of the view controller (meaning hey tableView, your boss will be this guy)
Either way, the viewController has to be ready to answer all the question from the TableView, so conforming to the UITableViewDataSource protocol.
the delegate scenario is the same.
It is important to understand how the loading of views works in iOS. Your xib will be translated into the hierarchy of views and they are loaded onto the memory. When you make an IBOutlet of those views, you'll have a reference of that loaded view in your code. If you do not create an IBOutlet, it doesn't mean that the view isn't there. It is there and it is in the memory.
When you set the delegate and the dataSource of a tableView and when the tableView is loaded onto the memory, it sets the delegate and the dataSource of the loaded tableView to the class as specified by you. It doesn't matter if you do not have a reference to it.
Most of my app is created programmatically, but I have a handful of complex views that are created using Interface Builder and loaded programmatically.
In one view I have a UITableViewController subclass created programmatically, and its tableView property is assigned to the UITableView instance in the XIB, referenced as an IBOutlet. This happens in the XIB's UIViewController's viewDidLoad, and the table view displays correctly.
At one point, I need to change the entire contents of the table view. Ideally, I would like to disconnect that view from the first UITableViewController and connect it to a different one that will feed it different data. Attempting to assign the view to the new controller's tableView property results in "A view can only be associated with at most one view controller at a time!" Assigning the previous controller's tableView to nil before assigning the new one avoids the error, but the table view disappears from the screen.
Honestly, I know the table view instance is usually managed by the UITableViewController. I can't find anything in the docs about setTableView automatically setting the back references for delegate and dataSource in an assigned tableView, so I'm surprised my externally-created tableView works in the first place. In fact, the TVC docs seem to discuss UITableViewController's tableView property as readonly, even though it is not tagged as such.
I'm sure I don't have all your information, but on the surface it seems that you are making this more complicated than it needs to be. Why don't you just use the current UITableViewController and corresponding UITableView and reload it with "new data". Alternatively, just programmatically create another UITableViewController and use that for your new data. Is there a compelling reason to recycle the UITableView?
The answer is no, and here's why:
I checked with the debugger, and the normal setTableView does set the view property on self as well as setting the delegate and dataSource properties on the new incoming tableView. This is not documented by Apple, but it was the assumed behaviour and so it was all well and good.
What I did not realize is that the default setView (from UIViewController) will remove an existing view from its superview before setting the new one. To prevent the "one view controller at a time" runtime error I was setting the old TVC's tableView to nil, which caused the tableView I intended to reuse to be removed from the view hierarchy. To avoid this behaviour, one would have to override setView, which is more complicated than I care to get into for this task.
Reusing views (in this case, a UITableView instance) is not supported by Apple. It is not mentioned in the UITableViewController documentation, but it is mentioned in the UITableViewController documentation regarding the view property. Arguably, UITableViewController's tableView property should be marked readonly by Apple, with its tableView solely managed internally, but there's probably a good reason why its not.
Good afternoon,
I have a storyboard configured but I have difficulty with one aspect.
I am using a UITableView to recreate a directory structure i.e. folder>subfolder>files. The structure is going to be different for every user and the structure is supplied via a API. I currently have a UITableViewController within the storyboard.
How can I recreate this in the storyboard?
Currently I am just recreating another instance of the UITableViewController class and pushing it on to the UINavigationController but I of course lose all of the assigned segues.
Thanks
I'd expect one scene to represent the folder hierarchy. It would be a single UITableViewController with a table with 2 prototype table view cells. One table view cell would be for folders, the other for files. The table cell for the folders would have a push segue leading back in a loop to the table view controller. The file segue would lead to what ever scene you uses for files.
You can to use the table view data source and delegate methods to drive the table view and fill it with instances of your prototype cells.
In the Object Library of Xcode, there are two options one can use to create table view - table view and table view controller.
What is the difference between the two and when would they be used ?
A TableViewController is a ViewController with a TableView built in. This will have the delegate methods needed already declared and setup. This VC is already a TableView delegate and datasource. It cannot be resized. Upside is ease of use, downside is very limited flexibility.
A TableView is just that a TableView (subclass of UIView). It can be added to a ViewController and resized, used alongside another view based object, etc. The upside is the flexibility, the downside is that you have to setup the delegate and datasource methods yourself (in my opinion, well worth the time to get the flexibility).
One other note is that when using the new Static TableView cells (part of iOS5), you have to use a TableViewController.
The UITableViewController is a subclass of the UIViewController. It already assumes you will have UITableView as your rootView, so you already have access from the code to a tableView (self.tableView). It implements the UITableViewDataSource and the UITableViewDelegate protocol. It also gives you alot of methods for you to override. It allows you to not depend on XIB file, because you already know what you will have (UITableView as a rootView).
The UITableView is just UIView, normally you will have to comply to the protocols I have referenced above in your UIViewController in order to populate (data source) and work with it (delegate), and you probably have to create an IBOutlet for your UITableView.
On one hand you have speed but you are not as flexible as the other path. On the other you have the opposite.