didSelectRowAtIndexPath not called. UITableViewController subclassed - iphone

Tried programming more in an OO manner.
NOTE:
Seems the problem is related to having a UITableView(which is a type of scrollview) ontop of another UIScrollView. Trying to get clarification on how to make this work.
So i made a UITableViewController subclass and add that as an object in my Mainview class.
#interface NRTableVC : UITableViewController <UITableViewDelegate, UITableViewDataSource>
{
NSArray * tableLabelsArray;
}
#end
The table scrolls and displays OK.
But my
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Did select row");
}
method never gets called.
in my Mainview class I use it as follows
RTable = [[[NRTableVC alloc] initWithStyle:UITableViewStylePlain]autorelease];
[scrollview addSubview:RTable.view];
I was wondering so I need to somehow set self as the delegate or something like that.
Anybody able to give me some hints as to what is wrong?
Many Thanks,
Code

Have you set delegate for tableview? Without delegate set it won't call any delegate methods.

What I usually do is, in the View I want the tableview is create an instance
I do this in ViewDidLoad or the LoadView methods
UITableView *tableView = [UITableView alloc] init...
tableView.delegate = self;
tableView.datasource = self;
Then I add it as a subview of the current view.
This means your MainView needs to implement the tableView datasource and delegate methods.
Edit:
If you use interface builder, remember to drag the datasource and delegates to the fileowner

Is anything retaining RTable? You're autoreleasing it but you don't show any code that indicates it's being retained anywhere.

Related

Converting UIView to UITableView

I've done this before but I have no idea what I'm missing.
I started the project as a single View project.
Then converted the ViewController to inherit from UITableViewController like so:
#interface ViewController : UITableViewController
went into the .xib for this ViewController and changed the class in the Custom Class section form UIView to UITableView:
Looking in my other project(s) where the ViewControllers are just straight TableView controllers, I don't see what else needs to be done, but when I run the app or when I view the xib it's not showing a tableview.
You'll need to drag out a UITableView in Interface Builder to replace the UIView. Then add the UITableViewDataSource and UITableViewDelegate protocols to your view controllers header file and connect the datasource and delegate outlets from your UITableView to your view controller in Interface Builder.
#interface ViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>
add delegate & dataSource. i think you are forgotten to add delegates &dataSource thats why its not showing table. add following lines to your viewDidLoad().
self.myTableView.dataSource = self;
self.myTableView.delegate = self;
after this also implements the required methods of delegate, that are
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return
10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//your code for cell data
}
What init method are you using in the .m file. You need to use the
[[UITableViewController alloc] initWithStyle:UITableViewStylePlain]
allocation method and make sure you have included the<UITableViewDataSource, UITableViewDelegate> and the relevant datasource and delegate methods.
Ok,
basically, if you want to just have a UITableViewController from scratch without having to manually do the above, just create a new Obj-C class, have it inherit from UITableViewController, and select to create a xib, and it will give you a viewcontroller and view already wired to working with a UITableView:

Reload UITableView not functioning in IOS5

The UITableview reloadData function is not calling the cellforRowAtIndexPath method. Following things I had tried:
Call [self.myTableView reloadData];
call reloadData method on ViewWillAppear too.
written self.myTableView.delegate=self; and self.myTableView.datasource=self too.
Also I have test using NSLog that number of rows are updating properly.
Data source and delegate are connected in storyboard.
I guess you haven't declared delegate in your .h file.
Example.
#interface ClassName:UIViewController <UITableViewDelegate>
Does your view conform to UITableViewDelegate and UITableViewDatasource?
And does it at least implement all of the required methods in those protocols? also, there's no need to say self.myTableView, you could just say myTableView if you're working inside of the class.
And it sounds silly, but did you forget to save your storyboard? I've done that on more than one occasion.
Did you implement the method?
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1; //Return the number of sections you want
}
It's easy to forget, since by default it returns 0.
If you don't do it the tableview thinks it has no sections and does not ask for any row.
Make sure you set the table view's delegate:
tableView.delegate = _an_object_that_conforms_to_UITableViewDelegate_;
This is normally the view controller in which you've declared the table view so you would have:
tableView.delegate = self;
Just make sure the view controller that contains the table view and acts as it's delegate declares itself as an UITableViewDelegate:
#class MyViewController <UITableViewDelegate> {
UITableView *tableView;
...

adding a UITableView programmatically to a UIViewController

