UIViewController shows two UITableView - iphone

I have a weird problem.
I'm subclassing UIViewController and adding a tableView property in which I load a UITableView.
Now I'm adding this UITableView to the parent's subviews.
Works fine but I get TWO TableViews. One standard styled TableView and one the way I wanted it to be on top of the standard one. Both contain the correct data though.
#interface RootViewController : UIViewController <ABPersonViewControllerDelegate, UITableViewDelegate, UITableViewDataSource> {
UITableView *tableView;
ToolbarController *toolbar;
...
}
#property(nonatomic, retain) UITableView *tableView;
#property(nonatomic, retain) ToolbarController *toolbar;
...
#end
#implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
CGRect mainViewBounds = self.parentViewController.view.bounds;
CGFloat toolbarHeight = 44;
toolbar = [[ToolbarController alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(mainViewBounds), toolbarHeight) parentView:self];
tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, toolbarHeight, CGRectGetWidth(mainViewBounds), CGRectGetHeight(mainViewBounds) - toolbarHeight) style:UITableViewStylePlain];
tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
tableView.rowHeight = 60.0;
[tableView tableView].delegate = self;
[tableView tableView].dataSource = self;
tableView.backgroundColor = [UIColor clearColor];
[self.parentViewController.view addSubview:tableView];
[self.parentViewController.view addSubview:toolbar];
}
#end
------UPDATED------
I just wrongly pasted one part
[tableView tableView].delegate = self;
[tableView tableView].dataSource = self;
is actually in code
tableView.delegate = self;
tableView.dataSource = self;
-------UPDATE 2--------
If I don't create my own UITableView by
tableView = [[UITableView alloc] ...]
then there is one automatically set for me.
This would be fine for me... I don't need to init one, but I can't change the frame on the standard one.
tableView.frame = CGRectMake(0, toolbarHeight, CGRectGetWidth(mainViewBounds), CGRectGetHeight(mainViewBounds) - toolbarHeight);
Setting frame has no effect whatsoever...

i Had the same issue you probably be converting the UITableViewController to UIViewController and Your RootViewController might have the uitableview.
Make the Property of _tableview in your RootviewController with IBOutlet. And link it with the tableview in your XIB .
Don't alloc _tableview in RootviewController and Don't addsubview it .

Instead of this,
[tableView tableView].delegate = self;
[tableView tableView].dataSource = self;
Have you tried just using:
tableView.delegate = self;
tableView.dataSource = self;
I don't know why it would be that, but it's the only thing that's standing out. Also make sure you haven't got another UITableView set up in IB.
It might also have something to do with toolbarController.
I'm assuming it's a custom class, so make sure you're not creating a UITableView in that.

I ran into same issue...
Instead of adding tableview to the view controller directly ([self.parentViewController.view addSubview:tableView];), use following way..
UIView *totalView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[totalView addSubview:tableView];
self.view=totalView;
Hope this fixes it (for #kris too!)

Related

App freeze when I remove [super loadView]

When I remove the [super loadView]; the view wont display. The superclass is UIViewController.
- (void)loadView
{
[super loadView];
UITableView *tableview = [[UITableView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 367.0f) style:UITableViewStylePlain];
tableview.dataSource = self;
tableview.delegate = self;
self.tableView = tableview;
[tableview release];
[self.view addSubview:self.tableView];
}
Any idea why? Thanks in advance!
1) UIViewController Class Reference, loadView section
Your custom implementation of this method should not call super.
2) You have to set view property to something. After all this method is called loadView :). Instead of [self.view addSubview:self.tableView]; try
self.view = tableView;
If you look at the view programming guide, it mentions that if you override [loadView], you should construct your own view.
default loadView will look at bunch of stuff, like load from nib first, then construct normal view.
So, just construct a view, and assign it to self.view -
UIView *view = [[UIView alloc] initWithFrame ...];
self.view = view;
[view release];
then it should be fine.
edit: example with your code:
- (void)loadView
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 367.0f)];
self.view = view;
[view release];
UITableView *tableview = [[UITableView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 367.0f) style:UITableViewStylePlain];
tableview.dataSource = self;
tableview.delegate = self;
self.tableView = tableview;
[tableview release];
[self.view addSubview:self.tableView];
}
edit2: link to viewcontroller programming guide:
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/BasicViewControllers/BasicViewControllers.html#//apple_ref/doc/uid/TP40007457-CH101-SW1
Look at custom view controller section, Creating the View Programmatically, and few other places in that doc.
I think you wanna move that [ tableview release ] after the addSubview.
This is because you never assign the view property in the code. When in the last line you access the view property, it causes -loadView to be called again, which results in a endless loop.

