i have created a UItableView named _tableView, here is the code for table view in view.m
- (void)viewDidLoad
{
[super viewDidLoad];
tableData = [NSArray arrayWithObjects:#"Team Members",#"MembershipStatus",#"relation of status",#"Registerd events", nil];
[_tableView setUserInteractionEnabled:TRUE];
[_tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 54;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[newCell setUserInteractionEnabled:TRUE];
newCell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return newCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"id");
}
while executing the code I got the table correctly. But when i am selecting one of the list item it won't respond. (i.e., the NSLog is not working). did i miss something ?? or what i do wrong ??
In your -viewDidLoad write:
[_tableView setDelegate:self];
check if the tableview's delegate is set to your viewController
#interface MyView : UIViewController <UITableViewDelegate, UITableViewDataSource>
in viewDidLoad:
self.tableview.delegate=self;
Check with your code
#interface ClassName : UIViewController <UITableViewDelegate, UITableViewDataSource>
in viewDidLoad:
self.tableView.delegate = self;
self.tableView.dataSource = self;
or
_tableView.delegate = self;
_tableView.dataSource = self;
check in .h file
#interface MyView : UIViewController is set or Not. if its not set then Set 1st there.
then in .m File while Creating TableView there
you just write
_tableView.delegate = self;
_tableView.dataSource = self;
Related
I'm subclassing UITableView in my app. It's set up to be it's own delegate.
#interface TableView : UITableView <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, assign) id delegate;
- (id)initWithFrame:(CGRect)frame;
#end
#implementation TableView
#synthesize delegate;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height-144, self.frame.size.width, 40)];
super.delegate = self;
super.dataSource = self;
self.tableFooterView = footerView;
}
return self;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 15;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self.delegate tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"Selected row!");
}
#end
Now, what I don't understand is how I TableView can be the delegate of UITableView, but also have a different delegate property that it pipes some functions to sometimes. So, I'd like for - for example - numberOfRowsInSection to be handled by this class, but for - for example - didSelectRowAtIndexPath to be forwarded to the UIViewController or whatever's presenting it.
Each of the delegate methods have a property (UITableView *)tableView you can use this to identify which table views action to be performed
Eg lets say you have 2 table views tableView1 & tableView2 now do something like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if tableView == self {
return [self.delegate tableView:tableView cellForRowAtIndexPath:indexPath];
} else if tableView == tableView2 {
// Do something
}
}
You can do the same concept using super and self calls
EDIT
Create a property called customDelegate, now in your ViewController set customDelegate = self and keep the TableView's delegate same
Now when you wish the class should handle the call just don't do anything as the behaves would be default
But if you wish that your viewController should handle the call then just pipe it using that customDelegate property
Eg
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if <SOME_CONDITION> {
// This will cause the TableView's delegate to be called
return [self.delegate tableView:tableView cellForRowAtIndexPath:indexPath];
} else {
// We wish the ViewController to handler this action then
return [self.customDelegate tableView:tableView cellForRowAtIndexPath:indexPath];
}
}
I' m trying to extract the UITableView Delegate method into a base class called BaseTableProvider
//BaseTableProvider.h
#protocol RSTableProviderProtocol <NSObject>
- (void)cellDidPress:(NSIndexPath *) atIndexPath;
#optional
- (void)cellNeedsDelete:(NSIndexPath *) atIndexPath;
#end
#interface RSBaseTableProvider : NSObject <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, strong) NSMutableArray *dataSource;
#property (nonatomic, weak) id<RSTableProviderProtocol> delegate;
#end
//BaseTableProvider.m
#implementation RSBaseTableProvider
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [[UITableViewCell alloc]init];
return cell;
}
#end
And then I create a subclass of BaseTableProvider, and override two UITableViewDelegate Method in the subclass
//RSFeedListTableProvider.h
#interface RSFeedListTableProvider : RSBaseTableProvider
#end
//RSFeedListTableProvider.m
#implementation RSFeedListTableProvider
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return [self.dataSource count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
RSFeedCell *cell = (RSFeedCell *)[tableView dequeueReusableCellWithIdentifier:kFeedCell];
if(cell == nil){
cell = [[RSFeedCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kFeedCell];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
Feed *feed = (Feed *)self.dataSource[indexPath.row];
if (feed != nil) {
cell.titleText = feed.title;
cell.subTitleText = feed.summary;
}
return cell;
}
#end
I initialized the ListTablerProvider in a ViewController.
//RSFeedListViewController.m
#implementation RSFeedListViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
_feedListView = [[RSFeedListView alloc] init];
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
_provider = [[RSFeedListTableProvider alloc] init];
_provider.delegate = self;
return self;
}
#pragma mark -- Life Cycle
- (void)loadView{
RSFeedListView *aView = [[RSFeedListView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.feedListView = aView;
self.view = aView;
self.feedListView.tableView.delegate = _provider;
self.feedListView.tableView.dataSource = _provider;
}
But I can't see the cell built on the screen.I debuged the code found that UITableView Delegate Method in RSFeedListTableProvider was not called.Any one can help me?Thanks!
I think you did not implement the numberOfRowsInSection datasource method in your subclass RSFeedListTableProvider. So it will invoke the super class implementation
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 0;
}
and there you are returning zero, so cellForRowAtIndexPath in your subclass never will be called.
Solution is implement numberOfRowsInSection in subclass and return proper count
Maybe you are inherited NSObject instead UITableViewController! And you need to create property UITableView *tableView, and connect to your UITableViewController dataSource and delegate.
I have a tableview with dynamic prototypes content. I want to call for a specific ViewController programatically when a dynamic cell tap. I used SWRevealViewController calls for my project.
When I tap on cell one with #"l1" identifier I want to load main view controller with sw_front , used in SWRevealViewController. I cannot use controll+drag becaue in her I have use tabviewcontrller. When I do that it disappear the tab bar.
#import "ListViewController.h"
#interface ListViewController ()
#end
#implementation ListViewController
{
NSArray *menuItems;
}
- (void)viewDidLoad {
[super viewDidLoad];
menuItems = [NSArray arrayWithObjects:#"l1",#"l2",#"l3",#"l6",#"l4",#"l5",#"l7", nil];
// Do any additional setup after loading the view.
}
- (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 [menuItems count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [menuItems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell.reuseIdentifier isEqualToString:#""]) {
UIViewController *mainviewcontroller = [[UIViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:mainviewcontroller];
[self.navigationController presentViewController:navi animated:YES completion:nil];
}
}
If you already set storyboard ID then you can push programmatically using following code.
Here viewController1, viewController2 etc are storyboard Id of individual UIViewController.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *pushViewController = [self.storyboard instantiateViewControllerWithIdentifier:[NSString stringWithFormat:#"viewController%ld",indexPath.row]];
[self.navigationController pushViewController:pushViewController animated:YES];
}
I'm trying to create a view programmatically which will have two views inside of it, one is for searching and the other one is a tableview which will shows photos;
But i'm having EXC_BAD_ACCESS error with code=2, all of the controller code is below. I suspected there is an infinite loop, but don't understand why.
Thanks for any help...
#interface PhotosViewController () <UITableViewDataSource, UITableViewDelegate>
#property (strong, nonatomic) UITableView *tableView;
#end
#implementation PhotosViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.title = #"Instagram";
[self.tableView registerClass:[PhotoTableViewCell class] forCellReuseIdentifier:CellIdentifier];
self.tableView.estimatedRowHeight = UITableViewAutomaticDimension;
self.tableView.allowsSelection = NO;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)loadView
{
_tableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain];
_tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView reloadData];
[self.view addSubview:_tableView];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PhotoTableViewCell *cell = (PhotoTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// NSLog(#"%f", self.navigationController.navigationBar.bounds.size.height);
return /*tableView.bounds.size.height -self.navigationController.navigationBar.bounds.size.height -*/40.0;
}
#pragma mark - Helper Methods
- (void)configureCell:(PhotoTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
// configure photo cell
if (cell == nil) {
cell = [[PhotoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.namelabel.text = #"Mister Tester";
cell.dateLabel.text = #"2 hours ago";
}
In loadView should you not call [super loadView] or assign self.view first.
I believe reading self.view without that can cause an infinite loop.
Why isn't the numberOfSectionsInTableView method not being called? It's called if I add [self.tableView reloadData] in viewDidLoad, but even then, cellForRow does not get called.
Edit: I updated the following code to register the nib for the UITableViewCell.
In a UIViewController, I have:
- (void)viewDidLoad
{
[super viewDidLoad];
XXFeedTableViewController *tableViewController = [[XXFeedTableViewController alloc] initWithStyle:UITableViewStylePlain];
tableViewController.view.frame = self.view.bounds;
[self addChildViewController:tableViewController];
}
XXFeedTableViewController.h
#interface XXFeedTableViewController : UITableViewController
#end
XXFeedTableViewController.m
#import "XXFeedTableViewController.h"
#import "XXFeedTableViewCell.h"
#interface XXFeedTableViewController ()
#end
#implementation XXFeedTableViewController
- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"XXFeedTableViewCell" bundle:nil] forCellReuseIdentifier:#"XXFeedTableViewCell"];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"XXFeedTableViewCell";
XXFeedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = #"Hey";
return cell;
}
#end
Apple docs say:
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. When the table view is about to
appear the first time it’s loaded, the table-view controller reloads
the table view’s data.
Try this, and see if it works. This is the way Apple recommends now with a nib based cell.
-(void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"XXFeedTableViewCell" bundle:nil] forCellReuseIdentifier:#"XXFeedTableViewCell"];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"XXFeedTableViewCell";
ROFeedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = #"Hey";
return cell;
}
After Edit:
In your initial controller, you should add the table view controller as a child controller before you add its subview:
XXFeedTableViewController *tableViewController = [[XXFeedTableViewController alloc] initWithStyle:UITableViewStylePlain];
self addChildViewController:tableViewController];
tableViewController.view.frame = self.view.bounds;
[self.view addSubview:tableViewController.view];
[tableViewController didMoveToParentViewController:self];