Best way to handle multiple UITableViews in one UIViewController? - iphone

I have a UIViewController that should be capable of displaying tableViews with multiple data sources. The UITableView spans about half the size of the screen, and there is and up and down button that allows you to go through different data. Everytime the up and down button is hit, I'd like to ultimately use UIViewAnimationTransitionCurlDown or something similar to display the next UITableView.
The question is: do I need multiple UIViewControllers to do this, with a tableView embedded in each one? Should I just create one instance of UITableView and change its data source when an up or down button is hit? If it's only one instance of UITableView, how do I manage to get a curl transition over the portion of the screen it takes up to make it look like a new tableView is coming in?

Why not have each table view belong to its own UITableViewController, and nest these within the current screen's view controller? This way the screen's view controller is responsible for swapping out its subviews, each of which have a table view controller containing the necessary logic to show their data.
In the end, it comes down to what your functionality and data sets look like. It may end up being easier to implement the table view datasource & delegate code once, injecting an actual data source into this class - or it may be easier to write custom datasource code for each table view.

Related

Swift - Reuse the old instance of view when switch between Views and Passing data over views

I am trying to create a simple app and here is how it works:
When the user clicks the button "Picking", it'll show a tableview. And when the user selects a row in the table view, it will show the first view and display the data on the label.
I have 2 problems:
Every time I click the button "Picking", a new instance of the table view controller gets created; but does not reuse the existing one. How can I make it reuse the old one?
I want to pass the selected data to the root view. I tried by creating a segue to show the root view when user selects a cell and then passing the data on prepareForSegue method. But, I faced the above problem of memory leak. How do I pass the data between screens without leaking memory?
It sounds like you may be making a circular view hierarchy. When you tap on the cell in the table view, if you're pushing a new instance of the first VC, that is the wrong way to do it IMO.
Instead, you should pass the data back to the first VC then dismiss the second VC. Then, when you tap on the "Picking" button again, it's a new instance of the table view but your previous instance has already been removed from memory.
This allows for the smallest amount of memory to be used at any given time. When the table view controller isn't on the screen, it doesn't need to be in memory.
IMO, the best way to pass data up a navigation stack is to use a protocol and delegate. It's similar to how Objective-C protocols and delegates worked if you're familiar with that. Here is Apple's documentation on both. The delegate section is about 1/3 the way down the page.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html

Implementing another table view in a UITableViewController ios

I need to add a new table view to my UITableViewController which will includes a different data and design.
the above prototype cells is the new table view I've added in storyboard, and the main table view is the second one which includes (title, label, and image).
Is it allowed to create another table view in UITableViewController, or should I create a UIViewController and implement the two tables in it???
In fact, I've finished the implementation of the first table view controller, so I need to implement the new one.
the attached image is showing what I want:
You will be better off with a UIViewController that has two tableViews as subviews if you want both of your tables to be shown at the same time. UITableViewController should be used only when there is just one tableView shown at a certain time.
You can either have one UIViewController being the dataSource and delegate for both of the tableViews, or have a UITableViewController for each of your tables and add them as subviews to a UIViewController that will be a container view for both of them. The latter will probably save you some time debugging possible issues as having two tableViews with a single delegate/dataSource requires a lot of duplicate code in the same place.
I think you should use UIExpandableTableView
there is detailed usage on github page
Scree example of UIExpandableTableView
Are you looking to have them be two independent tables, or is it a master/child setup?
If they are independent, I suggestion using one table and two sections, then depending on the section number return to correct cell.
For master/child, think about making a view that looks like a cell and have the master cells be the sections views and the children be the actually rows. You can make a section class that stores if the children are visible or not and in the numberOfRowsInSection method return the count if visible or 0 if not.
Just a couple ideas

reuse view from storyboard

