I know how to connect the datasource of a TableView in a Sotryboard, but not in a xib. I connect the datasource of my table with the viewController, and when I run it I get a SIGABRT. Is it enough? Do I have to write some code for the xib?
In .h file of your class adopt TableView protocols like this.
#interface EditProject : UIViewController<UITableViewDataSource, UITableViewDelegate>
When you connect datasource,delegate of UITableView at run time it will try to find these delegate and datasource methods if you have not written them then your application will crash.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//datasource method.
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//delegate method.
}
In .xib you do like this. Right Click on UITableView Controller and connect datasource and delegate to File's Owner.
Implement a class the follows the UITableViewDataSource Protocol, and provide the data via the protocol methods.
Related
I have a UITableView and it contains a custom UITableViewCell. To test, I have an array that has three strings in it. The UITableView delegate methods are called as expected, however, the tableView:cellForRowAtIndexPath delegate is always passed an NSIndexPath instance whose row property is always == nil:
tableView:cellForRowAtIndexPath is called 3 times (once for each object in my array). I added the tableView from within the designer (storyboard) and created an outlet for it. The UITableViewCell instances appear to be correctly instantiated which each call to this delegate. I just can't wrap my head around why the [indexPath row] value is always nil.
Interface(s):
In the implmentation file:
#interface FirstViewController ()
#property(nonatomic, strong)AppDelegate *sharedDelegate;
#property(nonatomic, strong)NSArray *userList;
#end
In the header:
#interface FirstViewController : UITableViewController <FacebookDelegate>
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#end
Init the custom cell:
-(void)viewDidLoad
{
[self.tableView registerClass: [ListCategoryCell class]forCellReuseIdentifier:#"ListCategoryCell"];
self.userList = #[#"d", #"g", #"f"]; // make some test data
}
And the delegate this is driving me mad:
//NSIndexPath.row is nil ?!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"ListCategoryCell";
ListCategoryCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = (ListCategoryCell *)[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
}
cell.titleLabel.text = [self.userList objectAtIndex:[indexPath row]];
cell.detailLabel.text = #"Detail";
return cell;
}
Am I missing something? Thanks!
Working Now
I left out some context (and I should not have) that I believe was very relevant to my problem. I created a UIViewController originally and then added a UITableView to this as the view. In the UITableView I created a custom prototype cell. I did all the house work:
UIViewController implemented the UITableViewDelegate & UITableViewDatasource.
Created and outlet for the UITableView.
Hooked up all the outlets
Everything seemed to work except for the fact that indextPath.row property was always nil. Some resources I found suggested that custom cells were not visible before the uitableview delegates were called.
In the end I made my class a subclass of UITableViewController. Things started working. I am still curious why my original attempt was failing.
Thanks for everyone's time. Some great comments helped me investigate some topics that are "good to know".
You need to provide at least two methods in view controller if you want it to manage your table view. They are:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
You've already provided the second, so your table view actually can produce cells but it doesn't know how many.The default value the first method returns is nil.That is the reason why you don't even have an index path.
Optionally:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
The default value is one,so you don't need to override this in case you have only one section
Make sure your view controller also follows delegate and datasource protocols.
I have read about using underscores to fix compiler warnings that say "Local declaration hides instance variable," but I have not been able to implement a fix. The solutions I have read about say to use an underscore in my .h file, and the #synthesize part of in my .m file. However, I do not synthesize my tableView. Please see my header file below:
.h File
#interface ListViewController : GAITrackedViewController <UISearchDisplayDelegate,
UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate> {
IBOutlet UITableView *tableView;
}
.m File
//SYNTHESIZE
#synthesize listItems, filteredListItems, savedSearchTerm, savedScopeButtonIndex,
searchWasActive, mapView, loadingImageView, loadingActivity;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//FIRST WARNING for tableView HERE
if (tableView == self.searchDisplayController.searchResultsTableView){
return [self.filteredListItems count];
}
else{
return [self.listItems count];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//SECOND WARNING for tableView HERE
[tableView setRowHeight: 60.00];
return 1;
}
You have an outlet/property named tableView and your delegate method also contains tableView.
So you need to change either of them. Typically you go to change the argument names of delegate and datasource as
- (NSInteger)tableView:(UITableView *)aTableView
numberOfRowsInSection:(NSInteger)section {
Change :
IBOutlet UITableView *tableView;
To :
IBOutlet UITableView *tableView1;
Make the same required changes in your .m file also. This warning is coming because in below delegate method:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
There is a reference of UITableView with name tableView and you have given the same name. Scope of this variable is function level where as scope of your variable declare in .h is class level.
Dont use same name : IBOutlet UITableView *tableView; use tableview or table_View
I do also spent lot of time on this issue. Finally I could solve this problem.
The thing is we should take care of outlets which are created by us. If you change outlets names then you must connect them properly after change.In my case after lot of struggle I could finish this issue hope it will help others....
For example if You have an outlet/property named tableView and your delegate method also contains tableView.
So you need to change either of them. Typically you go to change the argument names of delegate and datasource as
Change :
IBOutlet UITableView *tableView;
To :
IBOutlet UITableView *tableView1;
For more information visit this link->Local Declaration Hides Instance Variable - tableView Not Synthesized
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:
How can I access the UIView in which I have a UITableView, from the custom cells inside that table. I cant find a method to do that.
Thanks
You can add an instance variable that points to the UITableView and set it when creating/configuring the cell (e.g. in tableView:cellForRowAtIndexPath:). Make sure that your cell does not retain the tableView though.
Knowing your cell’s tableView, call [parentTableView superView] to access the UITableView’s parent view:
#interface PropertyListingCell : UITableViewCell {
__weak id parentTableView;
}
- (void) setParentTableView:(UITableView*)tv; // parentTableView = tv;
In UITableViewController implementation:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//dequeue/create and configure your custom cell here
[cell setParentTableView:tableView];
return cell;
}
UPDATE:
If you're using recent XCode (at least 4.3) you can simply add
#property (weak) UITableView *parentTableView; // use unsafe_unretained instead of weak if you're targeting iOS 4.x
to the #interface section of your UITableViewCell's subclass. Then, when you're creating a cell (in tableView:cellForRowAtIndexPath:) set this property accordingly:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// ...
//dequeue/create and configure your custom cell here
// ...
cell.parentTableView = tableView;
return cell;
}
And in your cell class call self.parentTableView to access the tableView this cell belongs to.
I'm trying to use a UITableView without using a nib and without using a UITableViewController.
I have added a UITableView instance to a UIViewController Like So
mytable = [[UITableView alloc] initWithFrame:CGRectMake(22, 207, 270, 233)];
[mytable setDelegate:self];
[self.view mytable];
Also I have added the following table view methods to my UIViewController (cut for brevities sake)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
I am getting a warning saying that my UIViewController does not implement UITableView delegate protocol.
Whats the correct way to tell the table view where its delegate methods are?
(This is my first attempt at trying to use a UITableView without selecting the UITableTableview controller from the new file options)
You need to conform your class to the UITableViewDelegate and UITableViewDataSource protocols. ( cellForRowAtIndexPath: is in the UITableViewDataSource protocol )
Do this by using angle brackets in your class interface definition:
#interface myViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {...}
The reason why you are getting this warning now and not before when you were using a UITableViewController is because UITableViewController already conforms to these protocols.
So, in essence a UITableViewController is just a class that conforms to UITableViewDelegate and UITableViewDataSource, and has a UITableView instance member.
That's pretty much it.
Of course, if you're not already subclassing UITableViewController, then you need to manually setup the dataSource and delegate of the UITableView:
[tableView setDelegate:self];
[tableView setDataSource:self];
You also must set the dataSource delegate to self:
[tableView setDelegate:self];
[tableView setDataSource:self];
or, equally:
tableview.delegate = self;
tableview.dataSource = self;
The warning is just telling you that your #interface section should declare that you implement the UITableViewDelegate protocol:
#interface MyUIViewController : UIViewController < UITableViewDelegate >
[tableview setDataSource:self]
You have to give it definitely, Why because of the two required methods of UITableView are under UITableViewDataSource protocol.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
In Swift3 this is how you set UITableViewDelegate:
class FeedsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var feedsTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
feedsTableView.delegate = self
feedsTableView.dataSource = self
// Do any additional setup after loading the view.
}
}