I ran into a piece of code for UITableView, click on of the cell and it reloads but what exactly is the data source? I am not too clear on this.
[xTable reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:button.tag inSection:0],nil] withRowAnimation:UITableViewRowAnimationFade];
It runs the following "tableview cellForRowAtIndexPath" method and loads the updated information for the specified cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Hope it helps.
DataSource is a protocol in the UITableView that defines a set of messages that the UITableView sends to this object(datasource)
These messages returns data that is filled inside the tableview
Some messages are like:
numberOfRowsInSection: you will return the number of rows this table will have
cellForRowAtIndex: you will return here the UITableViewCell object for the given index
numberOfSectionsInTableView: you will return the number of sections this table will have
How this works
in your class you will call tableView.dataSource = self;
[UITableView reloadData] gets executed, the datasource messages get sent to the datasource object (in this example it will be the object set on the right side of .dataSource = self;
table view will use these consecutive calls to build the table view itself
For further indepth reading please rever to
Simple tutorial on how to implement the datasource in iphone
Data Source design pattern
Related
The master-detail project created by XCode wizard contains implementation of tableView:cellForRowAtIndexPath: that calls dequeueReusableCellWithIdentifier:forIndexPath:, then calls own custom method configureCell to fill the cell controls with valid data, and then returns the cell to caller. As I understand, this is how table knows how to draw its cells content.
What I don't understand is how to use it when I want to get cell from my code. And is it even supposed to be called by my code, or is it only a callback used by table framework itself?
For example, if I just want to change text of one label in cell, I thought I can just call tableView:cellForRowAtIndexPath:, and change what I need in the resulting cell object controls. But calling tableView:cellForRowAtIndexPath: actually makes a new cell object (probably reusing one from pool of unused cell objects) and fill ALL controls like imageviews and labels in it with data. This does not look good to me regarding to performance, when I want change just one label.
So maybe I could remove configureCell out of tableView:cellForRowAtIndexPath:? But then how to ensure all cell contents will be redrawn by system when [table reloadData] is called?
P.S.
XCode 7 wizard created this kind of code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
[self configureCell:cell withObject:object];
return cell;
}
// Then later in controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] withObject:anObject];
break;
configureCell is called twice here. Seems like non-sense to me. I hoped at least people who write code for wizards understand how this is supposed to be working.
There's two different methods being called here that have similar names.
tableView:cellForRowAtIndexPath: is a UITableViewDataSource method that you implement to create the cell for the table to show. The tableview calls this method when a new cell is going to come on screen.
controller:didChange:... is calling a different method called cellForRowAtIndexPath: which is a UITableView method. This method queries the table for a cell that is already being displayed after previously being created using the tableView:cellForRowAtIndexPath: datasource method and doesn't result in it being called again. It's calling this method to access the already displayed cell and update it with new info when the object changes.
Both calls to configureCell are necessary.
I haven't developed any iOS apps in a while. I am fine with both swift and Objective-C but what I find different is adding a UITableView to ViewController. Before, I used to add a UITableView to ViewController, add the required datasource methods and the typical UITableViewCell object, and return the cell in cellForRowAtIndexPath:, which would display empty cells depending on the number of rows I return. Now, I did everything the same, but the UITableView is empty and when I scroll I see the lines but not my cell.textlabel.text value, which I set. It seems now I am supposed to add UITableViewCell to the UITableView and remove the
#pragma-mark TableView Datasource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_formTitles count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:#"cell"];
if(cell==NULL)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"cell"];
}
cell.textLabel.text=[_formTitles objectAtIndex:indexPath.row];
cell.detailTextLabel.text=#"Kaushik";
return cell;
}
I can't find a simple post online regarding the same.
Can someone post what are the changes in the new iOS 9 in a simple manner?
Thank you
Right..For those of you who are still prefer to add a tableview to a viewcontroller.Here are the steps
In the ViewController drag and drop the tableview.Now instead of the lines which you see in the old Xcode.This time you would see a blank table view with the text " Table View prototype content" in the middle.
We usually create a tableviewcell only we doing anything different like adding more labels or image etc but hereafter it is required to add a tableviewcell in the tableview.Drag and drop a tableview onto the tableview.It will display as protype cells.One can select type of cell here itself as basic,value 1,value 2 or subtitle.Also NEED TO SET THE REUSE IDENTIFIER IN THE STORYBOARD UTILITIES PANEL ON YOUR RIGHT. At the end, you can select the tableview and add the missing constraints.
Implement the typical required datasource methods in your viewcontroller class.
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:#"cell"];
cell.textLabel.text=#"text";
cell.detailTextLabel.text=#"DetailedText";
return cell;
}
The change here is that we dont require the usual if(cell==nil)
{..}
piece of code since we added the prototype cells to the storyboard.
Don;t forget to connect the delegate and datasource of the tableview to the viewcontroller.
This should display the tableview in your viewcontroller but i am getting a space on top of the tableview which i don't know why.Anyway this is how you add a tableview to a view controller using Objective-C language in iOS 9.3.
FYI: Guys if i've missed anything, please mention it in the comments
Thank you
Put tableView to view controller and link it to viewcontroller.
link delegate and datasource of tableview to viewcontroller.
in
viewcontroller.h
#interface ViewController :<UITableViewDelegate, UITableViewDataSource>
in viewWillAppear put
tblService.delegate=self;
tblService.dataSource=self;
and your array elements.
5.Impliment your tableview delegate method and datasource method .
6.be sure you cell identifier equal the one put on storyboard.
this link will help you more to implement your first app and this video.
I'm calling a function in which i retrieve a NSDictionary with data that needs to be displayed in tableviewCells. Is it possible to call the method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
in another method?
It is not possible to call that one specific method inside another method. However, you can call [self.tableView reloadData] inside any methods. This call all the UITableView delegate methods which includes - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
You can explicitly call any methods of UITableViewDataSource and UITableViewDelegate, but should only be done in cases of dire need. In a project of mine, I get specific (subclassed) cells which draw elements not in the drawRect: method, but in a drawCell method I have defined, for performance gains (preventing offscreen rendering, etc).
Unless your cells have special drawing needs, (resizing subviews, etc) you should let the cellForRowAtIndexPath: method do this work for you.
Still, if you want to explicitly get cells, you may do with:
[yourTableView cellForRowAtIndexPath:indexPath];
This will return you your cell. Mind you, it will execute all relevant code inside the cellForRowAtIndexPath: including dequeueing, creation, and any other calls you have made in it.
indexPath passed here is an object of type NSIndexPath, and you may create one like this:
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:ROW_NUM inSection:SECTION_NUM];
Where, ROW_NUM is the is the row number inside the section, which is SECTION_NUM. For the first cell in the third section, the indexPath is:
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:0 inSection:2];//Since indices start at 0
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 want to do the following:
I have to create a UITableView at the runtime depending upon some conditions, at the run time only I will come to know from which database table the data has to be pulled from to be presented in the UITableView to make this problem more complicated I will have to create a custom UITableViewCell also at the run time.
I am not able to think how do I create this UITableView and then how do I create all those delegate method at the runtime.
I will give some more background that will help understand this problem, I am making a request to my server, and the server returns me an xml response object, after parsing I figure out that I have to present a table to the user on a particular action and the table will have custom cell, for which the values are available in the xml response object.
Please help I have been trying to figure out this thing for a while now.
EDIT:
I will try to explain in a different way, if that helps people understand my problem.
Hi, I want, to do the following:
On the runtime(which means while my app is running) I have to create a UITableView depending upon some conditions(some action taken by the user), I will make a server call and will get the data for the UITableView.
There has to be a a custom UITableViewCell for this UITableView that I have created at the run time, I will get the information for the custom UiTableViewCell also at the run time.
So basically I don't have any thing at the compile time except that I may have to create a UITableView and a custom UITableViewCell.
I am trying to figure out that how do I create the delegate method and custom UITableViewCell at the run time.
One thing that I thought was to have a default class with all the delegate method and when I create UITableView at the run time associate this class as the delegate for the newly created UITableView, let me know if this is an ok solution.
But how do I associate the custom UITableViewCell to this delegate method at the run time is still an issue.
You just need to get the new values that you would come to know during the run time and then use [tableViewObject reloadData];
The delegate functions will remain the same. In IB just place the UITableView wherever you want and set the delegate and datasource to the file owner. Set the hidden property to yes by checking the check box.
Once the user does some action change the hidden property in the action function as tableViewObject,hidden = NO;
Your delegate methods will look like
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath (NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"acell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"acell"] autorelease];
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
In this tableData will be your datasource that could be declared in your .h file. In the function that captures the action of the user, you can get the data from the server and add it to the tableData and then as suggested earlier call [tableViewObject reloadData];
After you are done parsing the reply from the server you should call
[tableView reloadData];
And in the method [tableView:cellForRowAtIndexPath:]
Depending upon some values or identifiers that you have for each database load values from that particular database and render it into tableView cell.