I have a tableview with custom section headers. The view for the section header is defined in the storyboard and wired to an instance variable. Is there a way to request a new instance of the view from the storyboard?
In the past I have done this by having the section header defined in its own xib file and getting a new instance by using
[[NSBundle mainBundle] loadNibNamed:#"TimerViewSectionHeader" owner:self options:nil];
UIView *newHeaderView = self.sectionHeaderView;
I dont' think there is a way to do that. Best bet is to put the tableview custom header view in a separate nib and load it like you did in your code sample whenever you need to use it.
I tried to do the same thing and ran into the same problem.
I like to work with storyboards a lot and was impressed how fast I could create a working UI. However, as soon as you need to re-use views it makes a lot of sense to put those into a separate nib along with its UIViewController subclass.
You can then place a generic UIView in all the places where your re-used view should go and add the view using your ViewController:
[myReusableViewController loadView];
[myReusableViewController viewDidLoad]; // You have to handle view callbacks yourself.
[self.myReusableViewPlaceholder addSubview:myResusableViewController.view];
[myReusableViewController viewWillAppear:YES];
So to sum it up:
Use storyboard, it's great
Create the scaffold of your application in the storyboard, along with any static view (like About screens etc.)
Create re-used views in a custom nib + UIViewController subclass and add UIView placeholders in your storyboard.
In another answer I thought about some Pros and Cons of Storyboard
The solution I've come up with for this is as follows:
I have a tableview with multiple prototype cells that displays complex data. There is a segue to a detail view, and a transaction process view.
This first tableview has a search button that displays a new tableview with the results. It needs the same functionality as the main tableview that pushes it; including segues to the detail and transaction progress views so:
On storyboard, select and copy your main tableview. Deselect and paste. Create a push segue from your main tableview to your 2nd tableview; or from where ever you want to navigate to it from. Modify the 2nd tableview as you like. IE: If it requires some UI changes no problem.
Create a new viewcontroller class that is a subclass of the viewcontroller running the main tableview.
Override the data delegate in your subclass to serve up the subset of data you want.
Back in the storyboard, select your 2nd tableview controller and in the identity inspector select your subclass as the custom class.
For this solution to work smoothly, your app really needs to be managing data for the views. You could use prepareforsegue to pass data from 1st tableview to the second, but I've found the app data model far more flexible from numerous points of view.
Unless you have buttons that push to the sub views via segue, your subclass will need to override functions that push via segues with identities. NB Segues must have unique identifiers if you id them at all.
It took a lot of trial and error to figure this out, but once you understand the concept, it's a relatively smooth solution that is quite adaptable and not so bad to implement.
I am not sure about just views, but the way that I was able to get view controllers out of my storyboard is as follows.
UIViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"IdentifierName"];
From here, perhaps you might be able to use this similarly to how it was once done with nibs.
I've been able to reuse a view in the storyboard just by connecting a transition from one tableview into the one I want to reuse.
so my tableview that I want to reuse is pointed to twice.
It sort of works but the problem I'm running into it setting a variable (using instantiateViewControllerWithIdentifier) in my app delegate to my table view that is getting reused.
It seems that if I reuse it, the storyboard is creating 2 instances of my tableview and the one I get with instantiateViewControllerWithIdentifier isn't the one I want.
I'm not really sure if this is the proper way to do it. But I assume many others are doing this somehow. With the custom table cells in storyboard I suspect lots of people want to reuse their views.
For example: We want to reuse the view(include subviews) in storyboard shown below.
The best solution I know so far is clip and paste the view related code to the New Singe View file without losing the information.
Detailed steps are as follows
Step 1: Rename the view we want reuse. Just prepare for step 2.
Step 2: Open storyboard as source code in order to clip the XML code we need
Step 3、4: Search and clip the code we need
Step 4.5(Not needed): Open as Interface Builder to see the view removed
Step 5、6: New XXX.xib and paste the code we clipped just now
Step 7: Important. Insert code<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> to XXX.xib source code.
Warning: Do this before open it as Interface Builder! Otherwise, you will see wrong size and layout waring.
[![step 7][9]][9]
Step 8: New XXX.swift to connect the XXX.xib
[![step 8][10]][10]
Step 9: Add the view anywhere we want
[![step 9][11]][11]
I get warning: "You need at least 10 reputation to post more than 8 links."
Can you support me to upload the remaining 3 screenshots?

How to switch to a TableView from a first View?

