Augustyniak / RATreeView

Library providing easy-to-use interface for displaying tree structures on iOS and tvOS.
MIT License
2.49k stars 465 forks source link

Question: How can I use RATreeView with a storyboard? #160

Closed kmav closed 8 years ago

kmav commented 8 years ago

Is there any way to integrate with storyboards? For example, if there was some integration with tableviewcontroller then we could create segues more easy.

joshjack commented 8 years ago

Just like the examples, you need a class that implements UIViewController. In storyboard you can create a blank UIViewController instance. You can add toolbars, etc; and set up your segues. In the class implementation, manually add your RATreeview as a subview in ViewDidLoad (just like the example).

kmav commented 8 years ago

Thank you for your reply :)

I have already integrated with simple view controller storyboard object following the example. But, I think that the example is more focused on a programmatic approach, or I cannot understand how to integrate it in storyboards. Please find below my specific issues:

  1. When you touch a row, the children of the row/node unfolds. What I would prefer is to find out how I can create a segue/link to a next view controller to see details for the specific node. I think that the functionality to unfold on touch of a row is somehow buildin. Please correct me... I need the unfold functionality but I would like to link it with a button.
  2. Can I use a tableviewcontroller storyboard object instead of simple view controller and how the programmatic functionality of RATreeView can be integrated with TableViewController cells etc.?
  3. I use a navigation controller in front of the view controller (of the tree view). The first rows of the tree view table was covered by the navigation controller nav bar. So I had to create a view self.contentSubview, add this as a subview of self.view and add/instert treeview as a subview of the self.contentSubview, in order to fix that issue.

Please note that what I see in the example is more related on how to create a tableview programmatically as described here

AndrewSB commented 8 years ago

@kmav I don't think you can really use RATreeView as you'd like with storyboards, because it doesn't subclass UITableView, but UIView. So you need to take you UIView reference and then set everything up programmatically in viewDidLoad. Found a (much less popular) alternative library that subclasses UITableView, going to give using it a shot instead.

kmav commented 8 years ago

@AndrewSB Thank you for your feedback and the information for alternative library. In RATreeView library there is an RATableView class (private?) that inherits from UITableView. I wonder if I can use that to establish the integration. Also, regarding segues, i.e. opening a detail view when the user touches on a tree row, what I have noticed is that when you touch a tree row the children of that row are expanding/unfold. Can I change the functionality of touching a row to e.g. open a detail view and use some other control for expanding the children, or is this not permitted at all (this is how it is designed)?

joshjack commented 8 years ago

I apologize for missing your response to my initial comment.

When using a navigation controller you must use the "embed in" command in storyboard for any child view controllers to automatically add the toolbar and prevent overlap over sub views.

Regarding the expand/collapse functionality - implement the "should expand cell" and "should collapse cell" delegate methods to always return No. That will turn off the automatic expand/collapse action.

In my programs I use an addition style button that is only displayed by cells with children. Tapping that button calls "expand" or "collapse" on the cell, and reloads the tree view. I use delegate method implementation in the top UIViewController class just like the example. If you implement it there you can make calls to the RATreeView directly, where as if you implemented the method down in your cell class you'd have to pass messages back up to the parent to trigger tree reloads.

Capture the tapping action like a normal tableview cell with "didselect"

AndrewSB commented 8 years ago

@kmav I don't think it's possible to use the private internal class to make a table. I ended up just rolling my own solution for this, since I only needed one level of collapsibility it wasn't too bad.

Can share my solution if it would be of any help to you

kmav commented 8 years ago

@joshjack and @AndrewSB thank you so much for your kind assistance and explanations that show me the direction to follow. I will experiment a while and get back to you.

kmav commented 8 years ago

@joshjack After inactivating default shouldExpand/Collapse, what do you call to reproduce their behaviour with the '+' style button?

joshjack commented 8 years ago

@kmav it's a tree view command, something like [_mytreeview expandrowforcell:cell];

Because this is done as a code block using weak self inside the cell creation method (just like the demos), you have access to both the cell and the parent tree view.

kmav commented 8 years ago

@joshjack I have implemented most of what you suggested related to collapse/expand with an addition symbol and it works! performseguewithidentifier crashes, because, I think, as @AndrewSB pointed out, RATreeView cannot be used as a UITableView, so I cannot create in storyboards a TableView object and connect it to my RATreeView (I did not even tried). So, I cannot have a cell view to start ctrl-drag from it to my next detail scene.

What I did for the moment, is a programmatic solution in didSelectRowForItem as below:

- (void)treeView:(RATreeView *)treeView didSelectRowForItem:(id)item {
    TeamTableViewController *detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"UnitTeam"];
    if (detailViewController) {
        detailViewController.activeUser = self.activeUser;
        OrgUnitsChildren *dataObject = [self.treeView itemForSelectedRow];
        NSLog(@"... with unitID %d", (int)dataObject.unitID);
        [detailViewController setActiveUnit:[[Unit alloc] initWithName:dataObject.name unitID:[NSString stringWithFormat:@"%f",dataObject.unitID] lat:[NSString stringWithFormat:@"%f",dataObject.latitude] lng:[NSString stringWithFormat:@"%f",dataObject.longitude]]];
    }
    [self.navigationController pushViewController: detailViewController animated:YES];     
}

As for navigation controller and embed-in, this is how I use it. I have a series of scenes until RATreeView that the first of which is embed-in navigation controller. But, in connecting RATreeView ViewController scene with the next I cannot use segues at the moment as I said and the possibility that I have is using the code in didSelectRowForItem. In this way the navigationbar and title work. However, I still have issues for 3 first/last cells in RATreeView that are squeezed in bottom of scrollview of RATreeView ViewController. Finally, I think that in the provided example, the storyboard scenes are not used at all. There is a code in appdelegate that starts the RATreeView.

joshjack commented 8 years ago

@kmav here's an alternate approach:

1 - create a segue in storyboard that is connected not from a cell, but from the parent viewcontroller of the RATreeView. This is done by CTRL-CLICK dragging from the viewcontroller icon (yellow icon) at the top of the canvas to the next view. You will be prompted to choose what type of seque to use.

2 - name the segue like, "segueToTeamTBVC"

3 -

- (void)treeView:(RATreeView *)treeView didSelectRowForItem:(id)item {
            [self performSegueWithIdentifier:@"segueToTeamTBVC" sender:self];    
}

You'll still have to pass the "activeUser" somehow (I use a singleton class for that).

Last note - this line: `OrgUnitsChildren dataObject = [self.treeView itemForSelectedRow]; should be simplified to: OrgUnitsChildren *dataObject = item;`

kmav commented 8 years ago

@joshjack Yes. You have right! I failed yesterday with that ctrl-click and dragging, just due to bad arrangement of my scenes!!! Thank you very much for your help.