UITableViewController subclass with storyboard - iphone

I have a UITableViewController subclass that I want to use in conjunction with storyboards in order to set a custom background view. My subclass overrides the init method like so:
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.tableView.backgroundColor = [UIColor clearColor];
self.tableView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:iPhone568ImageNamed(#"background.png")]];
}
return self;
}
Now when I try and instantiate a new tableview controller (this is interface definition):
#interface AVSelectTableViewController : AVCustomTableViewController
The init method is crashing on any call to self.tableView. Everything looks connected in storyboard (table datasource and delegate points to AVSelectTableViewController parent).
Reading the docs it appears that perhaps the tableView property isn't being set correctly (it just returns the tableview managed by a controller); however I'm not sure how to access it. Any thoughts?

Use awakeFromNib instead of initWithCoder

Related

How to make UIViewController's view inherit from another UIView?

I have one UIViewController without NIB file. Now i have one my customized UIView. I want to make UIViewController's view inherit from my customized UIView, is it possible ? I know that if I have XIB file than I can make Custom Class from there but without XIB can it be done?
Thanks in Advance
If you are using a UIViewController subclass, and don't want to use a nib file, then override the loadView method in your subclass:
#implementation MyViewController
- (void)loadView {
self.view = [[MyView alloc] init];
// additional view setup here
}
If you are just using a generic UIViewController (not a subclass), then you might be able to just assign to the view controller's view property, like this:
vc.view = [[MyView alloc] init];
But I'm not sure if that works properly outside of loadView. I haven't seen any documentation that says it is or is not allowed.
Replace your view controller's view like this:
// ViewController.m, in viewDidLoad
self.view = [[MyCustomView alloc] initWithFrame:self.view.bounds];
A more conventional alternative is to fill the default view with the custom subview, like this:
MyCustomView *myCustomView = [[MyCustomView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:myCustomView];
I think you need to load a custom view programmatically, for that you need to override the loadView method of your view controller.
-(void)loadView
{
[super loadView];
CustomView *view = [[CustomView alloc]initWithFrame:self.view.bouds];
[self.view addSubview:view];
}
Replace this in your .h file
#interface ViewController : UIViewController
with
#interface ViewController : Customized View Controller

iPhone SDK - Adding a static image over a UITableViewController

I am trying to add a static fixed image to a UITableViewController, but when I do the standard [self.view addSubview:imageView]; the image is placed on the tableview and moves with the scrolling.
Is there any way to do this so that the image stays fixed?
I know one method would be to create a UIViewController, then add the UIImageView and a UITableView, but unfortunately, I am using a custom UITableViewController (just a library found on gihub to do what I needed), so my controller must be a UITableViewController.
Is there any way to do this? I've been going at this for a while with no luck.
Cheers,
Brett
There is no problem using UIViewController idea. You just keep 2 view controllers: 1) UIViewController, which has the UIImageView inside, and subview the view of 2) the UITableViewController. If necessary, make the UITableViewController a strong reference of the UIViewController.
I have done something similar all the time.
Yes, there are few ways. You could create your view hierarchy programmatically at
viewDidLoad or use a NIB file. Make sure that you correctly link the delegates and view properties.
If a nib file is specified via the initWithNibName:bundle: method (which is declared by the superclass UIViewController), UITableViewController loads the table view archived in the nib file. Otherwise, it creates an unconfigured UITableView object with the correct dimensions and autoresize mask. You can access this view through the tableView property.
If a nib file containing the table view is loaded, the data source and delegate become those objects defined in the nib file (if any). If no nib file is specified or if the nib file defines no data source or delegate, UITableViewController sets the data source and the delegate of the table view to self.
As https://stackoverflow.com/a/6961973/127493 say, UITableViewControllers can be replaced by simple UIViewControllers.
In fact, the trick is to add an UITableView to you UIViewController, make it delegate and etc..., and add it to your UIViewController.view.
So you will be able to add some "sister" views to your controller main view.
In my case, I am adding a an Image ( actually button with image) and when user touches on image, it will disappear and tableview will be shown.
so i am disabling scroll first then enable it back
find code below
// in viewDidLoad
[self.view addSubview:imgview];
tbl.scrollEnabled = NO;
// in -(IBAction)btnClicked:(id)sender
[imgview removeFromSuperview];
tbl.scrollEnabled = YES;
Thats working for me.
Do NOT use UITableViewController at all (I never use it and as I've heard nearly any developer uses it). It is a nightmare when you want to customize design with it.
Create your own subclass of UIViewController (MYTableViewController), add UITableView *tableView instance #property and #synthetize it:
#interface MYTableViewController : UIViewController <UITableViewDelegate,UITableViewDataSource> {
UITableView *tableView;
}
#property (nonatomic, retain) IBOutlet UITableView *tableView;
#end
Then in implementation add it to the view (using XIB or viewDidLoad method):
#implementation MYTableViewController
#synthesize tableView;
// If not XIB used:
-(void)viewDidLoad{
[super viewDidLoad];
CGRect frame = self.view.bounds;
self.tableView = [[[UITableView alloc] initWithFrame:frame style:UITableViewStylePlain] autorelease];
tableView.dataSource = self;
tableView.delegate = self;
[self.view addSubview:tableView];
// And here you van add your image:
[self.view addSubview:imageView];
}
// Do not forget to release it and clear delegate and datasourcce when view uloads:
#pragma mark - Memory management:
-(void)dealloc{
self.tableView.delegate = nil;
self.tableView.dataSource = nil;
self.tableView = nil;
[super dealloc];
}
- (void)didReceiveMemoryWarning {
self.tableView.delegate = nil;
self.tableView.dataSource = nil;
self.tableView = nil;
[super didReceiveMemoryWarning];
}
-(void)viewDidUnload{
self.tableView.delegate = nil;
self.tableView.dataSource = nil;
self.tableView = nil;
[super viewDidUnload];
}
#end