Trying to base some code off of Apple's Image Zooming App example, missing some simple Interface Builder knowledge

I'm trying to base part of my app off of Apple's Image Zooming example, to get zooming, scrolling, and orientation of images that are saved to the app's sandbox.
http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/UIScrollView_pg/Introduction/Introduction.html
I have it sort of working now, except that when the ScrollView loads, it's blank. The code looks something like this:
#interface PhotoViewController : UIViewController <UIScrollViewDelegate> {
UIScrollView *imageScrollView;
UIImageView *imageView;
}
#property (nonatomic, retain) IBOutlet UIScrollView *imageScrollView;
#property (nonatomic, retain) UIImageView *imageView;
#end
#implementation PhotoViewController
#synthesize imageView, imageScrollView;
- (void)viewDidLoad {
[super viewDidLoad];
imageScrollView.bouncesZoom = YES;
imageScrollView.delegate = self;
imageScrollView.clipsToBounds = YES;
imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"image1.jpg"]];
imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.backgroundColor = [UIColor blackColor];
imageView.userInteractionEnabled = YES;
[imageScrollView addSubview:imageView];
imageScrollView.contentSize = [imageView frame].size;
}
The xib has a Photo View Controller->Scroll View->View structure. I have a feeling this is where the problem is. I tried to hook up all the outlets identically to the example, but under Referencing Outlets the example has a viewController hooked up to the ImageZoomingAppDelegate. Since my PhotoViewController is a subview, there's not a place to hook up the viewController like that.
Here's how I bring up the PhotoViewController:
(IBAction) photoButtonPressed: (id) sender {
viewController = [[PhotoViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
}
I know I must be just "this close" to having it all hooked up right, but I don't understand the relationship of the xib to the code well enough to know how to debug it. I'm not even sure if I know enough to ask the right questions.
Try changing viewController = [[PhotoViewController alloc] init]; to
viewController = [[PhotoViewController alloc] initWithNibName:#"PhotoViewController" bundle:nil];
(of course change the text string to whatever you called your xib file).

How to programmatically create UIView -> UIViewController -> UITableView

I've been struggling to add a UIView above my UITableViewController. Through searches, reading and experimenting I've determined that instead of a UITableViewController I should just be using a UIViewController. I'm having a hard time making this work for a variety of reasons and I'd like to just start fresh with a better architecture.
Basically I'm looking for sample code / tutorials that could help me create the following completely programmatically (no NIBS):
- Navigation-based Layout
- UIViewController
-- UIView
--- UITableView
--- Etc.
The reason why I want a UIView above my UITableView is I want to be able to add UIViews above my table.
-UPDATE-
Adding code to make this more clear:
JMoviesListViewController.m - UITableViewController subclass
- (void)loadView
{
NSLog(#"loadView called");
UIView *baseView = [[[UIView alloc] init] autorelease];
TISwipeableTableView * aTableView = [[[TISwipeableTableView alloc] init] autorelease];
[aTableView setDelegate:self];
[aTableView setDataSource:self];
[aTableView setSwipeDelegate:self];
[aTableView setRowHeight:54];
[baseView addSubview:aTableView];
self.view = baseView;
[super loadView];
}
- (void)viewDidLoad {
listOfMovies = [[NSMutableArray alloc] init];
UIView *myProgView = (UIView *)self.progView; // progView is a method that returns a UIView
[self.view insertSubview:myProgView aboveSubview:self.tableView];
[self.navigationItem setTitle:#"Now Playing"];
movies = [[Movies alloc] init];
movies.delegate = self;
[movies getMovies:[NSURL URLWithString:apiQuery]];
[super viewDidLoad];
}
- (UIView *)progView {
if (progView == nil)
{
// create a progress view
//x,y,w,h
progView = [[UIView alloc] initWithFrame:CGRectMake(110, 110, 95, 30)];
progView.backgroundColor = [UIColor grayColor];
progView.tag = 1; // tag this view for later so we can remove it from recycled table cells
progView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin);
progView.layer.cornerRadius = 5;
UILabel *activityLabel = [[UILabel alloc] init];
activityLabel.text = NSLocalizedString(#"Loading...", #"string1");
activityLabel.backgroundColor = [UIColor grayColor];
activityLabel.textColor = [UIColor whiteColor];
activityLabel.font = [UIFont systemFontOfSize:14];
[progView addSubview:activityLabel];
activityLabel.frame = CGRectMake(5, 2, 70, 25);
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[activityIndicator startAnimating];
[progView addSubview:activityIndicator];
activityIndicator.frame = CGRectMake(70, 5, 20, 20);
}
return progView;
}
To be clear, the code works fine, the problem is that the cell lines of the table are "bleeding through" the UIView spinner that is inserted with this line:
[self.view insertSubview:myProgView aboveSubview:self.tableView];
leading me to believe that myProgView is not aboveSubview:self.tableView.
Views and controllers are separate things. You can have a hierarchy of view controllers and a hierarchy of views. But they're not interleaved, as the title of posts suggests (I know, Interface Builder displays them as a single hierarchy, but views and controllers are more like two parallel hierarchies).
Anyway, you can easily have a view controller set up whatever views you want in code. Override the loadView method, create a view that you assign to self.view, then add subviews to that view.
For example:
- (void)loadView
{
UIView *view = [[[UIView alloc] init] autorelease];
UITableView *tableView = [[[UITableView alloc] init] autorelease];
tableView.dataSource = self;
tableView.delegate = self;
[view addSubview:tableView];
self.view = view;
}
Your view controller should either inherit UITableViewController or implement the UITableViewDataSource and UITableViewDelegate protocols.
You have to actually specify the layout of your different views, not just add them as subviews. Try reading a tutorial about using AutoLayout programmatically.
You also want to set up all your views in loadView. There you can set the bottom of your extra view to the top of your table view.
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view = [[[UIView alloc] initwithFrame:CGRectMake(set your frame)] autorelease];
UITableView *tableView = [[[UITableView alloc] initwithFrame:CGRectMake(set your frame)] autorelease];
tableView.dataSource = self;
tableView.delegate = self;
[view addSubview:tableView];
}
if you are using **ARC** remove autorelease.

Creating a UITableViewController programmatically

This is what I tried. Nothing appears on the screen and none of the UITableView methods that you are supposed to implement are getting called.
-(void)loadView
{
UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view = view;
[view release];
}
- (void)viewDidLoad
{
[super viewDidLoad];
UITableViewController *TVC = [[[UITableViewController alloc]
initWithStyle:UITableViewStylePlain] autorelease];
CGRect cgRct = CGRectMake(0, 10, 320, 100);
UIView *newView = [[UIView alloc] initWithFrame:cgRct];
TVC.view = newView;
[newView release];
[self.view addSubview:TVC.view];
}
I've looked for good examples and tutorials on doing this programmatically but there are none.
What I am trying to achieve is a Table that doenst take up my who screen. Maybe 3/4 of my screen would be good.
Many Thanks
Code
The problem is that you're creating a UITableViewController, which is a UIViewController, and will expect to be on the nav stack. What you want to do is create a UITableView, which is a UIView. You are also not setting the table's delegate and data source, which you will need to do to get calbacks.
Your viewDidLoad should look something like this
- (void)viewDidLoad
{
[super viewDidLoad];
UITableView *table = [[[UITableView alloc] initWithStyle:UITableViewStylePlain] autorelease];
table.dataSource = self;
table.delegate = self;
table.frame = CGRectMake(0, 10, 320, 100);
[self.view addSubview:table];
}
(Note that if you're going to need access to the table outside of the callbacks, you should save it in an ivar rather than declaring it locally, and should retain it. Let me know if you need a few more lines of code to show you what I mean)
Make sure you set the delegate of TVC, with
TVC.delegate = self;
That's the reason why none of those methods are getting called. Also, make sure your class implements the UITableViewDelegate protocol by changing your interface declaration to
#interface YourViewController : UIViewController <UITableViewDelegate> {
//declare variables here
}
Also, equally important, don't set TVC.view, as this already happens when you initialize the view controller. You're just setting it to a blank view, which is why you're not seeing anything.
iOS7 seems to like this way of init'ing the tableview:
//make tableview
UITableView *table = [[UITableView alloc] initWithFrame:CGRectMake(0, 81, 200, 200) style:UITableViewStylePlain];
table.dataSource = self;
table.delegate = self;
[self.dataView addSubview:table];
try that out. Hope it helps someone.
UIView *newView = [[UIView alloc] initWithFrame:cgRct];
TVC.view = newView;
I'll give you a hint. Here you are setting the view of the UITableViewController to an EMPTY VIEW...

iPhone UITableView PlainStyle with custom background image - done "entirely" in code

I have been all over the place, seems the UITableView with a static background issue is well documented, but no one with a straight forward solution?
Im building my TableViews entirely in code, like this:
UIViewController *tableViewController = [[TableViewController alloc] init];
navigationController = [[UINavigationController alloc]
initWithRootViewController:tableViewController];
[tableViewController release];
[window addSubview:navigationController.view];
The window is my main UIWindow build for me in the app delegate. From here on I need to build a few different TableViews (controlled by the navigationController), some with fetchedResultsControllers, custom cells and so on. I prefer to do this completely in code, not using nib's as this would result in either having customization spread between code and IB or having to build and maintain 6+ different Nibs.
I simply can't find a working example where a tableViewController Class sets it's own background image. If I do this inside one of my TableViews (extending UITableViewController):
self.tableView.backgroundColor = backgroundColor;
I, of course, get the tableView's background colored (which incidentally colors the cell's as well, think the cell's inherits their color from the tableView?) but I wish to have a static background image that my cells slide up and down on top of. Not a "background image" that slides up and down with the users gestures.
Exactly what the GroupedStyle tableView offers, but in a PlainStyle tableView:) .. and done using code, not IB.
I guess I have to clear the background color of the table view, then set the Cells color when configuring them so they don't turn out transparent. And then somehow "sneak" a background image below the tableView view from inside the tableView instance?
How will I go about this, the best solution would to be able to do this in viewDidLoad or any other function inside my TableViewController, to keep all my customization in one place.
Hope someone can help me, Im all 'googled out' :) Thanks!
You need to set up your controller as a UIViewController, not a UITableViewController. Then add the tableview programmatically above a background imageView.
#interface SomeController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
...
UITableView *tableView;
...
}
#property (nonatomic, retain) UITableView *tableView;
#end
#implementation SomeController
#synthesize tableView;
...
- (void)loadView {
[super loadView];
UIImageView *v = [[[UIImageView alloc] initWithFrame:self.view.bounds] autorelease];
[v setImage:[UIImage imageNamed:#"table_background.png"]];
[self.view addSubview:v];
self.tableView = [[[UITableView alloc] initWithFrame:self.view.bounds] autorelease];
[self.tableView setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:self.tableView];
}
...
#end
All of this jumping through hoops is unnecessary if you're targeting > iOS 3.2, where you can use the new backgroundView property to set a UIImageView directly, e.g.:
// In your UITableViewController subclass
- (void)viewDidLoad
{
[super viewDidLoad];
UIImageView *view = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
self.tableView.backgroundView = view;
}
Ok, now it is running:)
My tableView was not populated with my cells, so breakPointing through the thing I found out
that even though I had implemented the TableViewDataSource and TableViewDelegate, this was only in the main view, I needed to set the delegate and datasource of the tableview to = self.
For others seeking an answer to this here is the method as it ended up with Coneybeares help:
- (void)loadView {
[super loadView];
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:self.view.bounds] autorelease];
[imageView setImage:[UIImage imageNamed:#"carbon_background.png"]];
[self.view addSubview:imageView];
[self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds] autorelease];
[self.tableView setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:self.tableView];
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
Thanks Coneybeare.
It doesn't crash anymore and the background image turns up just perfect (along with my navigationController in the top)
However, still no visible tableView? just the background image and the navigationControllerBar:
This is my implementation:
- (void)loadView {
[super loadView];
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:self.view.bounds] autorelease];
[imageView setImage:[UIImage imageNamed:#"carbon_background.png"]];
[self.view addSubview:imageView];
[self.tableView = [[UIView alloc] initWithFrame:self.view.bounds] autorelease];
[self.tableView setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:self.tableView];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = #"Hello, World";
return cell;
}
//commit edit, didSelectRow, memory … etc.
The forum wasn't up for an entire .m file in one go.
Please tell me if I left something out that could help indicate an error.
I thought maybe it was the order of the layers and tried this without any luck:
[self.view sendSubviewToBack:imageView];
Hope I missed something obvious.
Thanks for your time:)
Some tips:
If using a UISplitViewController:
splitViewController.view.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
If using a UINavigationController:
navigationController.view.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
If using both a UISplitViewController and a UINavigationController:
navigationController.view.backgroundColor = [UIColor clearColor];
splitViewController.view.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
Be sure to set the background color of any UIView you want to see through that is on top of the UINavigationController or UISplitViewController to [UIColor clearColor].