I know that there is this method to detect which UITableViewCell is selected:
- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
}
But i don't want to know the selected row, i want to know what the content of the cell is and according to that i want to do something. So is there a way to tag a cell?
For better understanding, let's say i have four cells 1, 2, 3 and 4. When i reorder them and my order is 1, 4, 2, 3 and i want to show the value in another view, then it'd show me 2 instead of 4 when i select the second row.
You cab call
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
method from your tableView:didSelectRowAtIndexPath: implementation to get the cell, like this:
- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
...
}
However, this is not the proper way of accessing, especially modifying, the table's content. Instead, you should access the model from which the table takes its information, and make all modifications there. This way the changes would "stick" when the current cell's visuals are scrolled off the screen and back.
There are three ways as far as my knowledge,
1) Access that cell by calling [tableView cellForRowAtIndexPath:indexPath].
Now you can compare data of cell with your model. i.e. You can use NSPredicate to get index value of your selected row data in you model(from which you are filling table cell)
2) When ever you reorder your table row simply change your model as well. E.g. Row-4 becomes Row-2, reorder your model(probably ArrayList) by simply remove object from 4th position and add in 2nd position. So when ever you delete table row it will be same index number of your model data for that row.
3) You can tag each view. But this is code redundancy. You can achieve such thing with out doing so. Instead of this option i will go for 1st or 2nd (For my opinion 2nd option is best if use your model/Array for keeping record only.)
You can access the selected cell like this in didselect delegate method.
UITableViewCell *lab = [tableView cellForRowAtIndexPath:indexPath];
UILabel *selectedCellLabelText = lab.textLabel.text;
Firstly you can define a property of NSString in your second class to access the value corresponding to particular cell content, arrayData is your array in which your value is stored e.g. 1, 2, 3, 4, 5 then write this code in your first class :-
- (void) tableView:(UITableView *) tableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath
{
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondView.stringValue = [arrayData objectAtIndex:indexPath.row];
[self.navigationController pushViewController:secondView animated:YES];
}
Related
I know that dequeueReusableCellWithIdentifier:forIndexPath is called by tableView method inside the tableviewcontroller. And if I understand correctly, tableView method is called several times until all the cells are populated. But what I don't know is where do you get the value for the parameter IndexPath? I want to use dequeueReusableCellWithIdentifier:forIndexPath for a method that I created because I want to access my cell to copy some values of its properties.
NOTE:
I already populated my cell, which means that I successfully used the method tableView.
(Edit) ADDITIONAL INFO:
I'm trying to create a profile and edit profile tableviews. Inside the profile tableview, I displayed the name, address, contact#, etc., of the user. Also, I have a segue called edit profile. In the edit profile, I have textfields for each category (name, address, etc.). What I want to do is, if I edit the contents of the textfields, I should be able to display the new contents in my profile tableview. An example case would be: in the profile view I'm displaying -> name:human, address:earth (each in its own cell). Now if I go to editprofile tableview, I will edit the contents such that -> name:alien, address:mars. After that, there is a button called 'apply' to end editing of contents and go back to profile tableview. If I go back to profile view, the display should now be name:alien, address:mars and not name:human, address:earth.
Here is some code if it's any help. The code is called by a button in tableviewcontroller. "MyCell" is the class of my cell. This code is not working properly. I hope someone can help me fix this.
- (IBAction)updateCopies:(id)sender {
static NSString *ident = #"MyCell";
NSIndexPath *indexPath;
//create cell
MyCell *cell = [self.tableView dequeueReusableCellWithIdentifier:ident forIndexPath:indexPath];
//create variable for accessing cells
int row = [indexPath row];
_labelValues[row] = cell.textField.text
}
You should only use dequeueReusableCellWithIdentifier when you need to supply the table view with a cell to display. If you want to get the UITableViewCell object at a certain index, you should use cellForRowAtIndexPath.
Your problem
What you really need is a model class. You can then pass this to the edit controller, which changes the properties. Then when you return to the tableView, you can reload it and display the new properties.
What you could also do is create a delegate protocol for your edit profile controller, something like EditProfileViewControllerDelegate with something like:
protocol EditProfileViewControllerDelegate {
- (void)editProfileViewController:(EditProfileViewController *)controller didUpdateName:(NSString *)name address:(NSString *)address;
}
You can implement this delegate in your table view controller and use it to update the values when the text is changed. However, this quickly becomes unwieldy, I would not recommend it over using a proper model class.
You can get indexPath using CGPoint..You can use dequeueResusableCell for reusability of the cell..
- (IBAction)updateCopies:(id)sender {
CGPoint position = [sender convertPoint:CGPointZero
toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:position];
//create variable for accessing cells
MyCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
int row = [indexPath row];
_labelValues[row] = cell.textField.text
}
Hope it helps you..
Use this
- (IBAction)updateCopies:(id)sender {
MyCell *parentCell = (MyCell *)sender.superview;
while (![parentCell isKindOfClass:[MyCell class]]) { // iOS 7 onwards the table cell hierachy has changed.
parentCell = parentCell.superview;
}
UIView *parentView = parentCell.superview;
while (![parentView isKindOfClass:[UITableView class]]) { // iOS 7 onwards the table cell hierachy has changed.
parentView = parentView.superview;
}
UITableView *tableView = (UITableView *)parentView;
NSIndexPath *indexPath = [tableView indexPathForCell:(MyCell *)parentCell];
NSLog(#"indexPath = %#", indexPath);
}
Well I got what you want to accomplish.
Firstly, there is a delegate which is being called when you click/select a cell and go to the Edit Profile page. That delegate is
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
///
}
Make a global variable, say selectedIndexPath which holds the current cell index path which is being edited. Update this value each time when you go to edit profile page.
Like this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
selectedIndexPath = indexPath;
// code to go to edit page...
}
Now in your updateCopies Method, do like this
- (IBAction)updateCopies:(id)sender {
//get the existing cell with the indexPath
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[selectedIndexPath]];
[self.tableView endUpdates];
//rest of your code goes here...
}
I am trying to get a URL from a cell. To do this, I am using NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; and then would like to do something like NSURL *url = self.finalURL[indexPath.row] but because indexPath.row is only for Arrays, this doesn't work. Is there a way to achieve the same thing as indexPath.row but for objects not in an array.
Here is how I am saving the url:
cell.finalURL = self.finalURL;
A cell doesn't have a URL, unless you create a subclass of the cell and add that property to is. Conventionally, you will have an array of objects, strings, dictionaries, etc., and that is your tableView's data source.
If I had an array with three NSURLs in it called myArray that contained google, amazon, and bing, and I wanted to display three cells with the respective labels matching the items in the array, I would implement the following code:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// we only want a single section for this example
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// this tells the tableView that you will have as many cells as you have items in the myArray array
return myArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// first we try to reuse a cell (if you don't understand this google it, there's a million resources)
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
// if we were unable to reuse a cell
if (cell == nil) {
// we want to create one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
// here is where we do ANY code that is generic to every cell, such as setting the font,
// text color, etc...
cell.textLabel.textColor = [UIColor redColor];
}
// here is where we do ANY code that is unique to each cell - traits that are based on your data source
// that you want to be different for each cell
// first get the URL object associated with this row
NSURL *URL = myArray[indexPath.row];
// then set the text label's text to the string value of the URL
cell.textLabel.text = [URL absoluteString];
// now return this freshly customized cell
return cell;
}
That, along with the rest of the default tableview code and setting up the array itself, results in the following:
When a user taps on a cell you can access the URL in the array and do something with it like so:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// first deselect the row so it doesn't stay highlighted
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// get the URL associated with this cell by using indexPath.row as an index on your
// data source array, if you tapped the first cell, it will give you back the first URL in your array...
NSURL *selectedURL = myArray[indexPath.row];
// do something with that URL here...
}
Think of your table view's data source as a bunch of little cubbies. You can create the data source in a million different ways, but once you have it you basically take the items and place them in numbered cubbies. Your table view create's itself based on what's in those cubbies, so to make the first cell it looks in the first cubbie, and so on, and later on when a user selects a cell from that tableview, all the table view does is tell you the cubbie number that was selected, and it's your job to use that information to retrieve the data from that specific cubbie and do what you need to with it. Hope that helps!
I'm really new to Objective-C here so what I'm asking may be trivial to most of you but any guidance will help.
Here's a picture of my storyboad.
My current objective is to allow for the user to enter in the number of sets (NSInteger *numReps) and then press the "Log Reps" button and have the table initialize with numReps cells that look like the prototype cell.
Now where I'm at a loss for the implementation. I've never done this kind of thing before so I'm not exactly sure what the best way to go about it is. I have thought of making a custom class for the UITableView table that would take info from the view after the Log Reps button is pushed. I'm not entirely sure how this would need to be implemented. Or can I simply add the table to the properties of the view controller and setup the table within the view controller? That was my initial idea and seems ideal so that I would have everything in one place.
Pleas advise. I am new to all of this and come from a C++ background so I'm still learning a lot of the notation.
Try this:
-(IBAction)btnLogClicked {
int iSet = 4 //Number of row in table
UITableView *tblView= [[UITab;eView alloc]initWithFrame:CGRectMake(0,50,320,100)];
tblView.delegate = self;
tblView.dataSource = self;
[self.view addSubView:tblView];
}
Table View Data Source and Delegate Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return iSet;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Display what you want to display in each cell
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
It's not clear what you want to present in your prototype cells, but you need an array (or probably an array of dictionaries) to populate the cells. The number of rows is determined by the number of entires (the count) of that array. So, if you take the number entered by the user, and add that many object to your array, then call reloadData on the table, you will get the number of rows that you want. What those object are that you add to the array, depends on what you're trying to show there.
you could start reading: Table View Programming Guide for iOS
But I can answer you:
You can add the UITableView to the UIViewController, but you need set your UIViewController like the TableView's delegate and dataSource. Your ViewController need to implement the protocol: UITableViewDataSource
The method that you are looking for is: tableView:numberOfRowsInSection:
But I really recommend you that read the Apple Reference.
I have an app that lists some data in a tableview, in cells. I want the user to be able to select a table view cell, any one, and have the app cycle through the 5 lower cells. Here is what I have so far:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
// Navigation logic may go here. Create and push another view controller.
[self fetchCellsToProcess:indexPath];
}
Here is the fetchCellsToProcess: method:
-(void)fetchCellsToProcess:(NSIndexPath*)indexPath{
for (int cellsToProcess = 0; cellsToProcess < 5; cellsToProcess++) {
//process each cell
//...
}
}
I need use the indexPath to get its indexPath.row. Then add 5 to that indexPath.row and only process the tweets between indexPath.row passed in and indexPath.row+5. What programming logic should I use to cycle through cells x -> x+5?
You should not be using cellForRowAtIndexPath: here: that's part of the presentation logic, while you are working on the model-level logic here.
Look at your cellForRowAtIndexPath: method, and see from where does the text of the cell's labels come. Usually it is an NSArray or some other collection. Your didSelectRowAtIndexPath: method should go directly to that same collection, and grab the info from there.
There is no direct approach to achieve this as dasblinkenlight mentioned
but there is a work around which works for me.
Please follow below approach:
Create your custom button within your custom cell
Create your custom cell class and put button(change type to custom ) do necessary connection custom cell class
create and connect action method named "actionSelectedCell" as below from that button in class you are implementing this logic.
And cellForRowAtIndexPath cell.customButton.text = data from your array or dictionary
- (IBAction)actionSelectedCell:(UIButton *)sender {
// below code for getting selected cell row and its section
UIView *view = sender.superview;
while (view && ![view isKindOfClass:[UITableViewCell self]]) view = view.superview;
UITableViewCell *cell = (UITableViewCell *)view;
indexPathForSelectedCell = [self.tableViewListViewVC indexPathForCell:cell];
NSLog(#"cell is in section %d, row %d", indexPathForSelectedCell.section, indexPathForSelectedCell.row);// so now you are getting indexpath for selected cell
// now you can create simple loop logic to get required data and do whatever you like post it to something or store it for any other use
NSString *strFifthCellContent = [NSString stringWithFormat:#"%#",[dataArray ObjectAtIndex:indexPathForSelectedCell.row+5]]; // in this way you can get data from any cell
}
I have a custom table view cell with 3 fields in it. I need to get the data in one of those fields to use in a SQLite query.
I've looked at cellForRowAtIndexPath, but don't see how to address the particular cell I want (it was defined with an IBOutlet, so it has a name) and get it's value.
When the row is tapped, your didSelectRowAtIndexPath delegate method will be called. In that method, you can use [tableView cellForRowAtIndexPath:indexPath] to get the row's cell. Then you can get whatever you need out of the cell.
I figured it out... here is the code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SingletonClass *shareInstance= [SingletonClass sharedInstance];
sArray *sa = [shareInstance.listOfSites objectAtIndex:indexPath.row]; // (rows are zero based)
NSString *labelContent = sa.sSiteID; // labelContent = site_id
// get list of sites based on selected row
slSQLite *dbCode = [[slSQLite alloc] init];
[dbCode getListOfSites:labelContent]; // labelContent is used to build query
}