I want to create an layout in that I want to put UITableView(SubTableView) inside UITableViewCell of the first UITableView(MainTableView). The problem which I am facing is that when I call the Data Source method of MainTableView, then all the DataSource Method are initialised but when cellForRowAtIndexPath method is executed then my SubTableView in not calling its DataSource Method for particular row of the MainTableView.
Instead it calls the DataSource Method of MainTableView and then it calls the DataSource Method for the SubTableView. My concern is that I want to call DataSource Method for SubTableView when cellForRowAtIndexPath method is executed for the MainTableView for particular row.
Related
I am populating cells in a UITableView from CoreData and I have a question about how best to transfer the data I need to my DetailController (i.e. the viewController that shows when the cell is tapped).
Currently when populating the UITableViewCells I use the indexPath passed to the cell to retrieve the appropriate managedObject from Core Data. At this stage I only update the cell with a few bits of information from the managed object (i.e. name, age, sex).
After the UITableView has been fully populated I want to allow users to select a UITableViewCell and present a DetailController showing more in-depth information (i.e. name, age, sex, occupation, weight, height etc.) When the cell is tapped I am using -prepareForSegue to transition to the newly presented DetailController.
My question:
The "sender" for the segue is the UITableViewCell (subclass) but I have only populated this with the information I needed to originally display in the smaller cell. Should I
add more iVars to the UITableViewCell subclass and store all the data
I need,
keep a pointer iVar on the cell to the model managedObject
something else that I might have missed?
With the Model View Controller pattern we use in objective-c Your views should never know about your data model. This means that your UITableViewCells should not have any properties that store objects from your data model. Cells should only have labels and views as properties which your view controller fills in with data from the model in its -tableView:cellForRowAtIndexPath method or similar
You get the UITableViewCell object as the sender in prepare for segue. You can find out the index path for the cell with the following method:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
NSIndexPath * selectedIndexPath = [self.tableView indexPathForCell:sender];
...
You can then use this index path to pull your model object out of core data again, and set it as a property on your next view controller, or whatever you need to do to pass the model object forward
I have a number of custom cell objects (subclasses of UITableViewCell) with a couple of values in them to allow for user interaction within individual cells (like steppers or something). These values are stored within the custom cell class, since calling up to the owner of the table view seemed like a bad idea at the time.
I know of the function (NSArray *) visibleCells. Will that allow me to access the data within the cell objects?
If not, how?
I'm assuming that I can use the built-in functions of the UITableView to pull returned UITableViewCells, but is that sufficent when I'm talking about a subclass of that called, say CustomizerCell?
The function:
- (NSArray *)indexPathsForVisibleRows
Answers an array of index paths. Those index paths can be used the same way your cellForRowAtIndexPath uses the passed index path to access your model.
MyObject *myCustomDataSupportingACell = [myDatasourceArray objectAtIndex:indexPath.row];
What is the scope of the table view cell's reuse identifiers — are they shared within one table view instance or within all the table views that use the same reuse identifier?
Eg, I have a FooTableViewController and a BarTableViewController, both of them have a tableView and both of them use #"Cell" identifier in tableView:cellForRowAtIndexPath, but the cell properties/styling are different. The question is - will those cells be reused across table views or not?
They are never shared between instances.
A UITableView object maintains a queue (or list) of the currently reusable cells, each with its own reuse identifier, and makes them available to the delegate in the dequeueReusableCellWithIdentifier: method.
(from [UITableViewCell reuseIdentifier] docs)
Emphasis on "UITableView object".
However, you should make your cell identifiers more descriptive. A different identifier for every cell type you are using. Your code will be more readable.
They will only be used in a single UITableView, they will never be shared. Each UITableView has its own "pool" of reusable UITableViewCells
I want to put new values in a table view.
My tableView:cellForRowAtIndexPath: has the following
if (cell == nil) { // do something }
When I remove the if statement on top and use reloadData the app crashes. Do I need to clear the old values in the table before I use reloadData? If so how?
Thanks
Edit:
I'm sorry i didnt mean that i put reloadData inside tableView:cellForRowAtIndexPath:. i put it inside another method and removed if (cell == nil) { // do something } from inside tableView:cellForRowAtIndexPath:
You should read the TableView Programming Guide to familiarize yourself with the concepts. reloadData is a method that eventually calls tableView:cellForRowAtIndexPath:.
You are generating infinite loop by calling reloadData inside
tableView:cellForRowAtIndexPath:
There is no need to clear data in a table view. You may want to ensure you properly implement -prepareForReuse in your UITableViewCell subclasses though, so that reused cells don't show old data.
It's BTW unclear why you want to remove the if (cell == nil) bit. If there is no cell to reuse (dequeue) then you need to create a new one. If you don't you'll return nil, which will cause an exception in UITableView.
You (99% of the time) can't call reloadData from tableView:cellForRowAtIndexPath:.
This is because reloadData eventually calls tableView:cellForRowAtIndexPath, so you get a never ending loop.
You need to explain more what you trying to do (and some extra code would be nice) in order to answer the question further.
reloadData calls all tableView data source , so you cann't call it in cellForRowAtIndexPath it will make an infinite loop.
Hey, I'm looking for useful resources about Delegates. I understand that the delegate sits in the background and receives messages when certain things happen - e.g. a table cell is selected, or data from a connection over the web is retrieved.
What I'd like to know in particular is how to use delegates with multiple objects. As far as I know, specifying the same delegate for an object (e.g. table cell) would cause the same events to be called for both the cells at the same time. Is there anything equivalent to instantiating a delegate for a particular object?
Thanks in advance!
In Cocoa, objects almost always identify themselves when calling a delegate method. For example, UITableView passes itself as the first parameter of the delegate message when calling it:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
If you wanted the same delegate to handle multiple UITableViews, then you just need a some conditional on the tableView object passed to the method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.myFirstTableView) {
// do stuff
} else if (tableView == self.mySecondtableView) {
// do other stuff
}
}
}
If you don't want to compare the object pointers directly, you can always use the tag property to uniquely identify your views.
Usually, if you have a delegate method that might have to receive messages from many different objects, you simply have the calling object pass itself to the delegate in the message (method call).
For example, if you wanted a delegate method to extract the text from a tableviewcell's label, the method definition would look something like:
-(void) extractTextFromLabelOfTableCell:(UITableViewCell *) theCallingCell{
...
NSString *extractedText=theCallingCell.textLabel.text;
}
You would call the method from a tableviewcell thusly:
[delegate extractTextFromLabelOfTableCell:self];
Each instance of the tableviewcell would send itself to the delegate and the delegate would extract that instance's text. In this way, a single delegate object could handle an arbitrarily large number of cells.
A delegate is a way of adding behaviors to a class without subclassing or for attaching a controller to a class.
In the table view example you gave, the delegate is extending or controlling the table, not the cell. The table is designed to have a controller, the cell is not. This design choice is why you can't specify cell-specific delegates.
However, delegate methods will always announce the source object (the one to which the delegate is attached) and relevant parameters (like the cell involved) so you should always be able to handle the action fully.
In your case, if you have a cell and you would like the cell to manage itself, then the delegate method (which will probably be implemented on your UITableViewController) can simply fetch the cell from the source table using its NSIndexPath (passed as a parameter to the delegate method) and invoke a method on the cell subclass to do its work.
I always liked Chris Sells' ".NET Delegates: A Bedtime Story"