I'm loading a UIViewController into one of my Nav controller's hierarchies, which will contain some text and some images. At the bottom, I will want to create a expandable and collapsable tableview.
First off, is this idea possible? If it is, how do I add it and where do I place the data source and delegate methods?
Can I just make a separate subclass of the TableViewController and then add it to my ViewController as a subview?
Yes, you can create a UITableView whose delegate, datasource, and parent view are not necessarily a UITableViewController. Since the UITableView is a UIView, you can add it as a subview of any other UIView. Any NSObject can be the delegate or datasource, as long as you implement the required protocol methods.
#interface MyViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
In fact, in my experience, not many people even use UITableViewControllers. When was the last time you wanted your table view to take up the entire usable space? In general, I create a plain old UIViewController and add a UITableView as a subview of its view, in addition to other subviews.
/************************************************/
/************* MyCustomController.m *************/
/************************************************/
#interface MyCustomController () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UITableView *tableView;
#end
#implementation MyCustomController
- (id)initWithNibName:(NSString*)nibName bundle:(NSString*)bundleName
{
self = [super initWitNibName:nibName bundle:bundleName];
if (self)
{
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.datasource = self;
tableView.delegate = self;
[self.view addSubview:self.tableView];
}
return self;
}
#pragma mark - UITableViewDataSource Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// return number of rows
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// return cell
}
#pragma mark - UITableViewDelegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// handle table view selection
}
#end
It's pretty easy, in something like your viewDidLoad method:
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:tableView];
Just remember that a UITableViewController is a subclass of UIViewController only with the tableview set as the controller's view.
So yes definitely possible and used quite frequently when you want to have a tableview but also other custom UI elements which prevent you from using the UITableViewController.
I'd normally choose to add it to my view controller's view in either its initialisation method or viewDidLoad method. This will vary based on whether you're creating your views from a NIB or entirely programatically.
In case of NIBs:
- (id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)bundleName
{
if ((self = [super initWitNibName:nibName bundle:bundleName]))
{
self.theTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewWhateverStyleYouWantHere];
theTableView.dataSource = self, theTableView.delegate = self;
[self.view addSubview:theTableView];
[theTableView release];
}
}
And then you can set the frame of your tableview in your viewDidLoad method.
I'd personally prefer to do the whole thing in interface builder as you'd achieve the same result with way less code to maintain.
If you're like me and already had created a UITableViewController and then realizing that you did so much work on it that re-writing it would be a pain, you can just do the following to add the UITableViewController to the UIViewController as a subview.
UITableViewController* tableViewController = [[UITableViewController alloc] init];
[self.view addSubview:tableViewController.tableView];
All the other answers above works great. I figure I'd add to this for those that have a heavily invested implementation of a UITableViewController and feel like refactoring would be a pain.

didSelectRowAtIndexPath not get called

I have a UITableView inside a UIViewController like so:
.h
#interface OutageListViewController : UIViewController<UITableViewDelegate,UITableViewDataSource> {
IBOutlet UITableView *outageTable;
.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Selected");
}
I have customized table cell:
//EDIT
I have fire UILabel side by side on my customized view, as well as a background spreading the entire area. But after resizing/removing the background image and label I putted on the customized cell, "didSelectRowAtIndexPath" is still not being called.
//END EDIT
#interface AbstractSummaryListViewCell : UITableViewCell {...}
and
#interface FiveColumnSummaryCell : AbstractSummaryListViewCell {...}
This UIView is inside another UIView:
#interface CustomTabBarController : UIViewController {
OutageListViewController *outageListViewController;
And my AppDelegate add this to the window:
[window addSubview:[customTabBarController view]];
Now I'm trying to determine which cell get clicked and didSelectRowAtIndexPath doesn't get called, I have dataSource and delegate connect from the UITableView to File's Owner, in fact the data populates correctly as my "cellForRowAtIndexPath" specifies, any ideas how can I fix this?
Thanks!
I solved it: forgot to check User Interaction Enabled in my customized cell xib. What a fool!
Are the following properties of UITableView all YES?
allowsSelection
allowsSelectionDuringEditing
Edit:
I think Paul is right. The delegate property has some problem. You can check the delegate property of tableView inside -(void)viewDidLoad. As you said, they should be connected to FileOwner in xib. So the following codes won't obtain nil.
- (void)viewDidLoad {
[super viewDidLoad];
// They should not be nil.
NSLog(#"delegate:%# dataSource:%#", self.tableView.delegate, self.tableView.dataSource);
}
It's possible that the view controller has not been connected to the delegate property of the outageTable anywhere.
You can make a quick test... Remove the "big" label and see if the didSelectRowAtIndexPath is called.

iphone - access uitableviewcontroller from uitableviewcell

I have a structure like this....
UITableViewController -> UITableViewCell -> UIView
I need the UIView to access a HashTable (NSMutableDictionary) in the UITableViewController
Is there a way to access the ViewController simply from the ViewCell (using [ViewCell superview] obviously won't work) ....Do I need to go down through the AppDelegate using [[UIApplication sharedApplication] delegate]?
Thanks!
This should do the trick:
UITableView *tv = (UITableView *) self.superview.superview;
UITableViewController *vc = (UITableViewController *) tv.dataSource;
I usually maintain a weak reference from my UIView to my UIViewController if I need one, usually by creating a method something like this:
-(MyView*)initWithController:(CardCreatorViewController*) aController andFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
{
controller = aController;
// more initialisation here
}
return self;
}
You could also use a delegate pattern if you want a more decoupled solution. I tend to think this is overkill for a view and its controller, but I would use it with a system of controllers and subcontrollers.
You can create a category for this:
#implementation UITableViewCell (FindTableViewController)
- (id<UITableViewDataSource>)tableViewController
{
UIView *view = self;
while (!(view == nil || [view isKindOfClass:[UITableView class]])) {
view = view.superview;
}
return ((UITableView *)view).dataSource;
}
#end
Then you can simply access self.tableViewController from the cell itself (assuming you have included this category). You may need to cast it to your table view controller's class tho.
Since the UITableViewCell is somewhere in the view hierarchy, you can access your root view by retrieving view.superview until you get it. If you don't want to add any properties to your view, you can access its controller through the view's nextResponder property. You would have to cast it to whatever class you need, of course, and it may not be the cleanest use of the property. It's a quick-n-dirty hack to get to it.
If you're looking for something you can show your children though, I'd aim for going through your app delegate, or if your view controller happens to be a singleton, just implement the singleton design pattern and access it through that.
Some modification from Kare Morstol answer :
The hierarchy of tableviewcell is in iOS 5.0(my test version)
cell.superview = tableview
cell.superview.superview = UIViewControllerWrapperView
So, use cell.superview to get tableview. And the tableview and tableviewController has a relation of delegate, dataSource in default.
You can get tableviewController reference by tableview.delegate or tableview.dataSource.
UITableView *tableView = cell.superview;
UITableViewController *tableViewController = tableView.delegate; // or tableView.dataSource`