When a table view is pressed, I am trying to grab the value of a textview from that table view row that has been selected as follows.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
tabBar = [self.storyboard instantiateViewControllerWithIdentifier:#"TabBarController"];
[self.navigationController pushViewController:tabBar animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
MyOrdersController *detailVC = [[MyOrdersController alloc]init];
NSLog(#"hello %#", detailVC.shipmentReferenceNumberTextLabel.text);
}
But im getting null value. How can I get the value of the textview in that specific row?
You can grab the textview from selected cell subview.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
for (id txtView in selectedCell.subviews)
{
if ([txtView isKindOfClass:[UITextView class]])
{
UITextView* tv = (UITextView*)txtView;
NSString* text = tv.text;
}
}
}
Just try it:-
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = selectedCell.textLabel.text;
}
Related
I'm using two different custom table cells in my table view. That said, I only want didSelectRowAtIndexPath to fire when, for example, Custom Cell Identifier 2 is tapped (but not when Custom Cell Identifer 1 is tapped). How might I go about this? See code below. Right now, didSelectRowAtIndexPath fires when either cell is tapped...
- (void)viewDidLoad {
[super viewDidLoad];
static NSString *ChatTableIdentifier = #"ChatTableViewCell";
static NSString *ChatTableIdentifier2 = #"SwapDetailTableViewCell";
UINib *nib = [UINib nibWithNibName: ChatTableIdentifier bundle:nil];
[self.tableView registerNib:nib forCellReuseIdentifier: ChatTableIdentifier];
UINib *nib2 = [UINib nibWithNibName: ChatTableIdentifier2 bundle:nil];
[self.tableView registerNib:nib2 forCellReuseIdentifier: ChatTableIdentifier2];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *data = self.messages[indexPath.row];
id swaptime = data[#"swaptime"];
if ([swaptime isKindOfClass:[NSString class]]) {
static NSString *ChatTableIdentifier2 = #"SwapDetailTableViewCell";
SwapDetailTableViewCell *cell = (SwapDetailTableViewCell *)[tableView dequeueReusableCellWithIdentifier:ChatTableIdentifier2 forIndexPath:indexPath];
NSString *time = data[#"swaptime"];
cell.startTime.text = time;
NSString *timeEnd = data[#"endswaptime"];
cell.endTime.text = timeEnd;
return cell;
} else {
static NSString *ChatTableIdentifier = #"ChatTableViewCell";
ChatTableViewCell *cell = (ChatTableViewCell *)[tableView dequeueReusableCellWithIdentifier:ChatTableIdentifier forIndexPath:indexPath];
NSString *userName = data[#"name"];
cell.sendingUser.text = userName;
NSString *messageBody = data[#"body"];
cell.messageDisplayed.text = messageBody;
NSString *timeReceived = data[#"published at"];
cell.timeStamp.text = timeReceived;
return cell;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SwapDetailsViewController *detailViewController = [[SwapDetailsViewController alloc]
initWithNibName:#"SwapDetailsViewController" bundle:nil];
detailViewController.swapDetails = [self.messages objectAtIndex:indexPath.row];
[self presentViewController:detailViewController animated:YES completion:nil];
}
You can put an if condition inside didSelectRowAtIndexPath as the one you put in cellForRowAtIndexPath
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *data = self.messages[indexPath.row];
id swaptime = data[#"swaptime"];
//perform action based on this, and don't do anything in second case
if ([swaptime isKindOfClass:[NSString class]])
//this indexPath will always contain cell of one kind
}else{
// this indexPath will contain second cell kind
}
}
Or alternatively you can also do-
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// this will give you cell at the selected indexPath
id cell = [tableView cellForRowAtIndexPath:indexPath]
//perform action based on this, and don't do anything in second case
if ([cell isKindOfClass:[SwapDetailTableViewCell class]])
}else{
}
}
If you don't want a particular row to be selected, the proper solution is to implement the tableView:willSelectRowAtIndexPath: delegate method and return nil for rows you don't want selected.
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (some condition) {
return nil;
} else {
return indexPath;
}
}
So now you need to determine the proper condition. I can think of three ways in your case:
Use the same if condition you have in cellForRowAtIndexPath:.
Get the row's cell and look at the cell's class.
Get the row's cell and look at the cell's reuse identifier.
Option 1 isn't ideal because if you change the logic in cellForRowAtIndexPath you have to remember to change it here too. Options 2 and 3 are essentially the same in this case. I'd go with option 3.
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell.reuseIdentifier isEqualToString: ChatTableIdentifier) {
return nil;
} else {
return indexPath;
}
}
Since you are now using ChatTableIdentifier in three places, I would move the lines:
static NSString *ChatTableIdentifier = #"ChatTableViewCell";
static NSString *ChatTableIdentifier2 = #"SwapDetailTableViewCell";
to before the #implementation line and remove them from everywhere else in the file. No sense in recreating the same variables over and over.
In didSelectRowAtIndexPath you can call method
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
for the indexPath of a current row and get the cell you are currently selecting. Every cell has a reuse identifier, so you can check the identifier of the cell you are selecting. if it equals "SwapDetailTableViewCell", then you can perform everything you need(for example move to another viewController)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell.reuseIdentifier isEqual: #"SwapDetailTableViewCell"]) {
SwapDetailsViewController *detailViewController = [[SwapDetailsViewController alloc]
initWithNibName:#"SwapDetailsViewController" bundle:nil];
detailViewController.swapDetails = [self.messages objectAtIndex:indexPath.row];
[self presentViewController:detailViewController animated:YES completion:nil];
}
Im using the following code to get the index of tablecell that got clicked.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
tabBar = [self.storyboard instantiateViewControllerWithIdentifier:#"TabBarController"];
[self.navigationController pushViewController:tabBar animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView setAllowsSelection:YES];
NSLog(#"you have selected %d",indexPath.row);
}
The problem with this code is that it prints the index value of row only once. If I tap the tableviews anymore, it doesn't print the index value. How to know which index I have clicked ?
try this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
{
NSLog(#"you have selected %d",indexPath.row);
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView setAllowsSelection:YES];
tabBar = [self.storyboard instantiateViewControllerWithIdentifier:#"TabBarController"];
[self.navigationController pushViewController:tabBar animated:YES];
}
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell * tableCell = [tableView cellForRowAtIndexPath:indexPath];
BOOL isSelected = (tableCell.accessoryType == UITableViewCellAccessoryCheckmark);
if (isSelected)
{
tableCell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
tableCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
Now check when accessory check marks appears it will print the index path or not??
I have the following code. I want to display the data that is selected. However, below code is display every post in database. I would like it to display just the one that is selected. How can i do that?
Post Table View Controller:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (![self objectAtIndexPath:indexPath]) {
// Load More Cell
[self loadNextPage];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.objects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell";
UserFeedTableViewCell *cell = (UserFeedTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UserFeedTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (object) {
cell.postView.text = [object objectForKey:#"post"];
// PFQTVC will take care of asynchronously downloading files, but will only load them when the tableview is not moving. If the data is there, let's load it right away.
}
return cell;
}
Details View Controller:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell1";
CommentsTableViewCell *cell = (CommentsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CommentsTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (object) {
cell.detailsPost.text = [object objectForKey:#"post"];
}
return cell;
}
You should select a row in tableView:didSelectRowAtIndexPath
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// store relevant value in your text object
[self performSegueWithIdentifier:#"showSegue" sender:self];
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
}
and the perform segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DetailViewController *controller= [segue destinationViewController];
// set your text object here
controller.text = // your text object
}
HTH
Create an object of the detail table view controller (on which you have to display the data) in the table view controller (from which data is sent), in the following way,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailTableViewController *objNext = (DetailTableViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"detailVC"];
objNext.strLink=[[feeds objectAtIndex:indexPath.row] valueForKey:#"link"];
[self.navigationController pushViewController:objNext animated:YES];
}
Pass the data which you want to pass on row select,
Here are some links which show how to pass data from one view controller to another, some of them are from stack overflow itself.
Passing Data between View Controllers
ios Pass data between navigation controller
https://teamtreehouse.com/community/how-to-pass-data-between-two-view-controllers-when-you-have-tab-bar-and-navigation-controller-in-between
How do i store all selected cells text label text in a NSMutableArray?
How do i remove the correct cells text from the NSMutableArray when a cell is deselected?
What i have this far:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
static NSString *CellIdentifier = #"Cell";
PFTableViewCell *cell = (PFTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[PFTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if ([self.allSelectedUsers containsObject:indexPath]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
NSLog(#"Yeeees");
}else{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
// Configure the cell
cell.textLabel.text = object[#"username"];
return cell;
}
This is when i'm selecting a cell:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([self.allSelectedUsers containsObject:indexPath]) {
[self.allSelectedUsers removeObject:indexPath];
}
else{
[self.allSelectedUsers addObject:indexPath];
}
NSLog(#"%d", self.allSelectedUsers);
[tableView reloadData];
}
When i check the log it doesn't display anything about the cells text label.
As I can't see how you're getting object instance, I suggest you to get back cell and read the title again.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// Lazy initialise array
if (!self.allSelectedUsers) {
self.allSelectedUsers = [NSMutableArray new];
}
// Take action
if ([self.allSelectedUsers containsObject:indexPath]) {
[self.allSelectedUsers removeObject:indexPath];
} else {
[self.allSelectedUsers addObject:indexPath];
}
[tableView reloadData];
// Logging all selected users
for (NSIndexPath *sIndexPath in self.allSelectedUsers) {
NSLog(#"%#", [tableView cellForRowAtIndexPath:sIndexPath].textLabel.text);
}
}
You are currently storing NSIndexPath objects, not NSString objects, so it's not exactly what your question is asking. With your PFTableViewController, you have access to the selector objectAtIndexPath:.
for (NSIndexPath *indexPath in self.allSelectedUsers) {
NSLog(#"%#", [self objectAtIndexPath:indexPath][#"username"]);
}
Note: You shouldn't be calling reloadData in your didSelectRowAtIndexPath: responder; change the accessory type for the cell instead.
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
You should also implement didDeselectRowAtIndexPath: to know when a user deselects a row.
Currently I just have a segue hooked up to a UITableView that pops to the next UITableView in the navigation stack.
What I need to do though now instead, is set up an if statement based on the text in the UITableView cell, to decide which of two possible UIViewControllers to pop to.
So ViewController2 needs to be able to pop either":
- back to ViewController1
OR
- forward to ViewController3
based on the text in the UITableView cell that is populated by JSON.
Can you help me out with that? Will post any code needed. Thanks!
Current ViewController:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"standardCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Spring *spring = [springs objectAtIndex:indexPath.section];
Leaf *leaf = [spring.leafs objectAtIndex:indexPath.row];
cell.textLabel.text = leaf.shortName;
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([segue.identifier isEqualToString:#"themes"]) {
UITableViewCell *cell = (UITableViewCell*)sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// Get reference to destination view controller
MRTViewController *tvc = (MRTViewController *)[segue destinationViewController];
}
}
UPDATE
Added code per #troops but still not sure how to pop to VC3
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *stringToCheck = #"AAA";
if([cell.textLabel.text isEqualToString:stringToCheck])
{
//Pop to VC1
[self.navigationController popToViewController:[[self.navigationController viewControllers]objectAtIndex:0] animated:YES];
} else {
//Pop to VC3, not sure what to put here
// Pass the info
tvc.spring = [springs objectAtIndex:indexPath.section];
tvc.leaf = [tvc.spring.leafs objectAtIndex:indexPath.row];
tvc.buttonNumber = _buttonNumber;
}
}
You could simply check the cell's textLabel's string: If you really want to use segues and not the tableView's delegate method of: didSelectRowAtIndexPath: That's why I based my answer off what your initial question/code looks like.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *stringToCheck = #"AAA";
if ([cell.textLabel.text isEqualToString:stringToCheck])
{
// Pop to VC1
[self.navigationController popToRootViewControllerAnimated:YES];
}
else
{
// Push to VC3
MRTViewController3 *tvc = [self.storyboard instantiateViewControllerWithIdentifier:#"YourID"];
tvc.spring = [springs objectAtIndex:indexPath.section];
tvc.leaf = [tvc.spring.leafs objectAtIndex:indexPath.row];
tvc.buttonNumber = _buttonNumber;
[self.navigationController pushViewController:tvc animated:YES];
}
}
Use delegate method, get cell, compare text.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if([cell.textLabel.text isEqualToString:#"Your String"])
{
//Pop or present view controller
}
}