Here's a clip on YouTube showing the issue. Video
I have a UITableView that lists the files located in the app alphabetically. As there are over 1500 files, I'm trying to implement functionality to navigate by letter of the alphabet when the right button is clicked on the remote. The issue I'm having is that the TableView indeed moves to the right spot, but instead of being highlighted like it normally would, I get a lighter highlighted color, and clicking select does nothing. If I then navigate normally by pressing down, it moves it back up to the 2nd item in the list. What am I doing wrong?
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.definesPresentationContext = YES; // know where you want UISearchController to be displayed
self.currentIndex = 0;
[self populateTheView];
}
- (void)populateTheView {
NSBundle *bundle = [NSBundle mainBundle];
self.title = @"Devo Songs";
self.files = [bundle pathsForResourcesOfType:@"pdf" inDirectory:@"WorshipSongs"];
NSString *documentsDirectoryPath = [self.files objectAtIndex:thepath.row];
self.filenames = [[documentsDirectoryPath lastPathComponent] stringByDeletingPathExtension];
NSMutableArray *names = [NSMutableArray arrayWithCapacity:[self.files count]];
for (NSString *path in self.files) {
[names addObject:[[path lastPathComponent] stringByDeletingPathExtension]];
}
//self.files = names;
self.files = [names sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
NSLog(@"FILESLOAD%@", self.files);
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self becomeFirstResponder]; // Make the view controller the first responder to handle remote control events.
}
- (BOOL)canBecomeFirstResponder {
return YES;
}
// Override pressesBegan method to detect right arrow key press event.
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
[super pressesEnded:presses withEvent:event];
for (UIPress *press in presses) {
if (press.type == UIPressTypeRightArrow) {
[self handleRightButtonPress];
}
}
}
- (void)handleRightButtonPress {
// Get the current name.
NSString *currentName = self.files[self.currentIndex];
// Get the current letter.
NSString *currentLetter = [currentName substringToIndex:1];
// Find the next index starting from the current index.
NSInteger nextIndex = self.currentIndex + 1;
while (nextIndex < self.files.count) {
NSString *nextName = self.files[nextIndex];
NSString *nextLetter = [nextName substringToIndex:1];
if (![nextLetter isEqualToString:currentLetter]) {
break;
}
nextIndex++;
}
// Check if we found a valid next index.
if (nextIndex < self.files.count) {
// Scroll the table view to the row corresponding to the next letter.
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:nextIndex inSection:0]
atScrollPosition:UITableViewScrollPositionTop animated:NO];
// Update the current index to the new index.
self.currentIndex = nextIndex;
// Deselect the current selected row (if any).
NSIndexPath *previousSelectedIndexPath = [self.tableView indexPathForSelectedRow];
if (previousSelectedIndexPath) {
[self.tableView deselectRowAtIndexPath:previousSelectedIndexPath animated:NO];
}
// Select the cell at the specified index.
NSIndexPath *indexPathToSelect = [NSIndexPath indexPathForRow:self.currentIndex inSection:0];
[self.tableView selectRowAtIndexPath:indexPathToSelect animated:NO scrollPosition:UITableViewScrollPositionNone];
} else {
// If we have reached the end of the list, reset the index to the first element.
self.currentIndex = 0;
// Scroll back to the top of the table view.
[self.tableView setContentOffset:CGPointZero animated:NO];
// Deselect the current selected row (if any).
NSIndexPath *previousSelectedIndexPath = [self.tableView indexPathForSelectedRow];
if (previousSelectedIndexPath) {
[self.tableView deselectRowAtIndexPath:previousSelectedIndexPath animated:NO];
}
// Select the cell at the specified index.
NSIndexPath *indexPathToSelect = [NSIndexPath indexPathForRow:self.currentIndex inSection:0];
[self.tableView selectRowAtIndexPath:indexPathToSelect animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
Not sure if it is needed, but the main scene for the app is a Tab Bar Controller. It has a total of two tabs, the one on the left that shows when launched is a Split View, and the second one is the one in question here which is just a UITableViewController
, and is presented via segue in storyboard.
On tvOS
platform you should work with focuses instead of selections for the navigation purposes so just use indexPathForPreferredFocusedViewInTableView
to inform UITableView
for a focused index path, e.g:
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
...
@property (nonatomic) NSIndexPath* focusedIndexPath;
@end
@implementation ViewController
...
- (void)focusRow:(NSInteger)row {
self.focusedIndexPath = [NSIndexPath indexPathForRow:row inSection:0];
[self.tableView setNeedsFocusUpdate];
}
#pragma mark - UITableViewDelegate
- (NSIndexPath *)indexPathForPreferredFocusedViewInTableView:(UITableView *)tableView {
return self.focusedIndexPath;
}
@end