UITableViewController inside UIViewController - iphone

I'm working on an Iphone project. In the storyboard I have myViewController containing few UILabels and a UITableView.
The mentioned UITableView is referenced in the myViewController class by an IBOutlet :
IBOutlet UITableView *myTable;
Now I build a UITableViewController (myTableViewController) that I want to populate myTable.
Then I go back to myViewController and I allocate in here myTableViewController :
MyTableViewController *myTableViewController = [[MyTableViewController alloc] init];
myTableViewController.tableView = myTable;
myTableViewController.tableView.delegate = myTableViewController;
myTableViewController.tableView.dataSource = myTableViewController;
It is not working (EXC_BAD_ACCESS error).
Usually I should populate myTable trough the UIViewController (making sure it conforms to nedeed protocols). But I'm really wondering If I can do what I did right above..

Most cases you can solve this by creating a UIViewController and a reference to the table inside the ViewController using an IBOutlet. However, there are cases where you need a full blown UITableViewController, such as in core data, and you also would like the ability to add things like UIToolbars. I know, a lot of times you can hack a UINavigationController, but sometimes you don't want a hierarchy/stack. In such a case, admittedly fairly rare, one way to do this is to create a UITableViewController subclass. You can import and initialize it in your UIViewController class, create an outlet from the tableView sitting inside the UIViewController's nib/scene, and then assign the tableView property of the UITableViewController to the tableView outlet of the UIViewController.
self.instanceOfUITableVC.table = self.tableView
It's a bit complex, but it works. Now you can control the tableView using the UITableViewController subclass instance.

Related

UITableviewController losing reference to tableview

I have been working on this for 2 days now, cant seem to get a grasp. I'm missing something very basic I guess.
Here's what I have:
A UIViewController as the Apps root controller.
There's a ContainerView, a subclass of UIView which I add to my root controller view.
Within that I want a UITableView.
Since there are several different Containers, I have different Nibs for each.
Heres how its wired: Nib with content, has the container as its file's owner. There's an outlet to the UITableView, it has the container as source and delegate.
The container implements the protocol methods.
Now I can't call reloaddata on the UITableView since it's nil. I type po in the consolo and it says 0x0 but I don't know why.
I have been trying different approaches, but all ended up in losing the reference to the tableView.
It's not like it's my first tableview I create but I have no clue on what I'm doing wrong here.
Any HELP please!!!!
Code:
This is my Outlet:
IBOutlet UITableView *contactsTV;
File's owner has a connection to it, the tableview vice versa.
I create the nib by doing:
Contentview *v = [[Contentview alloc] initWithFrame:[[contentViewArray objectAtIndex:i] CGRectValue]];
while contentViewArray is some array storing Framevalues as strings.
Then I do:
[v prepareView];
and it looks like this:
- (void) prepareView {
NSArray *mediaPlayerViews = [[NSBundle mainBundle] loadNibNamed:#"MyView"
owner:self
options:nil];
UIView *v = (UIView *)[mediaPlayerViews objectAtIndex:0];
[self addSubview:v];
}
Just experienced a similar issue -- everything appeared wired up correctly (Xcode 4) but the outlet reference was nil.
When I created the file, I used the "New File" -> subclass of UITableViewController. with NIB (automatic) process to set up the file. This resulted in the controller being declared as a UITableViewController and the NIB had a UITableView as it's root.
Although the TableDataSource and TableDelegate methods got called as expected, the outlet for the TableView was never being set when the nib was loaded.
To fix this, I basically had to change the controller from being a subclass of UITableViewController to just UIViewController and set the NIB accordingly: I cleared the NIB, added a UIView with a UITableView as a child, reconnected the outlets (View, TableView, TableDataSource, and TableDelegate), and it all worked as planned.
I think this may be a bug with XCode, when creating a subclass of UITableView with NIB.
Set it as a UITableViewController it should work.
Do you have property set in header file along with
IBOutlet UITableView *contactsTV
?
If you don't have setter method for your contactsTV, then your contactsTV isn't retained by your object.
Try to replace your code with
//header file
UITableView *contactsTV;
#property(nonatomic, retain) IBOutlet UITableView *contactsTV;
//implementation file
#synthesize contactsTV;

iPhone Subclassing view controller and IBOutlet UITableView

