Problem:
I have a UIView that has a UITableView as a subview. The UIView has a UITapGestureRecognizer configured.
My Problem is that taps on the table are consumed by the UIView's gesture recognizer. The result is the table view never gets to see taps.
How can I either make the recognizer fail when a point is within the table's frame OR make the table the default consumer of the tap.
I have tried (as the code examples show) a number of methods pointInside:withEvent, hitTest:withEvent but can't quite figure out how to do it.
Here is code representing the problem:
Controller:
#import <UIKit/UIKit.h>
#import "ABCDTableView.h"
#interface ABCDFirstView : UIView
#property (nonatomic,strong) ABCDTableView *tableView;
#end
#import "ABCDFirstView.h"
#implementation ABCDFirstView
#synthesize tableView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self awakeFromNib];
}
return self;
}
- (void)awakeFromNib
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(viewTouch:)];
[self addGestureRecognizer:tap];
}
- (void)viewTouch:(UIGestureRecognizer *)gesture {
NSLog(#"view touched");
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if (CGRectContainsPoint(self.tableView.bounds, point)) {
NSLog(#"point in table point as well as view");
return NO;
}
else if (CGRectContainsPoint(self.bounds, point)) {
NSLog(#"point only in view");
return YES;
}
NSLog(#"point not in view");
return NO;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *view = [super hitTest:point withEvent:event];
NSLog(#"view hittest res: %#",view);
return view;
}
#end
TableView
#import <UIKit/UIKit.h>
#interface ABCDTableView : UITableView
<UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) NSArray *list;
#end
#import "ABCDTableView.h"
#implementation ABCDTableView
#synthesize list;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self awakeFromNib];
}
return self;
}
- (void)awakeFromNib
{
self.delegate = self;
self.dataSource = self;
// create table list
self.list = [[NSArray alloc]
initWithObjects: #"one",#"two",#"three",#"four",#"five",
#"six", #"seven", #"eight", #"nine", #"ten", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.list count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cell";
UITableViewCell *cell = [self dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
cell.textLabel.text = [self.list objectAtIndex:[indexPath row]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"row selected");
}
#end
View
#import <UIKit/UIKit.h>
#import "ABCDTableView.h"
#interface ABCDFirstView : UIView
#property (nonatomic,strong) ABCDTableView *tableView;
#end
#import "ABCDFirstView.h"
#implementation ABCDFirstView
#synthesize tableView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self awakeFromNib];
}
return self;
}
- (void)awakeFromNib
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(viewTouch:)];
[self addGestureRecognizer:tap];
}
- (void)viewTouch:(UIGestureRecognizer *)gesture {
NSLog(#"view touched");
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
if (CGRectContainsPoint(self.tableView.bounds, point)) {
NSLog(#"point in table point as well as view");
return NO;
}
else if (CGRectContainsPoint(self.bounds, point)) {
NSLog(#"point only in view");
return YES;
}
NSLog(#"point not in view");
return NO;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *view = [super hitTest:point withEvent:event];
NSLog(#"view hittest res: %#",view);
return view;
}
#end
Use the UIGestureRecognizerDelegate method
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
and check if the touch.view is the same view as the one that should receive the gesture recognizer.
Related
I currently developing a small dictionary app under OSX for my own use, I would like to have a feature that when I hit the return key, the focus would go to the nssearchfeild.
So I try to make the app to receive keyDown event using a NSView and NSViewController told by this tutorial.
But every time I start the app, it wouldn't receive the keyDown event. I have to click on the window once, then hit the keyboard, so that it can receive keyDown event.
What did I do wrong? Can anyone help me out with this problem? I have been stuck in this problem for days, and searching throught Google and API wouldn't help much.
Thanks in advance!
Here is my code for AppDelegate.m
#import "AppDelegate.h"
#import "MyDictViewController.h"
#interface AppDelegate()
#property (nonatomic,strong) IBOutlet MyDictViewController *viewController;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.viewController = [[MyDictViewController alloc] initWithNibName:#"MyDictViewController" bundle:nil];
[self.window.contentView addSubview:self.viewController.view];
self.viewController.view.frame = ((NSView*)self.window.contentView).bounds;
[self.window makeKeyAndOrderFront:nil];
}
#end
And My ViewController.m
#import "MyDictViewController.h"
#import "FileHelper.h"
#import <Carbon/Carbon.h>
#interface MyDictViewController ()
#property (weak) IBOutlet NSTableView *wordsFilteredTable;
#end
#implementation MyDictViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.IMAGE_FILE = [NSImage imageNamed:#"Document.png"];
self.wordlist = [FileHelper readLines];
self.filterWordlist = [[NSMutableArray alloc] init];
}
return self;
}
- (void)loadView
{
[super loadView];
[self.view becomeFirstResponder];
}
-(void)keyDown:(NSEvent*)theEvent
{
NSLog(#"Caught key event");
}
-(void)keyUp:(NSEvent *)theEvent
{
unsigned short keycode = [theEvent keyCode];
switch (keycode)
{
case kVK_Return:
[self.searchField becomeFirstResponder];
default:
break;
}
}
-(void)mouseDown:(NSEvent*)theEvent
{
NSLog(#"Caught mouse event");
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
self.wordsFilteredTable.rowHeight = 37;
NSTableCellView *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
if( [tableColumn.identifier isEqualToString:#"WordColumn"] )
{
NSString *word = [self.filterWordlist objectAtIndex:row];
cellView.textField.stringValue = word;
cellView.imageView.image = self.IMAGE_FILE;
return cellView;
}
return cellView;
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [self.filterWordlist count];
}
- (void)controlTextDidChange:(NSNotification *)obj
{
NSTextView* textView = [[obj userInfo] objectForKey:#"NSFieldEditor"];
self.currentWord = [textView string];
[self.filterWordlist removeAllObjects];
for(NSString* word in self.wordlist) {
if ([word hasPrefix:self.currentWord]) {
[self.filterWordlist addObject:word];
}
}
[self.wordsFilteredTable reloadData];
}
#end
And my AppView.m
#import "AppView.h"
#implementation AppView
- (void)setViewController:(NSViewController *)newController
{
if (viewController)
{
[super setNextResponder:[viewController nextResponder]];
[viewController setNextResponder:nil];
}
viewController = newController;
if (newController)
{
[super setNextResponder: viewController];
[viewController setNextResponder:[self nextResponder]];
}
}
- (void)setNextResponder:(NSResponder *)newNextResponder
{
if (viewController)
{
[viewController setNextResponder:newNextResponder];
return;
}
[super setNextResponder:newNextResponder];
}
#end
I've a NSButton with both an Image and Alternate Image. I would like the alternate image to be shown on hover. To solve this, I've extended the NSButton to show the alternate image when hovering the view. Is there a better solution to this?
My solution:
#interface HoverButton()
#property (nonatomic, strong) NSTrackingArea *trackingArea;
#property (nonatomic, strong) NSImage *imageTmp;
#end
#implementation HoverButton
-(void)mouseEntered:(NSEvent *)theEvent {
[super mouseEntered:theEvent];
[self updateImages];
self.image = self.alternateImage;
}
-(void)mouseExited:(NSEvent *)theEvent {
[super mouseExited:theEvent];
self.image = self.imageTmp;
}
- (void)updateImages {
self.imageTmp = self.image;
}
-(void)updateTrackingAreas
{
if(self.trackingArea != nil) {
[self removeTrackingArea:self.trackingArea];
}
int opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways);
self.trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:opts
owner:self
userInfo:nil];
[self addTrackingArea:self.trackingArea];
}
#end
I would say this is better suited to an NSButtonCell subclass. you can do it in one method and it won't apply to all NSButtons (I doubt thats what you actually want). Just set your button cell type in IB to your custom subclass.
here is some code I just wrote and tested that works:
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
if (_alternateImageOrKeyEquivalentFont && _bcFlags2.mouseInside) {
// the draw bezel call is optional. maybe you don't want it
[self drawBezelWithFrame:cellFrame inView:controlView];
[self drawImage:_alternateImageOrKeyEquivalentFont
withFrame:cellFrame
inView:controlView];
} else {
[super drawInteriorWithFrame:cellFrame
inView:controlView];
}
}
you will need to set the showsBorderOnlyWhileMouseInside to YES probably in an init method for the cell.
CustomButton.h
#interface CustomButton : NSButton
#property (getter=isMouseInside) BOOL mouseInside;
#end
CustomButton.m
#implementation CustomButton
+ (Class)cellClass
{
return [CustomButtonCell class];
}
- (instancetype)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self commonCustomButtonInit];
}
return self;
}
- (void)commonCustomButtonInit
{
NSTrackingArea *trackingArea = nil;
trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect
owner:self
userInfo:nil];
[self addTrackingArea:trackingArea];
}
- (void)mouseEntered:(NSEvent *)event
{
self.mouseInside = YES;
if ([self.cell isKindOfClass:[CustomButtonCell class]])
{
CustomButtonCell *cell = self.cell;
cell.mouseInside = YES;
}
}
-(void)mouseExited:(NSEvent *)event
{
self.mouseInside = NO;
if ([self.cell isKindOfClass:[CustomButtonCell class]])
{
CustomButtonCell *cell = self.cell;
cell.mouseInside = NO;
}
}
#end
CustomButtonCell.h
#interface CustomButtonCell : NSButtonCell
#property (getter=isMouseInside) BOOL mouseInside;
#end
CustomButtonCell.m
#implementation CustomButtonCell
#end
Also see this answer.
I've been writing an app that has custom protocol to send the data from the child view to parent view the classes is
MainViewController
AddViewController (child to mainviewcontroller)
DaysViewController (child to addviewcontroller)
the custom protocol was declared in DaysViewController and implemented in AddViewController
AddViewController.h
#import <UIKit/UIKit.h>
#import "DaysViewController.h"
#import "Course.h"
#import "Student.h"
#interface AddViewController : UITableViewController<UIActionSheetDelegate,UIPickerViewDelegate,UIPickerViewDataSource,UIPickerViewAccessibilityDelegate,UITextFieldDelegate,DaysViewControllerDelegate>
{
NSArray *hoursarray;
UIActionSheet *aac;
IBOutlet UITextField *NameTx,*HoursTx,*DaysTx,*TimeTx;
Student *st;
Course *cc;
}
-(void) pickerDoneClick;
-(IBAction)fillTheOtherData;
#property (nonatomic ,strong) UIActionSheet *aac;
#end
AddViewController.m
#import "AddViewController.h"
#interface AddViewController ()
#end
#implementation AddViewController
#synthesize aac;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
//viewP.frame = CGRectMake(0, 154, 320, 205);
hoursarray = [[NSArray alloc]initWithObjects:#"2",#"3",#"4", nil];
[self.tableView setScrollEnabled:NO];
[DaysTx setEnabled:NO];
[TimeTx setEnabled:NO];
[HoursTx setKeyboardType:UIKeyboardTypeDecimalPad];
cc = [[Course alloc]init];
//UITapGestureRecognizer *tapgr = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapped:)];
//[self.view addGestureRecognizer:tapgr];
}
-(void)tapped:(UITapGestureRecognizer *)tap
{
[self.view endEditing:YES];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [hoursarray count];
}
//-(IBAction)addCourse
//{
// [UIView beginAnimations:#"view" context:nil];
// [UIView setAnimationDuration:1];
// viewP.frame = CGRectMake(0, 500, 320, 205);
// [UIView commitAnimations];
//
//}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [hoursarray objectAtIndex:row];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 3)
{
aac = [[UIActionSheet alloc]initWithTitle:#"How many ?" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil, nil];
UIPickerView *picker = [[UIPickerView alloc]initWithFrame:CGRectMake(0, 44, 0, 0)];
picker.delegate = self;
picker.dataSource = self;
UIToolbar *pickerToolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
[pickerToolBar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc]init];
UIBarButtonItem *flexspace = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexspace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDoneClick)];
[barItems addObject:doneBtn];
[pickerToolBar setItems:barItems animated:YES];
[aac addSubview:pickerToolBar];
[aac addSubview:picker];
[aac showInView:self.view];
[aac setBounds:CGRectMake(0, 0, 320, 464)];
}
else if (indexPath.row == 2)
{
DaysViewController *days = [self.storyboard instantiateViewControllerWithIdentifier:#"Days"];
days.delegate = self;
[self.navigationController pushViewController:days animated:YES];
}
}
-(void) pickerDoneClick
{
[aac dismissWithClickedButtonIndex:0 animated:YES];
}
-(void)chooseDays:(DaysViewController *)controller withArray:(NSArray *)theDaysArray
{
NSLog(#"I'm # chooseDays method");
NSLog(#"Before the add !!");
NSLog(#"chooseDays Method and the array is %#",theDaysArray);
cc.days = [NSMutableArray arrayWithObject:theDaysArray];
NSLog(#"After the add");
NSLog(#"chooseDays Method and the array is %#",cc.days);
// [self dismissViewControllerAnimated:YES completion:nil];
}
-(void)cancelChooseDays:(DaysViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(IBAction)fillTheOtherData
{
cc.name = NameTx.text;
cc.hour = [HoursTx.text integerValue];
NSLog(#"The name is %# and the hour credit is %d",cc.name,cc.hour);
}
#end
DaysViewController.h
#import <UIKit/UIKit.h>
#import "Course.h"
#class DaysViewController;
#protocol DaysViewControllerDelegate <NSObject>
#required
-(void)chooseDays:(DaysViewController *)controller withArray:(NSArray *)theDaysArray;
-(void)cancelChooseDays:(DaysViewController *)controller;
#end
#interface DaysViewController : UITableViewController
{
Course *courseDays;
NSArray *days;
NSMutableArray *dayChosen;
}
#property (nonatomic,weak) id<DaysViewControllerDelegate> delegate;
-(IBAction)done:(id)sender;
-(IBAction)cancel:(id)sender;
#end
DaysViewController.m
#import "DaysViewController.h"
#interface DaysViewController ()
#end
#implementation DaysViewController
#synthesize delegate;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
days = [[NSArray alloc]initWithObjects:#"Saturday",#"Sunday",#"Monday",#"Teusday",#"Wednesday",#"Thursday",#"Friday", nil];
dayChosen = [[NSMutableArray alloc]init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return [days count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DaysCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"DaysCell"];
}
cell.textLabel.text = [days objectAtIndex:indexPath.row];
return cell;
}
-(IBAction)done:(id)sender
{
//Course *course = [[Course alloc]init];
//[course.days addObject:dayChosen];
//NSArray *daysArray = [NSArray arrayWithObject:dayChosen];
NSLog(#"The Days are %#",dayChosen);
[self.delegate chooseDays:self withArray:dayChosen];
[self dismissViewControllerAnimated:YES completion:nil];
}
-(IBAction)cancel:(id)sender
{
[self.delegate cancelChooseDays:self];
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[dayChosen addObject:[days objectAtIndex:indexPath.row]];
NSLog(#"Days are %#",dayChosen);
}
#end
MainViewController has a button that take me to AddViewController and AddViewController has same button that takes me to DaysViewController , all the views has a UITableView .
what I want to do is when I send the data from DaysViewController to AddViewController to put it in an array and dismiss the view AddViewController should show up but instead MainViewController shows and this is what I dont want it to be.
AddViewController and DaysViewController have a UINavigationController but MainViewController doesn't.
Thank you in advance.
Okay, I think I know what your problem is. In your cancel function, try and switch this line of code:
[self dismissViewControllerAnimated:YES completion:nil];
With this line of code:
[self.navigationController popViewControllerAnimated:YES];
Let me know if that helps.
I'm sure my code is withour mistake, because I have two same tableViews and both with same code, same content and same design. But I don't understand why one of my tableViews is shown, and the other one isn't. I'm using Dynamic Prototype Content, Grouped Style and both tableViews are in container view in other ViewController. Here is code:
table.h
#import <UIKit/UIKit.h>
#interface table : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
NSArray *tabledata;
NSIndexPath* checkedIndexPath;
}
#property (nonatomic, retain) NSArray *tabledata;
#property (nonatomic, assign) int number;
#property (nonatomic, retain) NSIndexPath* checkedIndexPath;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
+(table*)instance;
#property (nonatomic) NSInteger selectedRow;
#end
table.m
#import "table.h"
#interface table ()
#end
#implementation table
#synthesize tabledata;
#synthesize tableView;
#synthesize checkedIndexPath;
#synthesize number;
+(InstrumentsI*)instance {
static table *statInst;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
statInst = [[table alloc] init];
});
return statInst;
}
#synthesize selectedRow;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
tabledata = [[NSArray alloc] initWithObjects:#"row1", #"row2", #"row3", nil];
self.selectedRow = 0;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - TableView Data Source methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tabledata count];
}
- (UITableViewCell *)tableView:(UITableView *)tableview cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
cell = [tableview dequeueReusableCellWithIdentifier:#"identifer"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"identifer"];
}
cell.textLabel.text = [tabledata objectAtIndex:indexPath.row];
if (indexPath.row == self.selectedRow)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
#pragma mark TableView Delegate methods
- (void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[table instance].selectedRow = indexPath.row;
if (indexPath.row != self.selectedRow) {
self.selectedRow = indexPath.row;
}
[tableView reloadData];
}
- (void)viewDidUnload {
[self setTableView:nil];
[super viewDidUnload];
}
#end
Check if you have implemented all the delegates and datasource methods.
Also confirm that you have set your file's owner or controller as delegates and datasource.
Try to reload the tableview after loading the data, like:
- (void)viewDidLoad
{
[super viewDidLoad];
tabledata = [[NSArray alloc] initWithObjects:#"row1", #"row2", #"row3", nil];
self.selectedRow = 0;
[self.tableView reloadData];
}
Can't understand why cellForRowAtIndexPath is never called, even though numberOfRowsInSection is called
I call this ViewController with
ServerDataController *dataController = [[ServerDataController alloc] initWithNibName:#"ServerDataController" bundle:nil];
[self presentModalViewController:dataController animated:YES];
here is my code:
Header file:
#import <UIKit/UIKit.h>
#interface ServerDataController : UIViewController <NSXMLParserDelegate, NSURLConnectionDelegate, UITableViewDataSource>
{
...
NSMutableArray *items;
UITableView *docsTableView;
}
#property (retain, nonatomic) IBOutlet UITableView *docsTableView;
#property (nonatomic, readonly) NSMutableArray *items;
#end
Implementation file:
#import "ServerDataController.h"
#implementation ServerDataController
#synthesize docsTableView;
#synthesize items;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (id)init
{
self = [super init];
if (self)
{
}
return self;
}
- (void)dealloc {
[items release];
[docsTableView release];
[super dealloc];
}
- (void)viewDidAppear:(BOOL)animated
{
[self fetchEntries];
animated = YES;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
if (self) {
items = [[NSMutableArray alloc] init];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[self items] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSString *cellTitle = [[[[items objectAtIndex:indexPath.row] docUrl] lastPathComponent] stringByDeletingPathExtension];
cell.textLabel.text = cellTitle;
return cell;
}
Any suggestions?
I don't see where you add items to your array, only an init in your viewDidLoad, I think it is empty, so that is why the function is never called. There simply aren't any items to be displayed.