I'm working on my first app and I've issues on how to layout some of its logics.
Basically, what the app is supposed to do is to show a first screen when launched where user can fill in some values and press a button that opens a tableview which shows results. The first screen (view), outlets and connections are all working fine. The issue I'm having is how to leave this "home" search view and show the results to the end user on a table view. Right now, I've only 1 view with its related View Controler and this controller handles the tasks of taking user inputs and get results throughout a HTTP post request.
I need your guidance...Thx in advance
Stephane
Is there a reason that this all has to happen on one screen? iOS is set up to allow for this to happen very easily and (I think) attractively by using a UINavigationController and pushing in a new view controller (could be a UITableViewController or simply a UIViewController that contains a UITableView).
If you MUST have all of this take place in one view, Swastik is correct that it will require some view acrobatics. One way to do it attractively is to use the UIView animations introduced with iOS 4.
Here's Apple's UIView documentation: UIView Class Reference
Specifically, check out the CLASS methods of:
1. animateWithDuration:animations: (with or without completion:)
2. transitionWithView:duration:options:animations:completion:
Note that these methods will require you to learn a little bit about blocks, but it's worth it and I think blocks give tremendous power!
With the methods mentioned above, you could fade out your form and fade in your tableview, or maybe just move the form off-screen while the table view flies in. The possibilities are limited only by your imagination.
u can add a table in ur xib.Initially make it hidden, & when u need to show it unhide it & also if u want to update table's data , you can reload the data of the table.

how to manage a stack of UITableViews without a navigation controller

I am new to iPhone development, and I am working on modifications to an existing iPhone app. The high-level overview of the issue is this.
I have a button displaying a pop-up containing a UITableView.
I'd like to click on a menu item and display a second UITableView with sub-items, including a back option. If the user clicks back, they go the original UITableView. If the sub-item has additional sub-items underneath it, it should (when clicked) launch another UITableView with these options. There is also a back button as a menu item that will allow the user to navigate to the previous menu displayed.
The challenge here is that I am not using a navigation controller. the original developer only wants to add UITable Views to the stack, add transitions between them as you go from one menu to the other. Most of the tutorials I have seen and tried utilize a navigation controller and Interface Builder to associate the UITableViews.
Right now, I have an XML data source populating the menu, and when I click on a menu item, the titles change correctly, but still uses the same UITableView to display the options - this has consequences of course, as some of the sub-items may not fit on a screen.
any thoughts on how this can be done? I can post some code if necessary, although I think the general description should be able to ring a bell with one of you smart guys!
This can be done in numerous ways.
I haven't done this first one, but you can probably create a UINavigationController and set its view to the appropriate frame (inside the bubble) hide the navigation bar and set the action of your back button to pop the current view controller.
Another method is to have multiple tableviews on one controller, the delegate and datasource methods have the UITableView as an argument so you can distinguish them when setting the height of your rows, headers etc and when returning a UITableViewCell.
The way I've chosen to deal with such configurations is to have one UITableView and have only the datasource change. When you reload, insert, delete rows or reload the whole table, you can change anything you want depending on the current datasource level. The easiest none animated way is to reload the whole table.
a) If your "options" go off-screen height wise (you want fixed height) table change the - (CGFloat)tableview:(UITableView *)table heightForRowAtSection:(NSInteger)section return value
b) If your "options" go off-screen length wise either make your cell's default textLabel flexible: cell.textLabel.adjustsFontSizeToFitWidth = YES; cell.textLabel.minimumFontSize = 14; or have custom cells (lookup subclassing UITableViewCell, which is recommended) for each datasource level.
If you subclass TableViewCells remember to have different dequeue cell identifiers for each level, so the table doesn't provide you with another level's cell class.
For the "stack" of tableviews or datasources, you can have an NSMutableArray with addObject for push and removeLastObject for pop.
For animations, UITableViews can animate their rows/sections for 3. (see documentation for insert, delete, reload - Rows/Sections UITableView class reference), for 2. you can even have UIView (if not CoreAnimation as Grimless suggested) animations, that move the current tableview to the left (setFrame:) and the next tableview from the right (setFrame offscreen before animation and then in place in the beginAnimation-commitAnimation clause), but make sure you add the tableviews in a container view (the bubble interior) that clips its subviews.
Oi. This is gonna be a tough one. My suggestion would be to maintain your own stack implementation. Then, use CoreAnimation to add/remove UITableViews from your main view controller to get animated effects. So whenever the user clicks on an element in the current table view, the appropriate controller creates a new controller and table view, and then your custom navigation controller pushes the old one onto the stack, removes the old table view from the main view, sets the new controller as the current one, and adds the new table view to the main view. Kinda messy, but I think it will work.