UIViewController, UITableView, Protocol - ios

I have a UIViewController, which has a
#interface MYViewController : UIViewController<UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tblView;
Now I am implementing the UITableViewDelegate because I want to use the tableview.
so in my viewdidload I do
- (void)viewDidLoad
{
[super viewDidLoad];
self.tblView.delegate = self;
//self.tblView.dataSource = self;
}
Now the Datasource setting throws a warning, and I never hit the
cellForRowAtIndexPath
method.
Sorry about the editing.
What am I doing wrong?

you need
self.tblView.datasource = self;
also adopt to UITableViewDatasource Protocol,
#interface MYViewController : UIViewController<UITableViewDelegate,UITableViewDatasource>
cellForRowAtIndexPath is a datasource method.

Your interface should also implement the UITableViewDataSource protocol.
#interface MYViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
{
....
}

Please try as below..
UIViewController.h
#interface MYViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>
#property (Strong, nonatomic) IBOutlet UITableView *tblView;
please don't forget to connect tblView outlet to tableView in your .xib file, since this is very required otherwise your datasource methods won't get called.
In UIViewController.m file
- (void)viewDidLoad { [super viewDidLoad];
self.tblView.delegate = self;
self.tblView.dataSource = self; }
and implement two required datasource methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return (number of row you want in table)}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ return cell }
surely this will work for you.

For UITableViewDatasource Protocol add UITableViewDatasource to
#interface MYViewController : UIViewController<UITableViewDelegate, UITableViewDatasource>
and add this line to viewDidLoad
self.tblView.datasource = self;
and go to your storyboard and link 'datasource' and 'delegate' to your tblView

There are couple of problems in your implementation.
You are not conforming to UITableViewDatasource protocol.
You are not setting tableview datasource.
You are not implementing UITableViewDatasource protocol's required methods
You cannot expect to work without setting datasource.

Related

Making Main View Controller Delegate of UITableViewDataSource

I'm new to iOS development. My Main View Controller doesn't display any cells from its table view. I was trying to set it up to display just one cell for now. The main view controller is a subclass of the UIViewController, and has a table view with the prototype cell as well. So my MainViewController.h file looks like below:
#import <UIKit/UIKit.h>
#interface MainViewController : UIViewController <UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
#end
I made the MainVewController a delegate of the UITableViewDataSource, is that the right idea here? My MainViewController.m looks like below:
#import "MainViewController.h"
#import "SWRevealViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Home";
SWRevealViewController *revealViewController = self.revealViewController;
if(revealViewController) {
[self.sidebarButton setTarget: self.revealViewController];
[self.sidebarButton setAction: #selector(revealToggle:)];
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1; //change to number of post objects in array (array.count)
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"basicCell" forIndexPath:indexPath];
return cell;
}
#end
I don't understand what I'm doing wrong here. Shouldn't my MainViewController's Table View be properly displaying the cell? Thoughts?
You should use in viewDidLoad:
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
I don't see the Table View outlet. Did you forget to connect the Table View from interface builder to your view controller header file? After doing that you should also assign the delegate and data source properties of the table view to "self".
Your class just conforms to <UITableViewDataSource>
you should also conform UITableViewDelegate do it this way.
#interface MainViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
You missed setting the delegate and dataSource
It can be done in 2 ways:
using code:
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
put this code in viewDidLoad:
using storyboard: ctrl drag from tableView to your ViewController and set it as delegate and dataSource. see the Image below.
EDIT:
Why don't we need to connect the table's cell as well?
Ans: Table cell is returned from dataSource method tableView:cellForRowAtIndexPath:. This cell is displayed in the tableView. So we don't connect it in the storyboard. However we can configure it in the storyboard.
What's the difference between data source and delegate?
Ans: Delegate: The delegate is an object that is delegated control of the user interface for that event.
Datasource: A data source is like a delegate except that, instead of being delegated control of the user interface, it is delegated control of data.
For more information see Delegates and Data Sources and this answer.

Reload tableview inside a UIview