ViewDidLoad method in UIViewController - when does it get called?

I have a UIViewController called LaunchController that is launched in my iPhone app when the app first opens:
#interface LaunchController : UIViewController<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
Then, when a button is clicked, I push another view controller:
MainController *c = [[MainController alloc] initWithImage:image];
[self presentModalViewController:c animated:NO];
MainController has the following constructor, which I use:
- (id)initWithImage:(UIImage *)img
{
self = [super init];
if (self) {
image = img;
NSLog(#"inited the image");
}
return self;
}
and then it has a viewDidLoad method as follows:
- (void)viewDidLoad
{
NSLog(#"calling view did load");
[super viewDidLoad];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:imageView];
NSLog(#"displaying main controller");
}
When the program runs, I see that the constructor for MainController is called (due to the output of NSLog), however viewDidLoad never gets called, even though I am calling presentModalViewController. Why is this? Why isn't viewDidLoad being called?
I think it is something as followings. When you need the property of view inside UIViewController, it will be loaded with lazy manner.
- (UIView *)view
{
if (_view == nil) {
[self loadView]; //< or, the view is loaded from xib, or something else.
[self viewDidLoad];
}
return _view;
}
After the view initialized, it will call viewDidLoad to inform the UIViewController.
You aren't loading your view controller from a xib file, and from comments you don't have anything in loadView (which is where you would create your view controller's view if you were not using a xib file).
Therefore, your view isn't being loaded, so viewDidLoad is never called.
Typically you would use initWithNibName: to initialise a new view controller, and then set the image after it (so expose the image as a property).
viewDidLoad will be called as soon as your controller's view property is accessed, that is when you display it for the first time or request it (e.g. have some code that calls c.view.
The reason viewDidLoad is not being called is because you aren't loading a view.
In your init method:
self = [super init];
means that you are just creating a naked view from scratch. not loading one from a nib.
try this instead:
self = [super initWithNibName:nil bundle:nil];
If you have a xib or nib file with the same name as the view controller class it should find if. Otherwise, you can just give a nibName that works.
UPDATE:
If you are not using nib files, then the appropriate method is NOT viewDidLoad. You have to implement loadView instead of viewDidLoad.
In your specific case, just put everything that is currently in viewDidLoad into loadView.

When to keep a reference to a UITableView

This is probably a dumb question but I'm just learning. If I have a method that creates a UITableView in code when a button is pressed like this
UITableViewcontroller *contentView = [[UITableViewController alloc] initWithSytyle:UITableViewStylePlain];
contentView.tableView.delegate = self;
contentView.tableView.datasource = self;
[contentView release];
In the UITableView delegate and datasource methods, how do I check if it is this tableView or another TableView? Do I have to have to have an instance variable for this tableView that always points to it for those delegate and datasource methods? Thanks.
You can use tag property. In your code
UITableViewcontroller *contentView = [[UITableViewController alloc] initWithSytyle:UITableViewStylePlain];
contentView.tag == 10;//add this line in your code
contentView.tableView.delegate = self;
contentView.tableView.datasource = self;
[contentView release];
then in your delegate method or datasource methods check
if(view.tag == 10)
{
//do stuff
}
Typically, you’d put the datasource and delegate methods in the table view, not the table view’s parent. That way you could separate the logic for each table view into its own view controller. But, if you must put them all in one class, you can use the tag property of the table view to keep track of which is which.

how to associate uicontroller to custom uiview programmatically

I have a custom UIview which is created programmatically. How to associate to it a custom UIViewController (programmatically as well)
Thanks and regards,
Implement loadView in the UIViewController to create a view hierarchy programmatically without a nib file.
- (void)loadView {
// allocate the subclassed UIView, and set it as the UIViewController's main view
self.view = [[[UIViewSubclass alloc] initWithFrame:CGRectMake(0, 0, 320, 460)] autorelease];
}
You can continue setting up the view/subview hierarchy in two ways. One is to add them in the custom UIView's initialization method, like so:
// in the MyView.m file
- (id)initWithFrame:(CGRect)f {
if (self = [super initWithFrame:f]) {
// add subviews here
}
return self;
}
The second way is to continue using the loadView method implemented in the UIViewController subclass, and just using [self.view addSubview:anotherView]. (Alternatively, use the viewDidLoad method in the UIViewController subclass.)
Note: Replace initWithFrame: with whatever the custom UIView's initialization method is (e.g., initWithDelegate:).
Say the view you created is called newView and the controller is newController. The simple approach would be:
newController.view = newView;
But I'd rather subclass UIViewController and override its - (void)loadView and - (void)viewDidLoad methods and create and/or manipulate the view there - that's the way Apple wants you to do it, and for good reason.