I have the following problem. I've created a ViewController pretty much like the above
#interface MyViewController : UIViewController {
IBOutlet UITableView *myTableView;
}
#property (nonatomic, retain) IBOutlet UITableView *myTableView;
I've linked myTableView on the Interface Builder to the matching nib's UITableView. and I've subclassed MyViewController to create YourViewController as so:
#interface YourViewController : MyViewController {
}
And then I load from a TabBarController the YourViewController on a tab item. Although I can see that MyViewController is indeed invoked at the end, no table view is displayed on the emulator.
I've tried debugging the MyViewController and it appears the the IBOutlet is nil.
Why is that?
I have encountered major issues with inheritance and IBOutlets and IBAction. I advise you to avoid that, and create shared stuff in another way.
I was hit hard by bugs when getting memory warnings for instance. Outlets and actions didn't get reconnected properly when they were defined in base class vs derived class.
Probably MyViewController's nib file is not loaded at all. Are you using for YourViewController a specific nib file? and in which way are you creating YourViewController.
Can you also try to define an "awakeFromNib" method in YourViewController and then from it call [super awakeFromNib] ?
However to understand your issue you must clearly explain how you load objects and if and where you use Nibs?
If you add it dynamically using code then only it will work. Not using Nib.
the UITableView (ie. your myTableView) needs delegates for data source and and its control.
And your controller needs a link to the Table view in the xib.
declare table delegate protocols in the interface section of your controller.
using IB, link the TableView in your xib to owners file:delegates.
using IB, link the file owner myTableView to the tableView in the xib.
I hope it will help.
Assuming that you have your whole navigation stack in MainWindow.xib
Open MainWindow.xib
Select YourViewController (Or whatever your controller that is subclassing UITableViewController is called)
Select Attributes Inspector
Ensure that the 'NIB Name' property has your correct YourViewController (Or whatever the name) selected
I had this exact same issue, this solved it for me.

Extending a UIViewController with a different NIB file

Ok, I am definitely doing something wrong here...
I have create a BaseViewController that is the datasource and delegate of an matching NIB file containing a UITableView. This controller is responsible pretty much for getting data from a remote web service, creating the cells, and populating the UITableView.
So now I want to create a SearchViewController, so that I can get a UISearchBar that a user can enter a search query, post it on the web service, get the results and populate a UITableView.
However most of the code (in retrieving the data/populating the UITableView) exists in BaseViewController. So the first thing I thought of is to create the SearchViewController as an extension of BaseViewController with a different NIB file.
I've created the new NIB file called SearchView containing a UISearchBar and a UITableView and linked those two with the File Owners IBOutlets. (The UITableView IBOutlet is being inherited from BaseViewController)
So finally in my MainWindow.xib I've added a TabBarController and from the IB I've linked the UINavigationController to load the SearchViewController with View being loaded from SearchView. When I switch to the search tab, I am getting a SIG_ABORT with error:
-[UITableViewController loadView] loaded the "SearchView" nib but didn't get a UITableView
Could anyone point me in the right direction on how to proceed? I am sure most of you doing stuff with UITableView have reused code by extended a class. Is this the correct approach?
I'm not sure that I follow your description exactly, but what I think you should do is create your SearchViewController as a subclass of BaseViewController, like
#interface EventListViewController : UIViewController { ... }
Is that what you mean by "extending" BaseViewController?
And then you're using [[SearchViewController alloc] initWithNibName:#"SearchView" bundle:nil] to create your SearchViewController? I usually handle the initial view loading of my apps programmatically in the app delegate.
The error you get sounds like your IBOutlet connections are wrong somehow. Too bad you can't post a nib file here as easily as you can post code.

Subclassing UITableViewController what you get?

