tableview:cellForRowAtIndexPath never called - ios

I'm very confusing with this.
I'm trying to create an UITableView grouped programmatically, using the single view template from Xcode. Looking at internet for some examples, there is no secret, the approach to do this is very simple. I'm not sure if my implementation are wrong or right, because the method tableView:cellForRowAtIndexPath: is never called, but the other ones are called and return a integer > 0.
There is code, any suggestions are welcome.
Thanks,
#import "ViewController.h"
#import "SimpleCell.h"
#interface ViewController () <UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, strong) UITableView *table;
#property (nonatomic, strong) NSArray *sections;
#property (nonatomic, strong) NSArray *section1;
#property (nonatomic, strong) NSArray *section2;
#property (nonatomic, strong) NSArray *section3;
#end
#implementation ViewController
static NSString * const CellIdentfier = #"Cell";
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addSubview:self.table];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[table]|"
options:0
metrics:nil
views:#{#"table": self.table}]];
dispatch_async(dispatch_get_main_queue(), ^{
[self.table reloadData];
});
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UITableView *)table
{
if(!_table)
{
_table = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
_table.delegate = self;
_table.dataSource = self;
_table.translatesAutoresizingMaskIntoConstraints = NO;
_table.rowHeight = 34.0f;
_table.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
_table.backgroundColor = [UIColor grayColor];
_table.showsVerticalScrollIndicator = NO;
[_table registerClass:[SimpleCell class] forCellReuseIdentifier:CellIdentfier];
}
return _table;
}
- (NSArray *)sections
{
if(!_sections)
{
_sections = #[#"Section1", #"Section2", #"Section3"];
}
return _sections;
}
- (NSArray *)section1
{
if(!_section1)
{
_section1 = #[#"Player a", #"Player b", #"Player c"];
}
return _section1;
}
- (NSArray *)section2
{
if(!_section2)
{
_section2 = #[#"Zone a", #"Zone b", #"Zone c"];
}
return _section2;
}
- (NSArray *)section3
{
if(!_section3)
{
_section3 = #[#"Area a", #"Area b", #"Area c"];
}
return _section3;
}
#pragma mark - UI Table View Delegate impl
#pragma mark - UI Table View Datasource impl
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
DLog();
SimpleCell *cell = [self.table dequeueReusableCellWithIdentifier:CellIdentfier];
if(!cell)
cell = [[SimpleCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentfier];
cell.label.text = [NSString stringWithFormat:#"Section: %i Row: %i", indexPath.section, indexPath.row];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger total = 0;
if(section == 0) total = self.section1.count;
if(section == 1) total = self.section2.count;
if(section == 2) total = self.section3.count;
DLog(#"Rows: %i", total);
return total;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
DLog();
return self.sections.count;
}
#end

Delete this:
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[table]|"
options:0
metrics:nil
views:#{#"table": self.table}]];
It should be called then.
EDIT:
Change this as well:
_table = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped];
This seems to fix it but I'm not sure why. I'm guessing that it has something to do with the table frame having to be larger than 0.

Related

uitableview:In a same Row selected button should checked and remaining buttons should be unchecked automaticallyy

i am doing feedback form using UITableview in that using custom checkbox for selection.In a UITableviewcell i placed four static buttons for options like,Very
Good,Good,Average,Below Average.
What i want is,i want to select only one button checked in a row, if i select another button checked automatically previous selected button should be unchecked.
Example: In same row suppose if i select Very Good first again i selected Average , previous selected Very Good should be unchecked.
Check My code Below for reference:
This is in cellforrowatindexpath
[cell.R1_BTN setImage:[UIImage imageNamed:#"Touch_G.png"] forState:UIControlStateNormal];
[cell.R1_BTN addTarget:self action:#selector(BtnClicked:) forControlEvents:UIControlEventTouchUpInside];
cell.R1_BTN.tag=1;
Click event here..
-(void)BtnClicked:(id)sender
{
//Need Code Here..
}
updated code for reference..
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [GNM count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [GNM objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([[NM objectAtIndex:section] isKindOfClass:[NSArray class]])
{
return [[NM objectAtIndex:section] count];
}
else
{
return 1;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FeedBackFormTVC *cell = [FeedBack_TV dequeueReusableCellWithIdentifier:#"ListCell" forIndexPath:indexPath];
cell.FBName_LBL.text = [[NM objectAtIndex:indexPath.section] isKindOfClass:[NSArray class]]
? [[NM objectAtIndex:indexPath.section] objectAtIndex:indexPath.row]
: [NM objectAtIndex:indexPath.section];
// below for assigning code action event..
....
....
...
}
I tried using Tags,but i didn't get what i want, pls help me.. thanks in Advance.
I think that you should use model to set for UITableViewCell. Your model's .h file like :
#import <Foundation/Foundation.h>
typedef enum : NSInteger {
UNKNOWN = 0,
VERY_GOOD = 1,
GOOD = 2,
AVERAGE = 3,
BELOW_AVERAGE = 4
}RangeMark;
#interface CellModel : NSObject
#property(nonatomic, assign) RangeMark range;
#end
.m file like:
#import "CellModel.h"
#implementation CellModel
#end
than you should init a table cell with .xib file looks like:
and its .h file like :
#import <UIKit/UIKit.h>
#import "CellModel.h"
#interface TableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIButton *veryGoodButton;
#property (weak, nonatomic) IBOutlet UIButton *goodButton;
#property (weak, nonatomic) IBOutlet UIButton *averageButton;
#property (weak, nonatomic) IBOutlet UIButton *belowAverageButton;
- (void)setupCellWithModel:(CellModel*)model;
#end
its .m file like :
#import "TableViewCell.h"
#implementation TableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)setupCellWithModel:(CellModel *)model {
if(model.range == VERY_GOOD) {
self.veryGoodButton.backgroundColor = [UIColor greenColor];
}
else if(model.range == GOOD) {
self.goodButton.backgroundColor = [UIColor blueColor];
}
else if(model.range == AVERAGE) {
self.averageButton.backgroundColor = [UIColor yellowColor];
}
else if(model.range == BELOW_AVERAGE) {
self.belowAverageButton.backgroundColor = [UIColor redColor];
}
}
- (void)prepareForReuse {
[super prepareForReuse];
self.veryGoodButton.backgroundColor = [UIColor lightGrayColor];
self.goodButton.backgroundColor = [UIColor lightGrayColor];
self.averageButton.backgroundColor = [UIColor lightGrayColor];
self.belowAverageButton.backgroundColor = [UIColor lightGrayColor];
}
#end
Finally your view controller .h file should look like :
#import <UIKit/UIKit.h>
#import "TableViewCell.h"
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
and .m file should look like :
#import "ViewController.h"
#interface ViewController () <UITableViewDelegate, UITableViewDataSource>{
NSMutableArray<CellModel*> *modelList;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 600;
self.tableView.rowHeight = UITableViewAutomaticDimension;
modelList = [NSMutableArray<CellModel*> new];
for (int i=0; i<50; i++) {
CellModel *cellModel = [[CellModel alloc] init];
cellModel.range = UNKNOWN;
[modelList addObject:cellModel];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
TableViewCell *cell = (TableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"TableViewCell"];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
[cell setupCellWithModel:[modelList objectAtIndex:indexPath.row]];
cell.veryGoodButton.tag = indexPath.row;
cell.goodButton.tag = indexPath.row;
cell.averageButton.tag = indexPath.row;
cell.belowAverageButton.tag = indexPath.row;
[cell.veryGoodButton addTarget:self action:#selector(veryGood:) forControlEvents:UIControlEventTouchUpInside];
[cell.goodButton addTarget:self action:#selector(good:) forControlEvents:UIControlEventTouchUpInside];
[cell.averageButton addTarget:self action:#selector(average:) forControlEvents:UIControlEventTouchUpInside];
[cell.belowAverageButton addTarget:self action:#selector(belowAverage:) forControlEvents:UIControlEventTouchUpInside];
return cell;
return nil;
}
- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return modelList.count;
}
- (void) veryGood:(UIButton*)sender {
[modelList objectAtIndex: sender.tag].range = VERY_GOOD;
[self setCellDynamicly:[NSIndexPath indexPathForRow:sender.tag inSection:0] withCellModel:[modelList objectAtIndex: sender.tag]];
}
- (void) good:(UIButton*)sender {
[modelList objectAtIndex: sender.tag].range = GOOD;
[self setCellDynamicly:[NSIndexPath indexPathForRow:sender.tag inSection:0] withCellModel:[modelList objectAtIndex: sender.tag]];
}
- (void) average:(UIButton*)sender {
[modelList objectAtIndex: sender.tag].range = AVERAGE;
[self setCellDynamicly:[NSIndexPath indexPathForRow:sender.tag inSection:0] withCellModel:[modelList objectAtIndex: sender.tag]];
}
- (void) belowAverage:(UIButton*)sender {
[modelList objectAtIndex: sender.tag].range = BELOW_AVERAGE;
[self setCellDynamicly:[NSIndexPath indexPathForRow:sender.tag inSection:0] withCellModel:[modelList objectAtIndex: sender.tag]];
}
- (void)setCellDynamicly:(NSIndexPath*)indexPath withCellModel:(CellModel*)cellModel {
TableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
[cell prepareForReuse];
[cell setupCellWithModel:cellModel];
}
#end
that s all :)
At the end app looks like :
yes this will be a solution for you, at least I hope like this :)
first of all create a custom button .h file like this :
#import <UIKit/UIKit.h>
#interface CustomButton : UIButton
#property (assign) NSInteger sectionTag;
#property (assign) NSInteger rowTag;
#end
custom button .m file like this :
#import "CustomButton.h"
#implementation CustomButton
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
#end
then I changed a few things in TableViewCell .h file like this :
#import <UIKit/UIKit.h>
#import "CellModel.h"
#import "CustomButton.h"
#interface TableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet CustomButton *veryGoodButton;
#property (weak, nonatomic) IBOutlet CustomButton *goodButton;
#property (weak, nonatomic) IBOutlet CustomButton *averageButton;
#property (weak, nonatomic) IBOutlet CustomButton *belowAverageButton;
#property (weak, nonatomic) IBOutlet UILabel *itemLabel;
- (void)setupCellWithModel:(CellModel*)model;
#end
TableViewCell .m file like this :
#import "TableViewCell.h"
#implementation TableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)setupCellWithModel:(CellModel *)model {
if(model.range == VERY_GOOD) {
self.veryGoodButton.backgroundColor = [UIColor greenColor];
}
else if(model.range == GOOD) {
self.goodButton.backgroundColor = [UIColor blueColor];
}
else if(model.range == AVERAGE) {
self.averageButton.backgroundColor = [UIColor yellowColor];
}
else if(model.range == BELOW_AVERAGE) {
self.belowAverageButton.backgroundColor = [UIColor redColor];
}
[self.itemLabel setText:model.itemText];
}
- (void)prepareForReuse {
[super prepareForReuse];
self.veryGoodButton.backgroundColor = [UIColor lightGrayColor];
self.goodButton.backgroundColor = [UIColor lightGrayColor];
self.averageButton.backgroundColor = [UIColor lightGrayColor];
self.belowAverageButton.backgroundColor = [UIColor lightGrayColor];
}
and its .xib like this :
on the other side, there is only one change on CellModel .h file like this :
#import <Foundation/Foundation.h>
typedef enum : NSInteger {
UNKNOWN = 0,
VERY_GOOD = 1,
GOOD = 2,
AVERAGE = 3,
BELOW_AVERAGE = 4
}RangeMark;
#interface CellModel : NSObject
#property(nonatomic, assign) RangeMark range;
#property(nonatomic, copy) NSString* itemText;
- (id)initWith:(NSString*)itemText withRangeMark:(RangeMark)range;
#end
and its .m file like this :
#import "CellModel.h"
#implementation CellModel
- (id)initWith:(NSString*)itemText withRangeMark:(RangeMark)range {
self = [super init];
if(self) {
self.itemText = itemText;
self.range = range;
}
return self;
}
#end
finally view controller .h file same but .m like this :
#import "ViewController.h"
#interface ViewController () <UITableViewDelegate, UITableViewDataSource>{
NSMutableArray *modelList;
NSMutableArray<NSString*> *sectionTitleList;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 600;
self.tableView.rowHeight = UITableViewAutomaticDimension;
sectionTitleList = [NSMutableArray<NSString*> new];
[sectionTitleList addObject:#"RESERVATION"];
[sectionTitleList addObject:#"FRONT DESK"];
[sectionTitleList addObject:#"CASHIER"];
[sectionTitleList addObject:#"HOUSE KEEPING"];
modelList = [[NSMutableArray alloc] initWithCapacity: 4];
[modelList insertObject:[NSMutableArray arrayWithObjects:[[CellModel alloc] initWith:#"Service Speed" withRangeMark:UNKNOWN],[[CellModel alloc] initWith:#"Good Speed" withRangeMark:UNKNOWN],[[CellModel alloc] initWith:#"Confirmation Quality" withRangeMark:UNKNOWN],[[CellModel alloc] initWith:#"Quick Service in Reservetion" withRangeMark:UNKNOWN],nil] atIndex:0];
[modelList insertObject:[NSMutableArray arrayWithObjects:[[CellModel alloc] initWith:#"Check In" withRangeMark:UNKNOWN],[[CellModel alloc] initWith:#"Happy on Their Service" withRangeMark:UNKNOWN],[[CellModel alloc] initWith:#"Coutesey" withRangeMark:UNKNOWN],[[CellModel alloc] initWith:#"Quick Service at Check In" withRangeMark:UNKNOWN],nil] atIndex:1];
[modelList insertObject:[NSMutableArray arrayWithObjects:[[CellModel alloc] initWith:#"Front Office & Reception" withRangeMark:UNKNOWN],[[CellModel alloc] initWith:#"Overall Quality of Room" withRangeMark:UNKNOWN],[[CellModel alloc] initWith:#"Check" withRangeMark:UNKNOWN],[[CellModel alloc] initWith:#"Response Time" withRangeMark:UNKNOWN],nil] atIndex:2];
[modelList insertObject:[NSMutableArray arrayWithObjects:[[CellModel alloc] initWith:#"Room Decor" withRangeMark:UNKNOWN],nil] atIndex:3];
// [modelList addObject: [[CellModel alloc] initWith:#"Service Speed" withRangeMark:UNKNOWN]];
// [modelList addObject: [[CellModel alloc] initWith:#"Good Speed" withRangeMark:UNKNOWN]];
// [modelList addObject: [[CellModel alloc] initWith:#"Confirmation Quality" withRangeMark:UNKNOWN]];
// [modelList addObject: [[CellModel alloc] initWith:#"Quick Service in Reservetion" withRangeMark:UNKNOWN]];
// for (int i=0; i<5; i++) {
// CellModel *cellModel = [[CellModel alloc] init];
// cellModel.range = UNKNOWN;
// cellModel.itemText = #"";
// [modelList addObject:cellModel];
// }
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
TableViewCell *cell = (TableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"TableViewCell"];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSLog(#"section: %ld - row : %ld - item text : %#", (long)indexPath.section, (long)indexPath.row, ((CellModel*)[[modelList objectAtIndex:indexPath.section] objectAtIndex:indexPath.row]).itemText);
[cell setupCellWithModel:[[modelList objectAtIndex:indexPath.section] objectAtIndex:indexPath.row]];
((CustomButton*)cell.veryGoodButton).rowTag = indexPath.row;
((CustomButton*)cell.veryGoodButton).sectionTag = indexPath.section;
((CustomButton*)cell.goodButton).rowTag = indexPath.row;
((CustomButton*)cell.goodButton).sectionTag = indexPath.section;
((CustomButton*)cell.averageButton).rowTag = indexPath.row;
((CustomButton*)cell.averageButton).sectionTag = indexPath.section;
((CustomButton*)cell.belowAverageButton).rowTag = indexPath.row;
((CustomButton*)cell.belowAverageButton).sectionTag = indexPath.section;
[cell.veryGoodButton addTarget:self action:#selector(veryGood:) forControlEvents:UIControlEventTouchUpInside];
[cell.goodButton addTarget:self action:#selector(good:) forControlEvents:UIControlEventTouchUpInside];
[cell.averageButton addTarget:self action:#selector(average:) forControlEvents:UIControlEventTouchUpInside];
[cell.belowAverageButton addTarget:self action:#selector(belowAverage:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[modelList objectAtIndex:section] count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return sectionTitleList.count;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 18)];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, tableView.frame.size.width, 18)];
[label setFont:[UIFont boldSystemFontOfSize:12]];
[label setTextColor:[UIColor whiteColor]];
NSString *string =[sectionTitleList objectAtIndex:section];
[label setText:string];
[view addSubview:label];
[view setBackgroundColor:[UIColor darkGrayColor]];
return view;
}
- (void) veryGood:(CustomButton*)sender {
((CellModel*)[[modelList objectAtIndex:sender.sectionTag] objectAtIndex:sender.rowTag]).range = VERY_GOOD;
[self setCellDynamicly:[NSIndexPath indexPathForRow:sender.rowTag inSection:sender.sectionTag] withCellModel:[[modelList objectAtIndex:sender.sectionTag] objectAtIndex:sender.rowTag]];
}
- (void) good:(CustomButton*)sender {
((CellModel*)[[modelList objectAtIndex:sender.sectionTag] objectAtIndex:sender.rowTag]).range = GOOD;
[self setCellDynamicly:[NSIndexPath indexPathForRow:sender.rowTag inSection:sender.sectionTag] withCellModel:[[modelList objectAtIndex:sender.sectionTag] objectAtIndex:sender.rowTag]];
}
- (void) average:(CustomButton*)sender {
((CellModel*)[[modelList objectAtIndex:sender.sectionTag] objectAtIndex:sender.rowTag]).range = AVERAGE;
[self setCellDynamicly:[NSIndexPath indexPathForRow:sender.rowTag inSection:sender.sectionTag] withCellModel:[[modelList objectAtIndex:sender.sectionTag] objectAtIndex:sender.rowTag]];
}
- (void) belowAverage:(CustomButton*)sender {
((CellModel*)[[modelList objectAtIndex:sender.sectionTag] objectAtIndex:sender.rowTag]).range = BELOW_AVERAGE;
[self setCellDynamicly:[NSIndexPath indexPathForRow:sender.rowTag inSection:sender.sectionTag] withCellModel:[[modelList objectAtIndex:sender.sectionTag] objectAtIndex:sender.rowTag]];
}
- (void)setCellDynamicly:(NSIndexPath*)indexPath withCellModel:(CellModel*)cellModel {
TableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
[cell prepareForReuse];
[cell setupCellWithModel:cellModel];
}
#end
I think that it will work fine for you. Just do some change part of array init on code to dynamic :)
last appearance :
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 600;
self.tableView.rowHeight = UITableViewAutomaticDimension;
sectionTitleList = [NSMutableArray<NSString*> new];
for (NSString* sectionTitle in yourSectionResponseArray) {
[sectionTitleList addObject: sectionTitle];
}
modelList = [[NSMutableArray alloc] initWithCapacity: [sectionTitleList count]];
//your row title array has to be 2D array.
for(int i = 0; i < [sectionTitleList count]; i++) {
NSMutableArray* rowStringArray = [NSMutableArray new];
for(NSString* rowTitle in [your2DRowResponseArray objectAtIndex:i]) {
[rowStringArray addObject: rowTitle];
}
[modelList insertObject: rowStringArray];
}
}
May be this can help you.
Since you haven't provided us the API response details as requested earlier we are forced to use static value. Please replace sectionTitleList & modelList from the array API response. Please find the below code to be used to assign you API response to model created by #Gökhan Aydın .
sectionTitleList = #[#"RESERVATION",#"FRONT DESK",#"CASHIER",#"HOUSE KEEPING",#"COMMON"];
modelList = #[
#[
#"Service Speed",
#"Good Service",
#"Confirmation quality",
#"Quick Service in Reservation"
],
#[
#"Check In",
#"Happy on their Service",
#"Courtesey",
#"Quick Service at Checkin"
],
#[
#"Front office & reception",
#"Overall Quality of Room",
#"Check",
#"Response time"
],
#[
#"Room Decor",
#"Time taken to serveTime taken to serveTime taken t",
#"Bathroom",
#"Facilities in the Room",
#"Choice of menu",
#"Housekeeping",
#"Room Service"
],
#[
#"Overall Comments",
#"Will you come back again"
]
];
self.navigationItem.title = [modelList lastObject];
GNM = [sectionTitleList mutableCopy];
NM = [[NSMutableArray alloc]init];
for (NSArray *feedbacktitles in modelList) {
if ([feedbacktitles isKindOfClass:[NSArray class]]) {
__block NSMutableArray *tempArray = [NSMutableArray new];
[feedbacktitles enumerateObjectsUsingBlock:^(NSString *title, NSUInteger idx, BOOL * _Nonnull stop) {
FeedbackModel *model = [[FeedbackModel alloc]initWith:title withRangeMark:UNKNOWN];
[tempArray addObject:model];
if (idx == [feedbacktitles count] - 1 ) {
*stop = TRUE;
[self->NM addObject:tempArray];
tempArray = [NSMutableArray new];
}
}];
}
}
or by simple for loop
for (NSArray *feedbacktitles in modelList) {
NSLog(#"%#",feedbacktitles);
NSMutableArray* rowStringArray = [NSMutableArray new];
if ([feedbacktitles isKindOfClass:[NSArray class]]) {
for(int i = 0; i < [feedbacktitles count]; i++) {
NSString* rowTitle = [feedbacktitles objectAtIndex:i];
FeedbackModel *model = [[FeedbackModel alloc]initWith:rowTitle withRangeMark:UNKNOWN];
[rowStringArray addObject: model];
if (i == [feedbacktitles count] - 1) {
[NM addObject: rowStringArray];
rowStringArray = [NSMutableArray new];
}
}
}
}

-didSelectRowAtIndexPath: not being called in UITableView

When I click the UITableViewCell , It have selection effect (grey background in clicked cell),But didSelectRowAtIndexPath is not calling ,what happen?
EDIT
this is my code
tableView.h file
#interface PopCardView : MMPopupView <UITableViewDataSource, UITableViewDelegate>
#end
tableView.m file
#property (nonatomic, strong) NSMutableArray *tagsArray;
#property (nonatomic, strong) UIView *backView;
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, assign) NSUInteger lastIndex;
#end
-(id)initWithTags:(NSMutableArray *)tags{
self = [super init];
if (self) {
self.backView = [[UIView alloc] init];
self.backView.backgroundColor = [UIColor whiteColor];
self.backView.layer.cornerRadius = 5;
self.backView.layer.masksToBounds = YES;
[self addSubview:self.backView];
[self.backView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.bottom.right.equalTo(self);
}];
_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 324, 300) style:UITableViewStylePlain];
_tableView.tableFooterView =[[UIView alloc] init];
[self.backView addSubview:_tableView];
[_tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.bottom.equalTo(self.backView).insets(UIEdgeInsetsMake(45,0, 45, 15));
make.size.mas_equalTo(CGSizeMake(324, 200));
}];
[_tableView registerClass:[PopCardTagViewCell class] forCellReuseIdentifier:#"cell"];
_tableView.allowsSelection = YES;
_tableView.allowsSelectionDuringEditing = YES;
[_tableView setUserInteractionEnabled:YES];
_tableView.dataSource = self;
_tableView.delegate = self;
}
return self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[_tagsArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PopCardData *data = (PopCardData *)obj;
data.selected = #"0";
if (idx == indexPath.row) {
data.selected = #"1";
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifer = #"cell";
PopCardTagViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:identifer];
if (!cell) {
cell = [[PopCardTagViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifer];
}
[self configureCell:cell forIndexPath:indexPath];
return cell;
}
-(void)configureCell:(PopCardTagViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
PopCardData *data = (PopCardData *)[_tagsArray objectAtIndex:indexPath.row];
//configure cell
[cell setUserInteractionEnabled:YES];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _tagsArray.count;
}
EDIT2
this is my initialize code of PopCardView,it use swift
let pop = PopCardView(tags: self.m_model.getItmes())
pop.show()
The code you show does not set any delegate to the table view. Either this is the reason or you posted an incomplete code snippet.
self.tableView.delegate = self;
and add UITableViewDelegate to your interface like
#interface ClassName ()<UITableViewDelegate>
Make sure you don't have anything in the cell that can swallow the touch event. Things like buttons and textfields can cause this. Strip everything from your cell, test to see if it works, then add things back in slowly to find the culprit.

UITableViewCell not displaying contents from array

I am working on Fitness(workout) scheduler app with SWRevealView Controller, which offers side bar menu feature.
I have tried to link one cell from the side bar menu to another Tableview controller, where I have set segue between them.
The segue is fine, but it does not display the text data that I have in the mutable array.
MainViewController.h
#import <UIKit/UIKit.h>
#interface MainViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
#end
MainViewController.m
#import "MainViewController.h"
#import "SWRevealViewController.h"
#interface MainViewController ()
#property (nonatomic) NSMutableArray *plans;
#property (nonatomic) NSArray *categories;
#end
#implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
// [UITableView setDelegate:self];
// [UITableView setDataSource:self];
self.plans = #[#{#"name" : #"Week 1-3", #"category" : #"Buff Dudes Workout"}, #{#"name" : #"Week 4-6", #"category" : #"Buff Dudes Workout"}, #{#"name" : #"Week 7-9", #"category" : #"Buff Dudes Workout"}, #{#"name" : #"Week 10-12", #"category" : #"Buff Dudes Workout"}].mutableCopy;
self.categories = #[#"Buff Dudes Workout"];
self.title = #"Workout Programs";
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.
}
#pragma mark - DataSource helper methods
- (NSArray *) itemsInCategory:(NSString *)targetCategory {
NSPredicate *matchingPredicate = [NSPredicate predicateWithFormat:#"category == %#", targetCategory];
NSArray *categoryItems = [self.plans filteredArrayUsingPredicate:matchingPredicate];
return categoryItems;
}
- (NSInteger)numberOfItemsInCategory:(NSString *)targetCategory {
return [self itemsInCategory:targetCategory].count;
}
- (NSDictionary *)itemAtIndexPath:(NSIndexPath *)indexPath {
NSString *category = self.categories[indexPath.section];
NSArray *categoryItems = [self itemsInCategory:category];
NSDictionary *item = categoryItems[indexPath.row];
return item;
}
- (NSInteger)itemIndexForIndexPath:(NSIndexPath *)indexPath {
NSDictionary *item = [self itemAtIndexPath:indexPath];
NSInteger index = [self.plans indexOfObjectIdenticalTo:item];
return index;
}
//- (void)removeitemsAtindexPath:(NSIndexPath *)indexPath {
// NSInteger index = [self itemIndexForIndexPath:indexPath];
// [self.items removeObjectAtIndex:index];
#pragma mark - table view datasource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return self.categories.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self numberOfItemsInCategory:self.categories[section]];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"workoutplanrow";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *plans = [self itemAtIndexPath:indexPath];
cell.textLabel.text = plans[#"name"];
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return self.categories[section];
}
#end
I think there is something wrong in my ellForRowAtIndexPath method.
Make sure your tableView dataSource and delegate in IB are connected to files owner (MainViewController).
Add a reference to your tableView and call tableView.reloadData() after setting plans and categories.

UISearchDisplayController delegate methods not being called

I am trying to gain some knowledge on UISearchDisplayController and going through some tutorial with examples, I have the below class ready with a search bar and table view with data on it.
Header file:
#import <UIKit/UIKit.h>
#interface MyClass : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate>
#property (nonatomic, strong) IBOutlet UITableView *suggestionsTableView;
#property (nonatomic, strong) IBOutlet UISearchBar *searchBar;
#end
Implementation file:
#import "MyClass.h"
#interface DVWNoteTypeSuggestionDisplayController ()
#property (nonatomic, strong) NSArray *items;
#property (nonatomic)BOOL isSearching;
#property (nonatomic, strong) NSMutableArray *filteredList;
#end
#implementation MyClass
- (id)init
{
self = [super initWithNibName:#"SuggestionDisplayController" bundle:BUNDLE];
if (self)
{
// Set the title.
self.title = #"test";
}
return self;
}
- (void)viewDidLoad
{
self.searchBar = [[UISearchBar alloc] init];
[[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchDisplayController.searchResultsDelegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.delegate = self;
self.searchBar.frame = CGRectMake(0, 0, 0, 38);
self.suggestionsTableView.tableHeaderView = self.searchBar;
self.items = [[NSArray alloc] initWithObjects:#"Item No. 1", #"Item No. 2", #"Item No. 3", #"Item No. 4", #"Item No. 5", #"Item No. 6", nil];
self.isSearching = NO;
self.filteredList = [[NSMutableArray alloc] init];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
//- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
// // Return the number of rows in the section.
// // Usually the number of items in your array (the one that holds your list)
// return [self.items count];
//}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (self.isSearching)
{
//If the user is searching, use the list in our filteredList array.
return [self.filteredList count];
} else
{
return [self.items count];
}
}
//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// //Where we configure the cell in each row
//
// static NSString *CellIdentifier = #"Cell";
// UITableViewCell *cell;
//
// cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// if (cell == nil) {
// cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
// }
// // Configure the cell... setting the text of our cell's label
// cell.textLabel.text = [self.items objectAtIndex:indexPath.row];
// return cell;
//}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSString *title;
if (self.isSearching && [self.filteredList count]) {
//If the user is searching, use the list in our filteredList array.
title = [self.filteredList objectAtIndex:indexPath.row];
} else
{
title = [self.items objectAtIndex:indexPath.row];
}
cell.textLabel.text = title;
return cell;
}
- (void)filterListForSearchText:(NSString *)searchText
{
[self.filteredList removeAllObjects]; //clears the array from all the string objects it might contain from the previous searches
for (NSString *title in self.items) {
NSRange nameRange = [title rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (nameRange.location != NSNotFound) {
[self.filteredList addObject:title];
}
}
}
#pragma mark - UISearchDisplayControllerDelegate
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
//When the user taps the search bar, this means that the controller will begin searching.
self.isSearching = YES;
}
- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
//When the user taps the Cancel Button, or anywhere aside from the view.
self.isSearching = NO;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterListForSearchText:searchString]; // The method we made in step 7
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterListForSearchText:[self.searchDisplayController.searchBar text]]; // The method we made in step 7
// Return YES to cause the search result table view to be reloaded.
return YES;
}
#end
Whenever I try to search for any items in the data set (eg: "Item No. 5") its not hitting the breakpoints on any of the delegate i.e. actually the search is not working. Please suggest what am I missing here as this is just my learning project right now.
It appears that a UISearchDisplayController created programatically in this way is prematurely zeroing the delegate, even though the view controller is retaining the UISearchDisplayController as expected.
Add the following to the end of your viewDidLoad and you'll see that the first log will be a valid object, but the second will be null.
NSLog(#"Delegate should be %#", self.searchDisplayController.delegate);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(#"Delegate is %#", self.searchDisplayController.delegate);
});
The quickest way I've found to get around this is to store your own reference to the UISearchDisplayController via a private property or ivar.
If you have to create object for search bar controller and set delegate search bar its work.
UISearchBar *searchBar = [[UISearchBar alloc] init];
[[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchDisplayController.searchResultsDelegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.delegate = self;
searchBar.frame = CGRectMake(0, 0, 0, 38);
self.tableView.tableHeaderView = searchBar;

cellForRowAtIndexPath doesn't work

On my xcode project I have a view with a tableview. I also have a "special" string that contains the objects to populate the array that populates the tableview.
Example:
NSString *myValues=[[NSString alloc]init];
myValues = #"aaa$bbb$ccc?111$222$333?";
as you can see the characters $ and ? separate the objects.
When I call the view I populate the array by the string but the tableview doesn't work. Here some code:
File.H:
#import <UIKit/UIKit.h>
#interface EquipaggioVC : UIViewController <UITableViewDelegate, UITableViewDataSource>{
UITableView *tableViewEquipaggio;
UITableViewCell *nibLoadedCell;
NSMutableArray *arrayEquipaggio;
NSString *stringaDati;
}
#property (nonatomic, retain) IBOutlet UITableView *tableViewEquipaggio;
#property (nonatomic, retain) IBOutlet UITableViewCell *nibLoadedCell;
#property (nonatomic, retain) NSMutableArray *arrayEquipaggio;
#property (nonatomic, retain) NSString *stringaDati;
#end
File.M:
#import "EquipaggioVC.h"
#import "AppDelegate.h"
#import "ClassEquipaggio.h"
#interface EquipaggioVC ()
#end
#implementation EquipaggioVC
#synthesize tableViewEquipaggio;
#synthesize nibLoadedCell;
#synthesize arrayEquipaggio;
#synthesize stringaDati;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(NSString *)uuid
{
//to create an ID
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
CFRelease(uuidRef);
return [(NSString *)uuidStringRef autorelease];
}
-(void)loadTestData:(NSString*)stringaDatiArray{
//populate the array by the string.
if(stringaDatiArray!=nil){
NSArray *elenco=[stringaDatiArray componentsSeparatedByString:#"?"];
for (int i=0; i<([elenco count]-1) ; i++) {
NSString *dettagliEquipaggio=[[NSString alloc]init];
dettagliEquipaggio=[elenco objectAtIndex:i];
NSArray *dettagli=[dettagliEquipaggio componentsSeparatedByString:#"$"];
ClassEquipaggio *aEquipaggio=[[ClassEquipaggio alloc]init];
aEquipaggio.idMembro=[dettagli objectAtIndex:0];
aEquipaggio.sessoMembro=[dettagli objectAtIndex:1];
aEquipaggio.dataNascitaMembro=[dettagli objectAtIndex:2];
[arrayEquipaggio addObject:aEquipaggio];
[aEquipaggio release];
}
}
}
- (UITableViewCell *)tableView:(UITableView *)tableEquipaggioView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
static NSString *sLoadNibNamed;
UITableViewCell *cell;
ClassEquipaggio *aEquipaggio=[arrayEquipaggio objectAtIndex:indexPath.row];
cell = [tableEquipaggioView dequeueReusableCellWithIdentifier:CellIdentifier];
sLoadNibNamed=#"EquipaggioCell";
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:sLoadNibNamed owner:self options:NULL];
cell = [self typeNibLoadCell:aEquipaggio.idMembro];
}
// Configure the cell
UILabel *tipoSessoLabel = (UILabel*) [cell viewWithTag:1];
tipoSessoLabel.text = aEquipaggio.sessoMembro;
UILabel *dataNascitaLabel=(UILabel*)[cell viewWithTag:2];
dataNascitaLabel.text=aEquipaggio.dataNascitaMembro;
return cell;
}
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{
return [arrayEquipaggio count];
}
-(UITableViewCell *)typeNibLoadCell:(NSString *)named{
return nibLoadedCell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return NO;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (void)viewDidLoad
{
[super viewDidLoad];
arrayEquipaggio=[[NSMutableArray alloc]init];
stringaDati=[[NSString alloc]init];
tableViewEquipaggio=[[UITableView alloc]init];
}
-(void)viewDidAppear:(BOOL)animated{
AppDelegate *appDelegate=(AppDelegate*)[[UIApplication sharedApplication]delegate];
UIBarButtonItem * btnIndietroa = [[[UIBarButtonItem alloc] initWithTitle:#"Indietro"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(editNavButtonPressed)]autorelease];
[self.navigationItem setLeftBarButtonItem:btnIndietroa];
stringaDati = [[NSUserDefaults standardUserDefaults] objectForKey:#"stringaDati"];
if(stringaDati!=nil){
[arrayEquipaggio removeAllObjects];
[self loadTestData:stringaDati];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)dealloc{
[super dealloc];
}
#end
On nib file the tableview has the connection with the delegate and datasource, as the IBoutlet is connected with it.
Thanks for your support.
EDIT: [arrayEquipaggio count] return 0.
By the looks of your question your problem is that the method cellForRowAtIndexPath is not being called and as you said the [arrayEquipaggio count] return 0.
Since you are using that array at the method numberOfRowsInSection with a return value of 0 is normal that your table is not calling the method cellForRowAtIndexPath. Since you are telling to your table that there are no rows.
If you want your table to be populated then check that your array return a value greater than 0.
In a nutshell It has no data to populate your table, that why it doesnt work.
Check that in your viewDidAppear:(BOOL)animated that your are pulling anything to stringaDati.
NSLog(#"info: %#",stringaDati);

Resources