I have a TableView with a prototype cell, in this prototype cell I have a text field.
Well, what I need is to get a information from this text field when it changes. I need to do that to feed a object.
How can I do that ?
Short answer - you don't.
Slightly more in depth answer...
The UITableViewCell is a "view". It is used only to display information to the screen. It is not for storing data in.
In a UITableViewController (i.e. UITableViewDatasource and UITableViewDelegate) you should have an NSArray (or an NSFetchedResultsController) that you use to store information in.
Then using the delegate methods you populate the table with that data.
If the data changes then you reload the table to update the cells.
What should never happen is the following...
Load the table by passing in data to the cell.
The cell then changes its own data and changes what is on the screen.
The controller then reads that data out of the cell.
No, no, no, don't do this.
What should happen is this...
Load the table and configure the cell display to represent the correct part of the data.
When the button is pressed (or text field is changed, etc...) in the cell then call a method back in the controller to update the data accordingly.
Now the data has changed, reload the cell.
It will now show the correct information based on the new data.
You need a custom cell with a public property (IBOutlet) UITextfield. Then you can set your ViewController as the textField's delegate in cellForRowAtIndexPath,
cell.textField.delegate = self;
in this case your ViewController has to implement UITextFieldDelegate protocol.
Related
I have a problem with getting data from cells in UITableView.
I have a lots of cells (other class with xib) with some people info in table view. Every cell has own switch.
Under table is button that will send message to every person with switch pressed on.
I set property in people class that will remember if switch for person is on. Every switch in cellForRow method has set selector with method for switch action.
Problem is that I have no idea, where to set person property value about switch state. In selector method I don't have access to person info. I have sender, but no info about person.
I'd do this in one of 2 ways depending on what exactly you're trying to do:
Pass a pointer of the person object to the cell when you're configuring it and let the cell handle updating the property that holds the value of the switch.
Make a protocol with a function
-(void)switchInCell:(UITableViewCell*) cell valueModifiedTo:(NSInteget) newValue
Adopt the new protocol in your view controller, add a delegate property of type new protocol to the cell, call that delegate method from within the cell if the switch value changes.
In that method implementation in your view controller, you can do
NSIndexPath* indexPath = [theTable indexPathForCell:cell];
PersonClass* person = Your_DataSource_Array [indexPath.row];
//modify person properties
You can set the UIView tag property to a number, for each of the subviews of the table View Cell's "content" property, at the cell's creation time (e.g. when you add all the UIViews, e.g. labels, buttons, etc...), giving each subview a unique value.
Later, if just given the UITableViewCell, you can iterate through the subviews of is content view and locate your switch (and any other UIViews) by checking their tag value.
If you are using custom cells, you can have method for your switch inside the cell's implementation. From the method, you can get back to the data source using delegation, or notifications and you can pass indexPath of the cell for further identification of the object in the data. You can have a property to store the indexPath of the cell in implementation of the cell's class and you can set the value to that property in cellForItemAtIndexPath: method. Good Luck!
you said you have sender. then you need to just make custom subclass of the control you are using and create a custom property like this.
#property (nonatomic, strong)NSIndexPath *indexPath;
and set it in cellforrowatindexpath. when your selecter calls the you can parse the sender to the custom created class and get the value form the property. try this once.
What i want to do is that if i write something in TextField then it must get displayed in TableView
It is straight forward.
Implement delegates/datasource methods for UITableView.
Make an array to hold user input(s). This array will be used as datasource to populate the table.
Reload the tableView.
I always use searchBar in tableView, Implement searchBar's delegate ,then set cell's text changed when you input searchString.
I have a tableview that is based on a array of DB results, these results contains a date field. I have a custom cell that contains an image and labels. I'm trying to do:
At cellForRowAtIndexPath I verify if the date of current item (objectAtIndex:indexPath.row) has date field bigger than the last item (objectAtIndex:indexPath.row-1). If this is true: I want to add a cell filling the ImageView with a certain image, but I need to add a new row just for show this image.
How can I do this? I'm already doing this verification, but I need to add a new cell...
Do not use the cellForRowAtIndexPath to decide how many cells you want to have. At the point this method is called you should have already setup the data source to provide table view with all information needed.
Here is what you need to do. Refactor your code in a way so you:
Setup the data source first.
Force reload of the table view either by calling the reloadData method.
hey you can add the object in your data base(for example ns array) and refresh the table view with method
[tableView reloadData];
then the method cell for row at index path will be called again and it will refresh the table view's items.just make sure the method cellforrawantindexpath in your code knows to handle the new data type(make validations).
Your tableView data source should not contain any of that logic where the content of once cell depends on the content of another cell. Instead, you should have a data item for each requested indexPath and that data item should contain ALL logic necessary for the cell to be configured. If an action on that cell has an effect on how another cell should look, you apply a change to the corresponding data-item, and then call reloadRowsAtIndexPaths: for the indexPaths.
In short: configure cells ONLY in tableView:cellForRowAtIndexPath: or tableView:willDisplayCellAtIndexPath, and ONLY do configuring. Other logic should be placed in some data(-controller) object.
As suggested, you should add an item to your data-array. Then call -insertRowAtIndexPath: on the tableView. ReloadData is like a big ugly hammer that you only use when ALL of the data for that tableView changes.
I have a UITableViewController with a few UITableViewCells. Each of those cells have different content: labels, images, text fields, etc. I am needing to set those pieces of content based around user interaction of my UITableViewController class.
For example: I have a cell that has a UIImageView in it. When a user taps the UIImageView I want a UIActionSheet to show. The problem is that I can't set the UIImageView as a property of the UITableViewController class. It has to be a property of a subclass for that UITableViewCell. But that means if I write the code for showing a UIActionSheet in the UITableViewCell subclass it won't show in the UITableViewController class.
My question is, since all of the objects within a UITableViewCell are in their own class, how do I alert the UITableViewController class when one of those actions happens?
Also, when a UIActionSheet is displayed it will need to show up in my UITableViewController class. If I select an item from that action sheet and wanted the text of that item to propagate to setting the text of a UILabel inside of a UITableViewCell, how could I do that?
With UITableViewController you control everything through the UITableViewDataSource implementation.
Here is how you can do it: make an int field in your model class that says which row needs to show a cell with an action sheet, and set it to -1 (which means that no cell needs to show an action sheet). In the tap handler of the UIImageView call the model, and tell it that the cell to which the UIImageView belongs needs an action sheet now. At that point you tell your UITableView to reload data. This sets the whole system in motion again - the table view calls back your data source to ask for the count, and then it calls again for the cell. This is when your data source looks at the model, sees that the row needs an action sheet, and returns a subclass of the cell with the action sheet visible.
Here is a diagram showing this sequence of events.
When the user is done with the action sheet, the action sheet needs to call the model again, and tell it that the action sheet is no longer needed (i.e. set the index back to -1). After that it should call the table view again, and tell it to reload the data. The sequence will repeat again, but is time there will be no flag asking for the action sheet, so a regular cell would be returned.
well, I simply suggest to use Custom UITableView Cell class, so when you are creating custom cell pass your uitableview controller to that class as parent. Now in your Custom Class you can add singleTap on UIImageView, from tap on it you can call method in your parent class via parent object you have already passed.
I'm building a blog reader app with a list of post objects in an NSArray.
cell.postTitle.text=post.Title;
I'm trying to find out which post has been selected and then set the corresponding cell.postTitle.text to a lighter font.
Somehow I have to remember this state when the navigationcontroller segue back to the top level (and destroyed?).
Can anyone tell me the best way to do this? Each post object has a postID. Maybe I can store this in NSUserDefault, but the list of read postID might grow too big over time.
Also there is didSelectRowAtIndexPath but in this method, I can't access the cell properties directly right?
If you are using a UITableView to display your information you should use the delgate didSelectRowAtIndexPath.
In order to make this work with a custom interface (I assume you have), you should create your own custom cell, subclass UITableViewCell and create a controller and xib. You can then register your xib to the table and use that. Then you can call the needed attributes.
Somehow I have to remember this state when the navigationcontroller segue back to the top level (and destroyed?).
This is best handled by using a delegate method by creating a custom protocol:
https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithProtocols/WorkingwithProtocols.html
When your user clicks the cell, you would call a delegate method which could set the postID value back in the top controller.
Also there is didSelectRowAtIndexPath but in this method, I can't access the cell properties directly right?
Yes, you can get at the cell. Check out this question and answer:
How to reach the current selected cell in didSelectRowAtIndexPath?
Alternatively, if you want to get at the data you used to create the table cells in the first place, in your didSelectRowAtIndexPath method you can used the indexPath.row value to get the value from your array that is at that index position and pass that via a delegate method.
Found a solution.
Just add the postId of the selected post to an NSMutableArray in didSelectRowAtIndexPath. Then in cellForRowAtIndexPath, I check to make sure that the postID doesn't exist in my self.readPostID array.
If it does I set the font to Helvetica Light, else set it to Helvetica Bold.
First I had to make sure to [self.tableview reloadData] every time viewdidappear.
Second, I just save my NSMutableArray of readPostId to NSUserDefault everytime viewDidDisappear and reload the array in viewDidLoad.
Also I had to make sure that cell reuse doesn't affect the font. The else condition fixed that.