Im trying to have 2 table views on the same view. They both are within the same UIViewController which implementes the UITableViewDelegate and Datasource. one of the tableviews is static and the other is dynamic. The dynamic table view is loading just fine using the methods from its datasource, but the static one is showing up blank. Normally I erase the datasource methods from the controller so the static TableView doesn't override what's already done on the storyboard, but now I can't because those methods are being used by the dynamic TableView.
How can I have both of then under the same controller?
As Putz says, you can set up your view controller to manage 2 table views by setting up your data source and delegate methods to check the table view that's passed in.
However, I don't think you can use static table views with anything but a UITableViewController, and a table view controller only knows how to manage a single table view.
The trick is to add 2 container views to your view controller that will contain 2 table views, and embed a different UITableViewController into each container view. Then each table view is managed by it's own table view controller. I have a project on github that does exactly this: https://github.com/DuncanMC/test
I've set up protocols that the parent view controller and the 2 table view controllers use to communicate, although you don't have to do that if your needs are simpler.
Here is the easiest option, that let's you keep a single VC for your delegate/datasource :
Set both tableviews delegate and datasource to your UIViewController.
Ctrl-drag from one of the static cells to your .h file, and create an IBOutlet collection ( called here staticCellsCollection). Add each static cell to this collection, careful with the order, it will be important.
Implement cellForRowAtIndexPath: this way :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == _dynamicTableView) {
// Do your dynamic thing
}
else if (tableView == _staticTableView) {
// Return the static cells one by one
// Here the static TV has only one section, and all cells are in staticCellsCollection
return staticCellsCollection[indexPath.row];
}
}
You also need to adapt numberOfRowsInSection and numberOfSectionInTableView but this is pretty basic (check which table is asking, and return appropriate values, for example staticCellsCollection.count for the number of rows of the static TV).
You may need to adapt this, for example if you want multiple sections in your static TableView, you should create an IBOutletCollection for each section, and handle the number of rows/sections accordingly, and return the correct cells. Anyway, this is pretty straightforward to implement once you get the idea.
You can have two tableView's use the same delegate functions. It's not amazingly pretty, but you can:
- (UITableViewCell *)tableView:(UITableView *)inTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(inTableView == tableView1)
{
...
}
else if
...
}
Put that type of logic into every tableView delegate function.
Related
So I'm developing an app where I have to display a table view as the content of a Static table view cell inside a UITableViewController, but I can't seem to populate it with my array.
Because I have two table views inside a UITableViewController, every time I try to add the Controller as it's data source the two tables contents are conflicted.
Does Someone know hot to bypass this?
Actually it is quite possible to have multiple table views using the same view controller as data source. There are many complex layout where this could be useful. To prevent your data from getting mixed up, just check which table view is asking for data in all of the data source methods, for example like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
YourObject *object;
if (tableView == _tableViewNumberOne) {
object = [self.yourFirstArray objectAtIndex:indexPath.row]
} else if(tableView == _tableViewNumberTwo) {
object = [self.yourSecondArray objectAtIndex:indexPath.row]
}
Setup cell ......
}
You need references to the two tableviews from where they were created of course
I want to achieve the following in xcode.
I have a view controller. Within this UIViewController I have a UITabBar. Below them is a UIView. What is the best way to add a UITableView to the UIView? Then being able to click on a UITableViewCell and opening up another UIViewController to show more information about the UITableViewCell?
Here is the current setup of my storyboard:
Could you offer me a solution to this problem? Thanks
You need a solution to your problem but I'm not sure what your problem is.
In storyboard, drag a UIView in your UIViewController. Then drag a UITableView (not controller) in that UIVIew.
You'll be able to see the view hierarchy on the left.
Then link your tableview datasource and delegate to the parent controller.
in your .h file, add the UITableViewDataSource and UITableViewDelegate protocols, also link your tableview as an Outlet.
In your .m files, add the tableview delegate methods (numberOfRowsInSection: and cellForRowAtIndexPath:)
I also suggest adding didSelect: among the tableview methods because, well, you'll need it.
and you're good to go. :)
It's actually the EXACT same thing as creating a tableview, except that your tableview is a subview of a UIView, which doesn't matter at all if it comes to code. The only thing you'll have to be "careful" of is to build your view properly in storyboard, and make sure the constraints don't make your tableview unusable for some reason.
Check one of my previous answers where I explain how to make a tableview and make it load another controller while passing data, which is something you might need if everything I wrote here still confuses you.
FOLLOW UP:
From your comments I understand that this subview of your UIView can be different things ; a tableview, a webview, and so on.
There are many ways to do that, and from my little knowledge I see two that can be easy and reliable (from my <1year experience as a developer...).
Get all the possibilities ready in your parent viewcontroller, if you only have 2 possibilities for example, that's "okay".
The best way is to prepare a container view (it's literally called container view) which would load different OTHER view controllers according to your needs.
I think option 2 is more reliable, because it will split the code into different classes, will allow you to modify each of them independently, and you can easily remove/add new views.
To my knowledge, you'll have some kind of switch statement in your parent controller that will load the desired UIViewController (or tableview or anything). Whatever you do there will just be as usual, but constricted to a smaller view inside another VC.
You can create that container view in storyboard and pre-link every other VC with segues (ToTable, ToWeb, ToCollection) are good examples for segue names that would link that container view to your 3 UIViewControllers.
Note that you can pass data if need be, but you would have all the separate controllers handle their own stuff even though it is visible inside your current vc.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [catagorry count]; //count number of row from counting array hear cataGorry is An Array
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
// Here we use the provided setImageWithURL: method to load the web image
// Ensure you use a placeholder image otherwise cells will be initialized with no image
[cell.imageView setImageWithURL:[NSURL URLWithString:#"http://example.com/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder"]];
cell.textLabel.text = #"My Text";
return cell;
}
these are the basic method to create a basic table view. to load an view controller corresponing to the cell click u can use did select row method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
/* //Pushing next view
cntrSecondViewController *cntrinnerService = [[cntrSecondViewController alloc] initWithNibName:#"cntrSecondViewController" bundle:nil];
[self.navigationController pushViewController:cntrinnerService animated:YES];
*/
[self performSegueWithIdentifier:#"identifier" sender:self];
}
I'm trying to figure out the best way for me to use the text from a UITableViewCell to set/change a UILabel in it's parent view. And I'd like it to be done when the user taps on a row. For more clarity, here is a simplified physical representation:
From this:
http://i.stack.imgur.com/O9ipE.png
To this, when the user taps on the row:
http://i.stack.imgur.com/fmeIb.png
I was thinking I probably just need to use delegates & protocols but then how would I actually change the UILabel? Wouldn't that just pass the text back, instead of passing it back and changing the UILabel? Also, I don't know very much about unwind segues, but could I use one of those to do this instead?
Yes, you would use a delegate method to pass the data back to the parent. Since you are using some kind of array datasource to populate the table, you already have access to those values in a clean format (instead of pulling from the tableViewCell's hierarchy).
From your table vc:
#protocol MyTableViewDelegate
-(void)didSelectText:(NSString *)text;
#end
then implement the -didSelectText: in your parent VC.
When the user selects the cell, you will have the indexPath, which gives you a section and row.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// It's good practice to do this check first
if([self.delegate respondsToSelector:#selector(didSelectText:)]){
//basically pull the value out of your data source and send it to the delegate
[self.delegate didSelectText: self.arrayDataSource[indexPath.section][indexPath.row]];
[self dismissViewControllerAnimated:YES completion:nil];
}
}
I was wandering if its possible to have more than one uiTableView in one ViewController.
For example:
tableView1 and tableView2 in one view controller.
Initial start up of view controller, tableView2 should be disabled and not visible.
tableView1 should show the data associated with it.
When user selects a row from tableView1... it should then show the data corresponding to the selected row in tableView2.
tableView1 should still be enabled, and if user selects another row, the contents of tableView2 should also change respectively.
Thanks for any help or guidance given. :)
Of course you can do this. This is 5 minutes in storyboard.
You should choose UIViewController (not UITableViewController!)
And create something like this:
Then you should create object references with a ctrl key.
You have to remember that you have to set delegate and dataSource in both tableViews to your ViewController:
And in yout second table view set initialView to hidden.
Then in your code in method - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath you should in first line call:
[self.mySecondTableView setHidden:NO]
and do all your stuff later. That's it.
EDIT:
Now i realize that you have set topic to "multiple" tableViews. This solution is messy enough for two TableViews. I suggest you to use container, and then all tableView will have own ViewController.
You can set different tags and outlets for this two TableView.
Then in
-(void)ViewDidLoad
self.yourSecondTableView.hidden = YES;
to hide second tableView
and when delegates methods was called
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
or
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
you can ask for tag like
if (tableView.tag == yourSecondTableViewTag)
return something
I have one parent class with one tableview.
That class is the delegate and datasource of that tableview as well.
Now I subclassed (derived) that class and made a child class.
I have one tableview in child class too.
Then I defined delegate and datasource functions in that child class, but it overrides parent class tableview data source/delegate methods.
But I want both of them to be separate.
However my Requirement is as Follows :
I want to retain a search bar and side button, on the top of all the viewControllers that search bar includes , a recent searches terms table underneath that.
So i thought of defining parent class for that and subclass other viewControllers from that class.
Am i doing it the right way ?
I assume you are talking about a view controller class. If I understood you right, then you are about to mess it up. Delegation is a way to avoid subclassing. Of course you can subclass the delegate - no problem. But you want a table view in the super class that owns a table in its view. And you want a subclass that has another table in its view plus the table that the superclass owns.
That is not impossible. But from your subclass' point of view, your subclass owns two table views. Even that is possible. Your view controller is the delegate of two tables (regardless of where in the view hierarchy they are declared and instanciated). When you now override the delegate and data source methods theny your subclass must either:
Determine which table it is dealing with/being called from. And then serve both tables appropriately.
Determine wich table it is dealing with/being called from. And then serve "its own" table appropriately and calls [super sameMehtod:withSamePamaters] to ensure that the superclas can still provide the data and server as delegate.
Which of both is smarter depends on the context and what you are about to achieve in detail.
A way of determinnig which table's delegate was called can be done by tagging the table views (do not use 0 as tag) or by comparing the tableView parameter of the delegate method with the corresponding properties (IBOutlets in this case). (In other cases you can compare the sender parameter with the IBOutlets. But tagging is probably easier to understand when reading the code later.)
Let's look at an example of the UITableViewDataSourceDelegat:
Your superclass implements:
#interface MySuperTableViewController:UITableViewController <UITableViewDelegate>
// There will be something in here.
// But it inherits self.tableView from UITableViewController anyway. We leave it with that.
#end
#implementation MySuperTableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// This method creates or re-uses a cell object and sets its properties accordingly.
}
#end
And your subclass:
#interface MySubTableViewController : MySuperTableViewController // no need to declare the delegate here, it is inherited anyway
#property (weak, nonatomic) IBOutlet UITableView *mySecondTableView; // self.table will be used by the superclass already.
#end
#implementation MySubTableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == self.table) { // This call refers to the one talbe that is managed by super
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
// This method now creates or re-uses a cell object and sets its properties accordingly.
// You may want to check wether tableView == self.mySecondTableView etc.
}
#end
(This comes from scratch, not syntax checked etc. Do not expect this to run properly right away :)
BUT ... please re-consider your class structure. I am afraid you are getting lost in some rather unlogical class hierarchy. There is nothing wrong with having two talbes managed by a common view controller even without this subclassing-thing. And there is nothing wrong with using multiple tables in a view where each of the tables has its own delegate (can be a view controller). Since iOS 5 (or was it introduces with 6) we can use the UIContainerView for that purpose and nicely build it up in IB/storyboard.
try this,
ViewController.h
IBOutlet UITableView *firstTable;
IBOutlet UITableView *secondTable;
ViewController.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
if (tableView == firstTable) {
return 1;
}
else if(tableView == secondTable)
{
return 1;
}
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
if (tableView == firstTable) {
return [arrItems count];
} else if(tableView == secondTable)
{
return [arrData count];
}
return 0;
}
etc etc ....