I am using this script for slide menu "SASlideMenu" and I am trying to select the first item by default, but with no success. Does anybody know how to do it?
I tried this:
(void) viewDidLoad{
[super viewDidLoad];
...
self.tableView.delegate = self;
NSString *CellIdentifier = #"homeCell";
UITableViewCell *homeCell = [self.tableViewdequeueReusableCellWithIdentifier:CellIdentifier];
[homeCell setSelected:YES];
}
UPDATE (improved explanation)
I am doing this in "SASlideMenuViewController.m"
UPDATE 2
Further to main question I would like to ask when user enters applicationWillEnterForeground how to select then first cell and switch to home page?
P.S. I dont want to open another question for that, because it could be treated like a "duplicate".
UPDATE 3
I don't know how to switch to home page when user is on another view. For example we switch user to home page when he came back to app(foreground), but this doesn't work in next situation; in SASlideMenu I have list of categories and when I go to one of this categories and then exit from app and back again into app, it switch me to home page and that's ok. But when I click on one of categories in SASlideMenu and then click inside of category view on one of articles and exit app and enter again then it does not switch me to home page and I don't know why. It's navigation based app.
Question 1: To select the first item by default on launch of app
Assuming that you are using the SASlideMenu code mentioned in the question. In your ExampleMenuViewController class you need to add the following,
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
if (indexPath) {
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
__________________________________________________________________________________
Question 2: To select the first item by default and to set home screen in applicationWillEnterForeground
Add the following method declaration in your ExampleMenuViewController.h file,
#interface ExampleMenuViewController :SASlideMenuViewController<SASlideMenuDataSource>
- (void)selectFirstRowAndSetHomePage;
#end
Add the following method in your ExampleMenuViewController.m file,
- (void)selectFirstRowAndSetHomePage {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
if (indexPath) {
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
NSString *identifier= [self.slideMenuDataSource initialSegueId];
if (identifier) {
[self performSegueWithIdentifier:identifier sender:self];
}
}
Implement the following in your SASlideMenuAppDelegate.h class,
#import "ExampleMenuViewController.h"
And,
- (void)applicationWillEnterForeground:(UIApplication *)application {
ExampleMenuViewController *exampleMenuViewController = (ExampleMenuViewController *)self.window.rootViewController;
[exampleMenuViewController selectFirstRowAndSetHomePage];
}
That should help.
__________________________________________________________________________________
This should work for you:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
Check with this code:
NSIndexPath *indexPath = [[NSIndexPath alloc] initWithIndex:0];
UITableViewCell *homeCell = [[self.tableView cellForRowAtIndexPath:indexPath] setSelected:YES];
When viewDidLoad is called your table is still empty. You are not even taking a cell which is inside the table.
Try this code:
NSIndexPath firstCellIndex = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView selectRowAtIndexPath:firstCellIndex
animated:NO
scrollPosition:UITableViewScrollPositionNone];
And put it into viewDidAppear.
Related
I have a UITableView with custom UITableViewCell and datasource.
My tableviewdelegate class is registered to callback on on an event and once I got the event, I am reloading the data on the tableview.
The call back comes after I edit the tableviewcell data. But once the callback came, when I reloaddata, the tableview is scrolling to the top; and not staying at the current selection.
So I have cached the current selected cell and trying to scrollToRowAtIndexPath.
But I am hitting a crash.
How can I scroll to that row after tabledata is loaded ?
{
[m_tableView reloadData];
if(m_currentEditingCell != nullptr)
{
[m_tableView scrollToRowAtIndexPath:m_currentEditingCell atScrollPosition:UITableViewScrollPositionNone animated:YES];
}
}
You should provide NSIndexPath instead of providing your tableviewcell as argument for the selector scrollToRowAtIndexPath:atScrollPosition: animated:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[yourTableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
The following code is able to select the cell after reload.
{
[m_tableView reloadData]; dispatch_async(dispatch_get_main_queue(), ^{ NSIndexPath* indexPath = [NSIndexPath indexPathForRow: ([m_tableView numberOfRowsInSection:([m_tableView numberOfSections]-1)]-1) inSection:([m_tableView numberOfSections]-1)]; if(m_currentCell != nullptr ) [self selectCurrentCell:m_currentCell];
}
}
I am using the following code to deselect a selected table view cell when returning back to the table view in -viewWillAppear:animated.
[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];
I also need to reload the table view's data in this case but when you do that it clears the selected state of the selected cell so you don't see any fade animation.
Is there a way to reload the table data and also preserve the selected state to create the deselect animation?
After several attempts, I've found something that works. You need to set the deselection to occur after a "delay" (of 0 seconds) in order to make sure it happens on the next draw cycle and gets animated properly.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow;
[self.tableView reloadData];
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[self performSelector:#selector(deselectRow) withObject:nil afterDelay:0];
}
- (void)deselectRow
{
[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];
}
Try this in your viewDidLoad:
[self setClearsSelectionOnViewWillAppear:NO];
The obvious solution suggested by #user2970476 seems to work fine on iOS 7. For iOS 8 I slightly modified #Stonz2's answer to use blocks
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
dispatch_async(dispatch_get_main_queue(), ^(void) { // necessary for iOS 8
[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];
});
}
I also had to set self.clearsSelectionOnViewWillAppear = NO; in viewDidLoad because the IB setting got ignored.
You will need to reload your table view first, select the row you want to indicate then perform the deselect animation. The issue you are having is your order of operation is incorrect.
You can save the current selection with
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
[self.tableView reloadData];
[self.tableView selectRowAtIndexPath:selectedRow animated:NO scrollPosition:UITableViewScrollPositionNone];
Okay so I'm making a to do list app. I'm just wondering how to use moveRowAtIndexPath:toIndexPath: properly since it keeps crashing if the toDoItemCompleted method is triggered. I'm trying to move a row down to the bottom of the list once the method is triggered.
-(void)toDoItemCompleted:(ToDoItem *)todoItem {
NSUInteger origIndex = [_toDoItems indexOfObject:todoItem];
NSIndexPath *origIndexPath = [[NSIndexPath alloc]initWithIndex:origIndex];
NSUInteger endIndex = _toDoItems.count-1;
NSIndexPath *endIndexPath = [[NSIndexPath alloc]initWithIndex:endIndex];
[self.tableView beginUpdates];
[self.tableView moveRowAtIndexPath:origIndexPath toIndexPath:endIndexPath];
[self.tableView endUpdates];
}
You don't say what the error is. You should post the full error and point out which line of code is actually causing the error.
But one issue with your code is that you forgot to update your data source. This needs to be done before updating the table view.
Another issue is with how you create the index paths.
Something like this:
- (void)toDoItemCompleted:(ToDoItem *)todoItem {
NSUInteger origIndex = [_toDoItems indexOfObject:todoItem];
NSIndexPath *origIndexPath = [NSIndexPath indexPathForRow:origIndex inSection:0];
NSUInteger endIndex = _toDoItems.count - 1;
NSIndexPath *endIndexPath = [NSIndexPath indexPathForRow:endIndex inSection:0];
// Update date source
[_toDoItems removeObject:todoItem]; // remove from current location
[_toDoItems addObject:todoItem]; // add it to the end of the list
[self.tableView beginUpdates];
[self.tableView moveRowAtIndexPath:origIndexPath toIndexPath:endIndexPath];
[self.tableView endUpdates];
}
I am working with a MasterDetail View using SplitViewController in iPad, My Master View has a tableView where I add rows dynamically. So the newly added row sits at zero postion. So what I want to achieve is that, I want to select the newly added row as soon as it is added to the Master table. Later when the user adds a new row, that row should be selected and the previously added row should be deselected.
For this I have written the code below
- (void)selectNewlyAddedRow
{
NSIndexPath* selectedCellIndexPath= [NSIndexPath indexPathForRow:0 inSection:0];
[m_tableView selectRowAtIndexPath:selectedCellIndexPath animated:TRUE scrollPosition:UITableViewScrollPositionNone];
[self tableView:m_tableView didSelectRowAtIndexPath:selectedCellIndexPath];
}
This code works if I write it in function ViewDidAppear, but if I write it in cellForRowAtIndexPath it doesnt work..
Please provide me correct understanding where I am going wrong.
Regards
Ranjit
viewDidAppear wont get call when you add new row so you just register for table reloaded notification and in method for that notification call select first row I hope it will help you....
- (void)selectFirstRow{
if ([self.tableView numberOfSections] > 0 && [self.tableView numberOfRowsInSection:0] > 0) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionTop];
[self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
}
}
Implement this delegate -
-(void)tableView:(UITableView )tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath)indexPath{
[NSNotificationCenter defaultCenter];
[notificationCenter postNotificationName:#"Table Reloaded" object:nil];
}
In your view controller add this line in viewdidload
-(void)viewDidLoad{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(tableReloaded:) name:#"Table Reloaded" object:nil];
}
-(void) tableReloaded:(NSNotification*)notification{
[self selectFirstRow];
}
So, using storyboard you can create a segue from the UITableViewCell from the first tableViewController to a detailViewController.
Not too complicated, however, when a UISearchBarDisplayController is introduced into the storyboard mix, how can you segue the results cell to the detailViewController?
I am able to search without a problem, I followed this tutorial: http://clingingtoideas.blogspot.com/2010/02/uitableview-how-to-part-2-search.html
All I can do is select a row from the search, it turns blue and doesn't go to the detailViewController.
I have implemented the method prepareForSegue, which works for the non searched cells, but can't figure out this one.
Here's the solution that's based on the comment by #James Chen. Also using a different IndexPath depending on which state the table is in.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"toDetail"]) {
Person *person = nil;
if (self.searchDisplayController.active == YES) {
NSIndexPath *indexPath = indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
NSLog(#"segue - section: %d, row: %d", indexPath.section, indexPath.row);
person = [self.filteredPersonArray objectAtIndex:indexPath.row];
}
else {
NSIndexPath *indexPath = indexPath = [self.tableView indexPathForSelectedRow];
NSLog(#"segue - section: %d, row: %d", indexPath.section, indexPath.row);
person = [self.personArray objectAtIndex:indexPath.row];
}
[[segue destinationViewController] setPerson:person];
}
}
I tried your solution and found that prepareForSegue is called twice
due to the life cycle and didSelect... -> performSegueWithIdentifier.
self:prepareForSegue: object on destination controller is set
(with wrong index) because
dest:viewDidLoad: the destination controller view is loaded after which
self:didSelectRow...: the index is known and properly set.
self:prepareForSegue: object is now correct but has no side effect.
I then focused on didSelect... and came up with this solution where I deleted the segue and pushed the view programmatically:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DestTableViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"DestViewController"];
CustomObj *custObj = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
custObj = [filteredListContent objectAtIndex:indexPath.row];
} else {
storeToDetail = [self.fetchedResultsController objectAtIndexPath:indexPath];
}
controller.custObj = custObj;
[self.navigationController setNavigationBarHidden:NO];
[self.navigationController pushViewController:controller animated:YES];
// presentViewController::animated:completion is always full screen (see problem below)
}
I then experienced some problems going back because I follow a segue
from a mapView, which lead to:
//DestinationViewController
- (IBAction)back:(id)sender
{
[self.navigationController popToRootViewControllerAnimated:YES]; // list
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; // map
}
which is not the way to do it but for now it works.
However, the first part is easy and clean, and maybe it works for you too?!
Ok I think I got it, it seems like a bit of a hack but it works for my purposes:
I am using storyboard:
I have a UITableview controller with UISearchBarDisplayController directly on top of it. No code just drag and drop.
From there, I followed this tutorial to get the search bar to search correctly http://clingingtoideas.blogspot.com/2010/02/uitableview-how-to-part-2-search.html
However prepareForSegue: would only let me display a cell from the original array, not with the search array.
So I used didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (savedSearchTerm) {
searchRowSelected = indexPath.row; //<-- the trick that worked
[self performSegueWithIdentifier:#"ShowDetail" sender:self];
}
}
searchRowSelected is an int variable that I declared at the top of the class.
didSelectRowAtIndexPath: knew which row I was selecting, but prepareForSegue didn't. Thats why I needed that variable.
This is how I used it in prepareForSegue:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"ShowDetail"]) {
dvc = [segue destinationViewController];
NSIndexPath* path = [self.tableView indexPathForSelectedRow];
int row = [path row];
if (savedSearchTerm){ //set the detailViewController with the searched data cell
myDataClass* c = [searchResults objectAtIndex:searchRowSelected];
dvc.myDataClass = c;
}else{ //set the detailViewController with the original data cell
myDataClass* c = [array objectAtIndex:row];
dvc.myDataClass = c;
}
}
}
Also use this code to clean up savedSearchTerm
-(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller{
[self setSavedSearchTerm:nil];
}
If anyone has a better solution I'm all ears :)