My table view is inside a UI View, this has been done writing codes, now i am trying to reload the data in table view but the table view is not refreshing.
The UIview and the table view declaration are as follows:
#interface
{
IBOutlet UITableView *tabView;
}
#property (nonatomic, strong) IBOutlet * tabView
#property (nonatomic, strong) UIView * myView; // in .m file
Ok there could be various mistakes which lead to your problem. First of all do you implement the datasource and delegate methods ?
To do so you should declare your header like this:
#interface MyClass : UIViewController<UITableViewDelegate, UITableViewDataSource> {}
Second you should hook up your tableView with those delegate/datasource methods. To do so drag&drop it in the InterfaceBuilder or in you viewDidLoad method write this:
tableView.delegate = self;
tableView.dataSource = self;
Now make sure to implement all the necessary methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {}
If you done all this you should update your tableView like so:
[tableView reloadData];
Also check if you connected your IBOutlet UITableView *tableView; in the Interface Builder.
Provided you have linked up the delegate and the data source methods of the table view correctly, you could just do :
[self.tableView reloadData];
Make sure you have done :
self.tableView.dataSource = self;

REUSE a UITableView with its UI/delegate methods

I have 2 UIViewControllers, the 2 ones are containing EXACTLY the SAME UITableView(with its custom cells and delegate methods).
My question is their any way to "centralize" the UITableView UI and code(datasource and delegates), so that I just have to modify in one file instead of 2 .
following up on my comment, the table view in the xib in your father vc and the delegate methods in your father vc are just in the same place because you chose it to be like that, the table view and the delegate methods are actually quite detached.
so create a new object, say FatherTableController which implements UITableViewDatasource and UITabelViewDelegate and copy those methods out of your FatherViewController into this FatherTableController
now in your FatherViewController, go like
FatherTableController tableController = [FatherTableController new]; //should be a property or a singleton
self.tableview.delegate = tableController;
self.tableview.datasource = tableController;
now you can do that in both your separate vc's that use the same table, and even use the exact same table contoller between the two views if you share it in some way (possibly via a singleton pattern, which can be useful for sharing state between the two view controllers)
Solution:
#interface FatherViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UITableView *parentTableView;
#implementation FatherViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.parentTableView.delegate=self;
self.parentTableView.dataSource=self;
}
//declare the delegate / datasource methods
--------------------- CHILD VIEW CONTROLLER ---------------------
#interface ViewController : FatherViewController
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.delegate=self;
self.tableView.dataSource=self;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return [super numberOfSectionsInTableView:tableView];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [super tableView:tableView numberOfRowsInSection:section];
}

Custom delegate method not called

