I meagrate my project to adjust ios7 while I encountered a strange problem : the delegate method "tableView:didSelectRowAtIndexPath:" is not called in ios7 ,it works well in prior ios version.I was wonder if some specific property be changed in ios7
Here is the code:
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
[self.tableView setAllowsMultipleSelection:NO];
[self.tableView setMultipleTouchEnabled:NO];
}
- (void)tableView:(UITableView *)sender didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[sender deselectRowAtIndexPath:indexPath animated:YES];
_currentContact = [contactArr objectAtIndex:indexPath.row];
if ([_currentContact.accountNPC hasPrefix:#"0"]) {
isContactToNPC = NO;
}else{
isContactToNPC = YES;
}
....
}
Add the following in your viewController.h file
<UITableViewDelegate,UITableViewDatasource>
also connect the tableview's delegate and datasource to the File's Owner of .xib
I'm sorry,I found the answer
I just need set
[cell setExclusiveTouch:YES]
Tks #abhishekkharwar from https://stackoverflow.com/a/18826264/2396477
Related
I'm writing an app hat has many views and I used sliding views library (ECSlidingViews). The problem is when I fill an array with objects and fill the table with the objects in tableView:cellForRowIndexPath: method, it does present the data in the table, but when I go to other view and come back the data disappears because tableView:cellForRowIndexPath: is not called. Here is the code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"begin of cellForRowAtIndexPath");
SchedualeCell *cell = (SchedualeCell *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
Course *temp = [array objectAtIndex:indexPath.row];
cell.nameLb.text = temp.name;
cell.hourLb.text = [NSString stringWithFormat:#"%d",temp.hour];
cell.startTimeLb.text = temp.startTime;
cell.endTimeLb.text = temp.endTime;
NSLog(#"End of cellForRowAtIndexPath");
return cell;
}
tableView:numberOfRowsInSection: and numberOfSectionsInTableView: is invoked when I come back to the view that has the table view.
P.S.: The view is UIViewController that has table view inside of it, and I searched all StackOverflow before posting my problem.
EDIT : this is where I set the delegate and datasource
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Did Appear");
// Do any additional setup after loading the view.
self.view.layer.shadowOpacity = 0.75f;
self.view.layer.shadowRadius = 10.0f;
self.view.layer.shadowColor= [UIColor blackColor].CGColor;
if (![self.slidingViewController.underLeftViewController isKindOfClass:[MenuViewController class]])
{
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Menu"];
}
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
if (array == nil)
{
array = [[NSMutableArray alloc]init];
}
table.delegate = self;
table.dataSource = self;
[table reloadData];
}
and I did included The delegate and datasource in the header
#interface MainViewController : UIViewController<UITableViewDataSource , UITableViewDelegate,addDelegate>
First of all , it's not numberOfRowsAtSection and numberOfTableView. It's numberOfSectionsInTableView and numberOfRowsInSection.
Things you can do :
1) NSLog your numberOfRowsInSection. Note that , If it's "0" then your cellForRowAtIndexPath is never going to be called.
2) If you are using your UITableView inside some UIView then you should add :
[self.view addSubview:table];
3) Don't Forget to include :
#interface yourViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
Once check that you reframed the tableview in ViewWillAppear.
Some times if we set out of frame, CellForRowAtIndexPath will not call.
I'm hardly working on a new project. The main structure is a tableView in the RootViewController, where some rows shows the actual statuses and some informations to the user. I'm now working on the editing mode which won't work.
In the navigationbar is a button which calls edit here's the code:
- (void)edit {
NSLog(#"Edit pressed");
if (edit) {
NSLog(#"Deactivate edit\n");
edit = NO;
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Bearbeiten" style:UIBarButtonItemStyleBordered target:self action:#selector(edit)];
[contentTableView setEditing:NO animated:YES];
} else {
NSLog(#"Activate edit\n");
edit = YES;
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Fertig" style:UIBarButtonItemStyleDone target:self action:#selector(edit)];
[contentTableView setEditing:YES animated:YES];
}
}
My viewController is a subclass of UITableViewController and the contentTableView is not nil... I implemented the following methods:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
NSMutableDictionary *oldDict = [[NSMutableDictionary alloc] initWithDictionary:[saver read]];
NSDictionary *movingDict = [[oldDict objectForKey:#"content"] objectAtIndex:sourceIndexPath.row];
[[oldDict objectForKey:#"content"] removeObjectAtIndex:sourceIndexPath.row];
[[oldDict objectForKey:#"content"] insertObject:movingDict atIndex:destinationIndexPath.row];
[saver write:oldDict];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableDictionary *oldDict = [[NSMutableDictionary alloc] initWithDictionary:[saver read]];
[[oldDict objectForKey:#"content"] removeObjectAtIndex:indexPath.row];
[saver write:oldDict];
[contentTableView beginUpdates];
[contentTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; //This doesn't work!
[contentTableView endUpdates];
}
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
return #"Entfernen";
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
I copied this from another Project and changed some parts of code but the main things I didn't touch!
What happens?
When I press Edit ('Bearbeiten') the function "edit" gets called. It replaces the button with Done ('Fertig') and writes the correct log:
> 2011-04-27 13:35:44.338 MyApp[1113:207] Edit pressed
> 2011-04-27 13:35:44.339 MyApp[1113:207] Activate edit
If I slide on a cell, the button Remove ('Entfernen') appears and when I press it, the button disappears but the row is still there, but it's removed from the content.
Does anyone know where I'm doing something wrong or where I forgot something?
Thanks in advance, mavrick3.
Edit 1:
I forgot to say: The method [tableView reloadData]; doesn't call numberOfRowsInSection...
Those problems seems to be a bug in the iOS Simulator running iOS 4.3.2.
If you figured out this problem, please set your Deployment Target to an older SDK e.g. 4.2 and run your application on it.
So i have this very basic ipad view controller and i was doing some testing with multiple UITableViews in the same view. The issue I was having was when I selected a row, it would throw a EXC_BAD_ACCESS so I turned on the stack logging and found this
*** -[VCTables tableView:didSelectRowAtIndexPath:]: message sent to deallocated instance 0x4c0ad40
Then i started looking at my code and could not figure out for the life of me what is causing it. I have UITableViewDataSource and UITableViewDelegate on my view controller and have all the appropriate code to handle did select row at index. It draws the tables properly, it just doesnt seem to be hitting self as the datasource.
I have tried building the UITableViews in code, and also in Interface builder. I have re-downloaded and installed XCode 3.2.3 SDK 4.0.2 after uninstalling it and restarting. I couldn't for the life of me see what I am missing but after doing the previous, I am convinced now (i guess) that it is a code issue rather than the IDE, I just cant open my eyes wide enough to see the code issue.
Also, this happens with just one table as well. And with 2 tables, it happens no matter which table I select
here is some code:
VCTables.h
#import <UIKit/UIKit.h>
#interface VCTables : UIViewController<UITableViewDelegate,UITableViewDataSource> {
UITableView *table1;
UITableView *table2;
}
#end
VCTables.m
#import "VCTables.h"
#implementation VCTables
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 50;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 7;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = [[NSString alloc] initWithString:#"yourCell"];
if(tableView.tag == 2000){
[CellIdentifier release];
CellIdentifier = [[NSString alloc] initWithString:#"myCell"];
}
UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if(tableView.tag == 2000){
[cell.textLabel setText:[NSString stringWithFormat:#"%d",indexPath.row]];
}else{
[cell.textLabel setText:[NSString stringWithFormat:#"%d%d",indexPath.row,indexPath.section]];
}
[CellIdentifier release];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
NSLog(#"selected");
}
- (void)viewDidLoad {
[super viewDidLoad];
table1 = [[UITableView alloc] initWithFrame:CGRectMake(20, 73, 320, 480) style:UITableViewStylePlain];
table1.delegate=self;
table1.dataSource=self;
table1.tag=2000;
[self.view addSubview:table1];
table2 = [[UITableView alloc] initWithFrame:CGRectMake(483, 73, 320, 480) style:UITableViewStylePlain];
table2.delegate=self;
table2.dataSource=self;
table2.tag=2000;
[self.view addSubview:table2];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[super dealloc];
}
#end
I'm not sure it gets more basic than that. Please tell me the rookie mistake that is so painfully obvious that I must stop posting here. Thanks in advance
message sent to deallocated instance 0x4c0ad40
This error indicates that your VCTables instance has been released. The UITableView still has a reference to it (the delegate property), so it is trying to send a message to a released object. The common term for this is a zombie.
In order to debug, you should look at how the memory management is being done for your VCTables object. Where is it created, and who owns it?
If you can make use of Apple's performance tools, try using the zombies tool to find out where that VCTables object is released.
I'm a bit confused all as to why the belowSubview does not work.
I'm adding some (subviews) to my navigationController and all of that works well.
-(UITableView *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
...
[self.navigationController.view addSubview:ImageView];
[self.navigationController.view addSubview:toolbar];
add some point in my app I wish to add another toolbar or image above my toolbar.
so let's say I'm doing something like this
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
...
[self.navigationController.view insertSubview:NewImageView aboveSubview:toolbar];
//crucial of course [edit]
rvController = [RootViewController alloc] initWithNibName:#"RootViewController" bundle:[NSBundle] mainBundle];
rvController.CurrentLevel += 1;
rvController.CurrentTitle = [dictionary objectForKey:#"Title"];
[self.navigationController pushViewController:rvController animated:YES];
rvController.tableDataSource = Children;
[rvController release];
However this doesn't work..
Does anyone know what I'm doing wrong here ...
Should I have used something else instead of addSubview or is the problem somewhere else?
From what you have posted, it looks like that should work.
There are a few other issues however. First it is convention that varibales that represent instances of objects start with lowercase. So ImageView and NewImageView should be imageView and newImageView.
I would make sure that in your tableView:didSelectRowAtIndexPath: method newImageView and toolbar are both valid. Are they in your header file?
Try this and see where is errors out:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
...
...
NSAssert(self.navigationController.view,#"WTF? self.navigationController.view is nil");
NSAssert([self.navigationController.view superview],#"WTF? lf.navigationController.view is not onscreen");
NSAssert(newImageView,#"WTF? newImageView is nil");
NSAssert(toolbar,#"WTF? toolbar is nil");
NSAssert([toolbar superview],#"WTF? toolbar is on in the view");
[self.navigationController.view insertSubview:newImageView aboveSubview:toolbar];
}
I have read many topics about UITableViews not refreshing on iPhone, but couldn't find anything matching my situation, so I'm asking for help.
In my class, which extends UIViewController, I have a TableView and an 'ElementList' (which is a wrapper for NSMutableArray) used as data source.
A separate thread adds a new Element to the array via the 'updateList:' method.
When this happens, I want the tableView to be refreshed automatically, but this doesn't happen.
By debugging my app, I can see that 'cellForRowAtIndexPath' is never called and I can't figure out why.
I tried to add an Observer, which calls the 'reloadTableView' method (it is actually called) but the tableView is not updated.
This is my code:
#import <UIKit/UIKit.h>
#interface ListViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
UITableView *tableView;
ElementList *elementList; // Wrapper for NSMutableArray
}
// Called by someone else, triggers the whole thing
-(void)updateList:(Element *)element;
// Added out of desperation
-(void)reloadTableView;
#end
#implementation ListViewController
-(void)loadView
{
// Create the TableView
tableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain];
assert(tableView != nil);
tableView.delegate = self;
tableView.dataSource = self;
[tableView reloadData];
self.view = tableView;
// Added out of desperation
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadTableView) name:#"UpdatedListNotification" object:nil];
}
-(void)reloadTableView
{
// Try anything
[tableView reloadData];
[tableView setNeedsLayout];
[tableView setNeedsDisplay];
[tableView reloadData];
[self.view setNeedsLayout];
[self.view setNeedsDisplay];
}
// Called by someone else, triggers the whole thing
-(void)updateList:(Element *)element
{
assert(element != nil);
[elementList addElement:element];
[element release];
// Notify the observer, which should update its table view
[[NSNotificationCenter defaultCenter] postNotificationName:#"UpdatedListNotification" object:self];
}
// TableView Delegate protocol
- (void)tableView:(UITableView *)table didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Element *selected_element = [elementList getElementAtIndex:indexPath.row];
if (selected_element == nil)
{
NSLog(#"ERROR: Selected an invalid element");
return;
}
[table deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"Selected %#", selected_element.name);
}
// TableView Data Source protocol
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [elementList count];
}
- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Set the cell label
cell.textLabel.text = [[elementList getElementAtIndex:indexPath.row] name];
cell.textLabel.frame = cell.bounds;
cell.textLabel.textAlignment = UITextAlignmentLeft;
return cell;
}
#end
Any help is greatly appreciated, thank you.
Notifications are executed in the same thread as the caller. Updating the UI should really be done in the main thread, so you should call -reloadData on the main thread:
-(void)updateList:(Element *)element
{
assert(element != nil);
[elementList addElement:element];
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil];
}
Also note that you shouldn't release an object that you don't own. So don't call [element release] in your -updateList method. The release should be called by the caller of the function.
That didn't quite work for me - but very close. The method I used was -
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
You can also do
[self performSelectorOnMainThread:#selector(reloadTable) withObject:nil waitUntilDone:YES];
so that you can implement a method on the ViewController to do all the UI stuff that you need.
-(void)reloadTable
{
[self.tableView reloadData];
}