This is probably me being a little dim, I am setting up a UITableViewController via a UINavigationController, I have subclassed UITableViewController: (see below) and have implemented the datasource methods to get my table up and running
#interface RootViewController : UITableViewController {
NSArray *dataList;
}
#property(nonatomic, retain) NSArray *dataList;
#end
My question is: when I came to implement the viewDidLoad for RootViewController I wanted to set the title for the table (See image below). I looked at the docs for UITableViewController and found that it had a property called "tableView" so I tried ...
[[self tableView] setTitle:#"Eeek!"];
This did not work, what I should have tried was ...
[self setTitle:#"Eeek!"];
What I am wondering, when you subclass UITableViewController and add code your actually dealing with the tableView and not the UITableViewController, does this make sense?
Gary
what you are setting is actually the UIViewController (the parent class of UITableViewController) title, which is what UINavigationController uses to display a title in its navigationBar (the blue bar in your image)
Edit to better answer question: so no, when you subclass UITableViewController, you are actually dealing with the controller, not the table view itself.
Short answer to the question, no - you are still dealing with the properties of the Controller. The difference between the two setTitle: operations is:
// This message is being sent to the UITableViewController
[self setTitle:#"Eeek!"];
// This message is being sent to the UITableView property of the UITableViewController
[[self tableView] setTitle:#"Eeek!"];
There is no setTitle: method on the UITableView object, so that fails.
Abstractly in terms of MVC, the first is setting the property on a Controller and the second is setting the property on a View.

iPhone Views at Runtime?

I am new to the iPhone SDK and am trying to create 3 views and switch between them. Data will come from a server and I will basically be showing 1 view and caching the other two. So far I am just trying to create a view and display it at run-time. My code is listed below. It shows only a blank screen and I think I am missing a key concept. Any Help?
#import <UIKit/UIKit.h>
#import "ImageViewController.h"
#interface Test5ViewController : UIViewController
{
IBOutlet UIView *rootView;
ImageViewController *curImage;
ImageViewController *nextImage;
ImageViewController *prevImage;
}
#property(nonatomic,retain) IBOutlet UIView *rootView;
#property(nonatomic,retain) ImageViewController *curImage;
#property(nonatomic,retain) ImageViewController *nextImage;
#property(nonatomic,retain) ImageViewController *prevImage;
#end
and
- (void)loadView
{
self.curImage = [[ImageViewController alloc]initWithNibName:#"ImageView" bundle:[NSBundle mainBundle]];
UIImage *pic = [UIImage imageNamed:#"baby-gorilla.jpg"];
[self.curImage assignImage:pic];
self.rootView = self.curImage.view;
}
and
#import <UIKit/UIKit.h>
#interface ImageViewController : UIViewController
{
IBOutlet UIImageView *image;
}
-(void)assignImage:(UIImage *)screenShotToSet;
#property(nonatomic,retain) IBOutlet UIImageView *image;
#end
Welcome to the iPhone SDK!
In general, there are two ways to get any view displayed.
First, and most commonly, you use a NIB file created by the Interface Builder. This is usually the easiest way to get started and I would recommend it for what you're trying to do here. It's too lengthy to describe all the steps you need to do for what you have here, but basically start in xcode by creating a new file and selecting "user interfaces" and choose View XIB. This will create a basic NIB file (they're called NIBs rather than XIBs for historical reasons). The first step in interface builder is to change the class name of the "File's Owner" to your UIViewController subclass (Test5ViewController). You can then drop anything that IB will allow into the view window or even replace the pre-supplied view object with one of your own. And here's the trick: make sure the view outlet (supplied by the UIViewController superclass) is connected to a view. Once this is done, this view will be automatically loaded when your NIB is loaded. You can then just put your UIViewController subclass (Test5ViewController) in your MainWindow.xib NIB file to get it automatically loaded, and you're in business.
Now, the way you're doing it here is the second way. Some people like to code this way all the time and not user interface builder. And while it's definitely necessary sometimes and always more flexible, it makes you understand what is happening a bit better. There may be other things, but the main thing you're missing is that in your code above, you have nothing that is adding your view into the view hierarchy. You need to check first that you have an UIApplicationDelegate subclass and it needs to load your "root" UIViewController class. All initial project creation types in xcode do this (except Window-based application). It is code like:
[window addSubview:rootController.view];
Once this is done, if your view controller wasn't loaded by the NIB (described briefly above), your loadView method will be called, expecting you to build your own view hierarchy. Above, you created the view(s), but failed to put them in a hierarchy. You need something like:
[self.view addSubview:curImage.view];
No view will be rendered until added to the view hierarchy. Make sure to look up the UIView class in the documentation and understand the variety of ways to add and remove views to the view hierarchy.
A couple things I should warn you about:
* your code above is leaking. You need to review how objective-C properties work. There's lots on this site about it. More than I have time to write about here.
* don't create a rootView property in the case you have here. There already is one in the superclass (UIViewController). It's just 'view'. Use that for saving your root view.
I hope this helps you get started. It can be bewildering at first, but you'll soon get it going! I recommend building and rewriting and rebuilding a lot of sample code before you do your "real" application. The SDK has many great samples.