I'm trying to adapt Apple's example of TableViewUpdates (expanding TableView Cells) to my own application, but I can't seem to get it to work.
I tried narrowing the problem down and I think I know where the problem lies now.
Apple uses a UITableViewController as the base controller for the view, but I have a UIViewController that has the UITableViewDelegate and DataSource as delegate methods. I added the HeaderViewDelegate to it like this:
#interface SearchViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, IngredientHeaderViewDelegate>
IngredientHeaderFooterView.h:
#import <Foundation/Foundation.h>
#include <UIKit/UIKit.h>
#protocol IngredientHeaderViewDelegate;
#interface IngredientHeaderFooterView : UITableViewHeaderFooterView
#property (nonatomic, weak) IBOutlet UILabel *lblTitle;
#property (nonatomic, weak) IBOutlet id <IngredientHeaderViewDelegate> delegate;
#property (nonatomic) NSInteger section;
- (void)toggleOpenWithUserAction:(BOOL)userAction;
#end
#protocol IngredientHeaderViewDelegate <NSObject>
#property (nonatomic) NSInteger hoi;
#optional
- (void)sectionHeaderView:(IngredientHeaderFooterView *)sectionHeaderView sectionOpened:(NSInteger)section;
- (void)sectionHeaderView:(IngredientHeaderFooterView *)sectionHeaderView sectionClosed:(NSInteger)section;
#end
In IngredientHeaderFooterView.m:
- (void)toggleOpenWithUserAction:(BOOL)userAction {
if ([self.delegate respondsToSelector:#selector(sectionHeaderView:sectionOpened:)]) {
NSLog(#"Test1");
[self.delegate sectionHeaderView:self sectionOpened:self.section];
}
if ([self.delegate respondsToSelector:#selector(sectionHeaderView:sectionClosed:)]) {
NSLog(#"Test2");
[self.delegate sectionHeaderView:self sectionClosed:self.section];
}
}
And in my UIViewController that implements the delegate:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
IngredientHeaderFooterView *ingredientHeaderView = [self.tableView dequeueReusableHeaderFooterViewWithIdentifier:SectionHeaderViewIdentifier];
IngredientDescriptionInfo *ingredientInfo = (self.sectionInfoArray)[section];
ingredientInfo.headerView = ingredientHeaderView;
ingredientHeaderView.lblTitle.text = ingredientInfo.play.name;
ingredientHeaderView.section = section;
ingredientHeaderView.delegate = self;
return ingredientHeaderView;
}
But respondsToSelector: always returns false. What could it be?
In your SearchViewController, you need to implement both methods from the protocol IngredientHeaderViewDelegate:
- (void)sectionHeaderView:(IngredientHeaderFooterView *)sectionHeaderView sectionOpened:(NSInteger)section
{
NSLog(#"section opened");
}
- (void)sectionHeaderView:(IngredientHeaderFooterView *)sectionHeaderView sectionClosed:(NSInteger)section
{
NSLog(#"section closed");
}
Also, don't forget to actually assign the delegate in IngredientHeaderFooterView. Make sure that it's not nil when toggleOpenWithUserAction: is called.
If you make sure that the methods are implemented and the delegate is actually assigned you should be good :)

How can I subclass a UITableView?

I want to subclass a UITableView as I want to create a reusable table view component in my application.
The idea is instead of using a delegate for say cellForRowAtIndexPath I want the table view itself to get that call.
I don't think I want a UITableViewController as this UITableView that I want to build has to live in various UIViewControllers (and these UIViewController might have UITableViews of their own).
I subclassed my UITableView as:
#interface ShareUITableView : UITableView
but none of its methods get called.
My ShareUITableView is created via the NIB by setting the custom class to ShareUITableView. I have verified in code that a ShareUITableView is instantiated.
My UITableView does not delegate to its view controller, so that's not the problem.
Any ideas?
If I understood you, you need this class declaration:
#interface ShareUITableView : UITableView <UITableViewDataSource>
And then, in your class constructor, you should assign the instance itself as its own datasource:
- (id)init
{
//...
self.dataSource = self;
//...
}
Of course, the class will have to adopt the protocol.
Good luck!
MyTableView.h
// MyTableView.h
// This overrides the UITableViewDataSource with your own so you can add any methods you would like.
#protocol MyTableViewDataSource <UITableViewDataSource>
#required
// This is where you put methods that are required for your custom table to work (optional)
- (int)myRequiredMethod;
#optional
// This is where you put methods that are optional, like settings (optional)
#end
// This overrides the UITableViewDelegate with your own so you can add any methods you would like.
#protocol MyTableViewDelegate <UITableViewDelegate>
#required
// This is where you put methods that are required for your custom table to work (optional)
#optional
// This is where you put methods that are optional, like settings (optional)
#end
// Make sure you add UITableViewDelegate and UITableViewDataSource implementations.
#interface MyTableView : UITableView <UITableViewDelegate, UITableViewDataSource> {
// Your customer datasource and delegate.
id <MyTableViewDataSource> myDataSource;
id <MyTableViewDelegate> myDelegate;
}
#end
MyTableView.m
// MyTableView.m
#import "MyTableView.h"
#implementation MyTableView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
// This is how you can use your custom method.
int i = [myDataSource myRequiredMethod];
}
return self;
}
- (void)awakeFromNib {
// This assigns the delegate and datasource you assigned to File's Owner in your xib to your custom methods
myDataSource = (id<MyTableViewDataSource>)self.dataSource;
myDelegate = (id<MyTableViewDelegate>)self.delegate;
self.delegate = self;
self.dataSource = self;
}
// This is an example of how to override an existing UITableView method.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// This calls the method implemented in your ViewController. See Below.
NSInteger rows = [myDataSource tableView:tableView numberOfRowsInSection:section];
return rows;
}
#end
MyViewController.h
// MyViewController.h
#import "MyTableView.h"
// Use MyTableViewDataSource and MyTableViewDelegate instead of UITableViewDataSource and UITableViewDelegate
#interface MyViewController : UIViewController <MyTableViewDataSource, MyTableViewDelegate> {
#end
MyViewController.m
// MyViewController.m
#import "MyViewController.h"
#interface MyViewController ()
#end
#implementation MyViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
// This method will be overridden by myTableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (int)myRequiredMethod {
return 2;
}
Subclassing is a great way to make reusable custom UI elements.
I think, you should still go with a Controller class. I expect subclassing UITableView to be tedious work — if possible with reasonable amount at all.
There is no problem to have UIViewController/NoViewController implemented the delegate and datasource and yet assign another controller to a specific tableView. note, that the datasource and delegate don't need to be subclasses of UITableViewController.
have a look at this answer: Implement Delegate at Run Time?
My UITableView does not delegate to its view controller, so that's not the problem.
You have to have to use delegate and datasource, that is how TableViews are filled and configured. otherwise you will have to overwrite every method of UITableView — including private ones, a no-go if you want into AppStore. Recreating UITableView without subclassing it would be even easier.

Resources