I want to break my code into 3 files and them up via addsubview. For ex. i have a masterview, mastreview contains a currentView. CurrentView contains 1 webview and 1 tableview.
Now, i have written all code in one file and it works like a charm. But i want to make it abstract and loosely coupled . So i need a separate file ex. webviewController to implement its delegate and function related to it AND tableviewController to implement its delegate and functions related to it. And add both by addsubview, alloc init in masterview file.
I did it my way,though i was able to addsubview on CurrentView, the problem was my delegate functions are not working properly.
Also, i am confused about tableviewController should inherit UIViewController or UIView or UITableView.
it would be good if anyone can guide or send some link related to it, any example...???
Actually you should have the app crashing if the delegates are not retained somewhere.
If you do link the object with view controller to be it's delegate at Interface Builder, the view controller will be destroyed after it's outlets so you don't care. If you are creating separate class for the delegate, you should care about it's lifecycle, standard classes do not retain their delegates so you have to retain it on the same level where you are retaining the delegated object. Like if you are creating a UITableView subview and you have MyTVDelegate class, you should create the delegate instance, assign it to tableView.delegate and retain as viewController var so that viewController will dealloc both subviews and their delegates when needed.
For the second question, UITableviewController inherits UIViewController as you can see at header files (command+click on UITableviewController), and UITableView inherits UIView. Every viewcontroller should have the root view of UIView and I believe UITableviewController has UITableView as it's root view.
Related
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.
I have dragged out a splitViewController, and identified it as a subclass I have created MySplitViewController.
When Right-clicking the splitview storyboard I can see that I've set its Master and Detail view controllers, and furthermore that the delegate is NOT set.
I have made my subclass conform to the protocol and implemented some methods, but they are not being called (which I not understand is because the delegate is not set).
But whenever I try to ctrl+drag from the delegate option in the storyboard to my class, it won't link up. In fact, it won't link up with anything. Am I using this protocol wrong, should my subclass of UISplitViewController not be its own delegate? Then where do I define the delegate in code or otherwise?
Thank you for your time.
Edit: More info-
I tried putting self.delegate = self; in viewDidLoad, but that didn't seem to help.
The particular method I am trying to override is
splitViewControllerPreferredInterfaceOrientationForPresentation:
and I've put an NSLog in the code to notify me if it gets called, which it isn't
As far as I know, NSSplitViewControllers cannot have delegates, and their splitViews can't have their delegates reassigned since the controller acts as the delegate.
If you need access to the delegate methods, simply subclass the controller, then change the class name in Interface Builder.
I'm relatively new to Xcode.
I am trying to do this in Xcode's Interface Builder as much as possible. Because I am working with legacy code, Storyboards are not an option.
I'm working with a XIB I'll call DualTVController. It is based on a simple UIViewContoller.
In this XIB I have two UITableViews, the LeftTV and the RightTV. In IB, I am able to assign the delegate/datasource of the LeftTV to the File's Owner, which is the class representation of the XIB. This works fine.
I want to assign the delegate/datasource of the RightTV in IB. So far, I've successfully been able to use the LeftTV for this, but that's just confusing.
Instead, I have created a UITableViewController subclass called RightDelegate, and assigned it as the class of a simple Object I create through the IB. I made it follow the UITableViewDataSource and UITableViewDelegate protocols. This allows me to hook up the delegate/datasource of RightTV to it in IB, but when I try to run it, I get a BAD_ACCESS error.
I have the same delegate code in RightDelegate as I do in LeftTV (which works). Can anyone suggest the problem? Am I responsible for instantiating RightDelegate in code?
Thanks for any help.
note: I know you want to do this in IB, but in this case this is probably best handled in code. setting delegates for a single tableview in IB is simple, but eaisly overlooked. Since the delegates are so important, I usually keep them in code so there less mistakes.
when you are going to use more than one tableview there are a couple of ways to manage the delegates.
a) manage both delegates in your view controller with logic on each delegate callback to determine which tableview is asking (ends up messy)
b) split delegates by leaving one in your vc and putting the other in its own separate controller (somewhat confusing)
c) split delegates by using a separate tableview controller instance for each tableview. This is probably the best choice but it does require 3 controllers - your initial view controller that will init the xib file and then two separate tableview controllers - leftTable, rightTable.
in your main view controller, make sure you setup a property for each tableview:
then include your view controllers
then initialize the tableview controllers and set the delegates
//Example
self.rtv = [[rightTableViewController alloc] init]; //create a strong property for this
self.rtv.delegate = self; //let it talk back to you if needed
self.ltv = [[leftTableViewController alloc] init];
self.ltv.delegate = self;
self.rightTableView.delegate = rtv;
self.rightTableView.datasource = rtv;
self.leftTableView.delegate = ltv;
self.leftTableView.datasource = ltv;
Then just add code in each tableview controller to manage the tableviews.
If you need the tableview controller to call your main view controller then use delegate callbacks.
hope this helps, best of luck.
I followed this discussion: UITableView issue when using separate delegate/dataSource, and even though I found it super informative and useful, I have a follow up question:
So I've got a similar setup where I have a UITableView within the UIView. The UIView is controlled by it's own UIViewController (let's call it MyUIViewController) and also I moved the delegate and datasource for the UITableView into a separate subclass of UITableViewController (say, MyUITableViewController).
Everything works fine with the tableView.
The question is, how do I make a callback from MyUITableViewController to the MyUIViewController? For example, if the user selects a cell under the tableView which triggers didSelectRowAtIndexPath, I need to update something on the UIView which is actually a parent of this UITableView. So I basically need to send a message to MyUITableViewController. How would I do that?
You can use a delegate pattern in this case. I have a similar answer with sample code in this SO . In your case, the parent view controller is MyUIViewController. And the child view controller is MyUITableViewController.
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.