i have a TableView which loads a detailview in didSelectRow. I have no problems with the data's.
I am using coreData and to populate the TableView i am using a NSFetchedResultsController.
Now, i want to make a next and previous function in the detailView to jump to the next or previous Table(row) Element. Next Previous like in the Mail-App.
I know that i have to use a button with IBAction.
But how can i make this function?
thanks,
brush51
Edit 1:
I have it done so:
- (IBAction) previousCard:(id) sender {
NSLog(#"previousBtn");
DashboardViewController *parent = (DashboardViewController *)self.parentViewController;
NSIndexPath *actualIndexPath = selectedRow2;
NSIndexPath * newIndexPath = [NSIndexPath indexPathForRow:actualIndexPath.row-1 inSection:actualIndexPath.section];
NSLog(#"newIndexPath: %#", newIndexPath);
[parent.tableViews selectRowAtIndexPath:newIndexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle]; //HERE I GET SIGABRT
}
But i get an error:
-[UIViewController tableViews]: unrecognized selector sent to instance 0xd758ae0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController tableViews]: unrecognized selector sent to instance 0xd758ae0'
How to solve this?
With your UITableView, you can get the selected row by:
- (NSIndexPath *)indexPathForSelectedRow
And set the selection by incrementing the indexPath.row:
- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition
then you action could be:
-(IBAction)nextCell:(id)sender {
NSIndexPath * actualIndexPath = myTableView.indexPathForSelectedRow;
NSIndexPath * newIndexPath = [NSIndexPath indexPathForRow:actualIndexPath.row+1 inSection:actualIndexPath.section];
[myTableView selectRowAtIndexPath:newIndexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}
for that you can manage with your DataSource array.
when you load your detail view at that time you pass your index of array(indexPath.row). by that index you fetch data in detail view. and using increment and decrement in that index you get data for next and previous cell.
Steps
1) setup your tableView.
2) when redirect to DetailView at that time set one int variable for store current indexPath.row . so define one int in detail View.
3) using next and previous button manage indexpath.row which is in int variable.
and represent appropriate data from Source array.
You can use:
(UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
To get the cell you want (next or previous).
And then set the returned cell "Selected" property to YES.
cell.selected = YES
Related
The following problem occurs in my project, when i pressed and hold a backbutton (uibarbuttonitem) and a tableview row. And letting go the tableview row and followed by letting go the backbutton the following error occurs:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'.
I have figured out the problem here is that the tableview didselectrowatindexpath has wrong indexpath.
Case: A uibarbuttonitem and a tableview row is pressed and hold simultaneously.
In situation 1: The uibarbuttonitem is letting go and followed by letting go the tableview row.
Result: Selector for uibarbuttonitem is called. (In my case no error.)
In situation 2: The tableview row is letting go and followed by letting go the uibarbuttonitem.
Result: Selector for uibarbuttonitem is called and followed by the delegate methods of tableview. (In my case the error above occurs.)
- (void)backbutton {
self.itemList = [self getOldItem];
[self.tableView reloadData];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// It crash on this line.
Model *model = [[self.itemList objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
[model show];
}
Does anyone know if this is a normal behavior for which order the selector methods of those button are called? And how i should handle this?
If the app starts, I need to select table row of the last element, that was used.
The name of the last used element I save in plist.
The code I used is:
id plist = [[PlistHandler alloc] init];// FIXME: Dont work with long list, if the element is out of view.
if ([tableData containsObject:[plist readDataForKey:#"selectedFile"]]) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[tableData indexOfObject:[plist readDataForKey:#"selectedFile"]] inSection:0];
[self.fileTable selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
[self tableView:self.fileTable didSelectRowAtIndexPath:indexPath];
}
The problem I found is: If the row is out of view ( table is big and the element if lower then view), I get some exception: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: selectedFile)' Maybe someone know the better way to select a row or to work around.
UPDATE:
I debuged a bit and now I know where the issue happen:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
id plist = [[PlistHandler alloc] init];
[plist writeDataToKey:#"path" andData:[NSString stringWithFormat:#"%#/%#", documentsDirectory, cellText]];
[plist writeDataToKey:#"selectedFile" andData:cellText];
}
It's on the last line, because the cellText is nil, so maybe the index is wrong.
Bit why it works with the elements, that are in the view.
Cell is probably not initialized, because it has not be used. This is, because it is not on the screen.
The deeper problem is that you try to get data from the UI. The UI is for displaying data, not for storing and retrieving data. Retrieve the data from your model. Your application should know how to do this, because it knows how to set the cell.
https://developer.apple.com/library/mac/documentation/general/conceptual/devpedia-cocoacore/MVC.html
I was trying to insert items into a collection view with this code:
- (IBAction)addCards:(UIButton *)sender {
int numberOfCardsToAdd = EXTRA_CARDS_NUMBER;
if ([[self.collectionView visibleCells] count] == 0) {
numberOfCardsToAdd = self.startingCardCount;}
// loop through the game model, draw random cards from the deck and assign it to the array
// take into account the "no cards left in deck" case
for (int i = 0; i < numberOfCardsToAdd; i++) {
if (![self.game.deck isEmpty]) {
SetsCard *cardToAdd = (SetsCard *) [self.game.deck drawRandomCard];
if (cardToAdd) [self.game.cards addObject:cardToAdd];
NSIndexPath *newObject = [[NSIndexPath alloc] initWithIndex:[self.game.cards indexOfObject:cardToAdd]];
[self.collectionView insertItemsAtIndexPaths:#[newObject]]; // adding card to view
}
}
[self.collectionView reloadData];
}
and I got this error:
Assertion failure in -[NSIndexPath row], /SourceCache/UIKit_Sim/UIKit-2380.17/UITableViewSupport.m:2680
2013-06-13 09:09:12.443 Improved Matchismo[1206:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid index path for use with UITableView. Index paths passed to table view must contain exactly two indices specifying the section and row. Please use the category on NSIndexPath in UITableView.h if possible.'
*** First throw call stack:
(0x1cb1012 0x10eee7e 0x1cb0e78 0xb84665 0x29eb6c 0x54b14d 0x53fd69 0x53e60e 0x53e646 0x926e 0x1102705 0x362c0 0x36258 0xf7021 0xf757f 0xf66e8 0x65cef 0x65f02 0x43d4a 0x35698 0x1c0cdf9 0x1c0cad0 0x1c26bf5 0x1c26962 0x1c57bb6 0x1c56f44 0x1c56e1b 0x1c0b7e3 0x1c0b668 0x32ffc 0x269d 0x25c5)
libc++abi.dylib: terminate called throwing an exception
which really confuses me because I was adding items to an UICollectionView, not an UITableView, and my app does not use any instance of UITableView at all. Does anyone know why I got this error, and how I can fix it?
Thanks very much in advance!
A collection view works with two-level index paths (section/row) in the same way as
a table view, so you should create the index path
NSIndexPath *newObject = [NSIndexPath indexPathForRow:... inSection:0];
if there is only one section (section 0).
-[NSIndexPath row] is declared in the #interface NSIndexPath (UITableView) category and the error message has probably not been changed when collection views were introduced in iOS 6, so the message "Invalid index path for use with UITableView" is misleading.
my problem is that when i am clicking in the table view it returns this error
2013-02-22 11:22:42.293 Exercise[1570:c07] -[NSIndexPath item]: unrecognized selector sent to instance 0x6e7ddd0
2013-02-22 11:22:42.294 Exercise[1570:c07] *
and this is where it returns the wrong index
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"uitable index: %ld",(long)indexPath.item);
DBHelper *dataObj = [appDelegate.dataArray objectAtIndex:indexPath.row];
self.selIndex = indexPath.item;
LblID = dataObj.dataID;
VCFname.text = dataObj.DBFirstName;
VCLname.text = dataObj.DBLastName;
VCMobile.text = dataObj.DBMobile;
VCEmail.text = dataObj.DBEmail;
VCBday.text = dataObj.DBBirthdate;
NSLog(#"dataID:%i dataArrayCount:%i",self.selIndex,appDelegate.dataArray.count);
}
i have connected the table view's delegate and datasource to file owner.
EDIT: additional info
I am trying to get the data from my sqlite database to show on the textfield when i click in the tableview
That's not how NSIndexPath works. The index path has a 'row' and 'section' property, which you can use to determine the cell tapped. Here's the documentation for NSIndexPath.
the item property is declared In UICollectionView.h not in the UITableView.h. You can see item. And in the tableView , you should use the indexPath.section
I have a tableView with many values.
I want to get the first indexPath.row value of the table which is being displayed currently.
How can I do that?
I get Following Error while implementing krishnabhadra's answer:
Line at which the error comes is:
[self.table scrollToRowAtIndexPath:indexVis atScrollPosition:UITableViewScrollPositionTop animated:YES];
ERROR:
Assertion failure in -[NSIndexPath row], /SourceCache/UIKit_Sim/UIKit-1447.6.4/UITableViewSupport.m:2018
2011-04-01 11:57:25.458 GlossaryPro[1525:207] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid index path for use with UITableView. Index paths passed to table view must contain exactly two indices specifying the section and row. Please use the category on NSIndexPath in UITableView.h if possible.'
What could be wrong?
You can use tableView indexPathsForVisibleRows function, which returns an NSArray of NSIndexPath for all visible UITableViewCell. From indexPath.row you can find your array index.
NSArray *visible = [tableView indexPathsForVisibleRows];
NSIndexPath *indexpath = (NSIndexPath*)[visible objectAtIndex:0];
indexPath.row will give you index of first object displayed.
[self.myTableView visibleCells];
NSArray *anArrayOfIndexPath = [NSArray arrayWithArray:[self.myTableView indexPathsForVisibleRows]];
NSIndexPath *indexPath= [anArrayOfIndexPath lastObject];
Hope this will help you.
you can use indexPathsForVisibleRows
Returns an array of index paths each identifying a visible row in the receiver.
- (NSArray *)indexPathsForVisibleRows
Return Value
An array of NSIndexPath objects each representing a row index and section index that together identify a visible row in the table view. Returns nil if no rows are visible.
You can use: [self.tableView visibleCells]
That will return a nsarray of UITableViewCell objects, each representing a visible cell in the receiving table view.
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UITableView_Class/Reference/Reference.html
Get exact index number at center currently being displayed:
let middleIndex = ((tableView.indexPathsForVisibleRows?.first?.row)! + (tableView.indexPathsForVisibleRows?.last?.row)!)/2
Example:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let middleIndex = ((tableView.indexPathsForVisibleRows?.first?.row)! + (tableView.indexPathsForVisibleRows?.last?.row)!)/2
print(middleIndex)
}