Swift custom toolbar implementation - ios

I'm trying to implement a custom UIToolbar. The toolbar currently has 5 buttons: 3 change the content on the page (keeping the same toolbar with toggled item selected) & the other two segue to modal view controllers.
How to segment the code/views amongst the several different "pages"?
I currently have a class called ToolbarViewController that instantiates the toolbar with the different items. It has a generic action that switches the button titles "ON" and performs different actions depending on which one was tapped. Each subsequent VC that needs to have that toolbar just subclasses ToolbarViewController and the toolbar is automatically created without code replication.
By segueing this way, if the user is in tab1 and presses button1 the program crashes, because there's no segue from tab1 to tab1. One way I have been able to fix this is by having an initializer in ToolbarViewController that receives the "currentTab" and doesn't allow segues for that tab. This seems incredibly inefficient.
Another solution I've been considering is having a single VC that has the toolbar. By pressing a button, I would be able to change the View of that VC. This also has a problem, I can't have AutoLayout set in storyboard, because the VC doesn't segue to anything, just changes the view itself. This will become a problem when I need some complex views with constraints everywhere.
Are any of the 2 approaches I listed advisable? If not, what approach should I take & how should I implement these changes?

I think you should use a TabBar instead of a toolbar as you can achieve much of the same functionality I believe you are trying to achieve with greater ease.
However if you are determined to preserve the modal segues you can setup actions for each of your toolbar button presses. Give your toolbar buttons action properties.
In Swift:
UIBarButtonItem(title: "YourTitle", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(YourVC.yourMethod(_:)))
func yourMethod() {
(code here)
}
As far as your problem with AutoLayout, you should drop an empty view into your ToolBarViewController then create custom UIView subclasses with nibs. Setup the way you want each view to look in the nibs with your constraints. Then, in code, load each custom UIView Subclass into the empty view on your ToolBarViewController.
Good luck!

Related

Can't link my UITableViewController to my nested UITableView

I need to provide some background to explain how I got to where I am. I'm trying to create an interaction that involves different segues (slide up from the bottom, slide in from right) and, as far as I can tell I can't mix these two styles amongst scenes that are embedded in a Navigation Controller because the Show segue will only appear from right to left if I do.
The behavior I want is: Initial View Controller -> Settings (segue from bottom) -> -> detail for selected Setting ('standard' segue from right to left)
I also want to put a navigation bar in the Settings view so I can have a Done button that will close the view (slide out of sight from top to bottom) like this:
Interface builder won't let me add a navigation bar when I'm using a Navigation Controller and without one it looks like this:
So, I tried something from a thread that suggested nesting views. It almost works (the first screenshot above was taken from that code), but it resulted in a new problem. That problem is that I can't link the nested `UITableViewController' to my SettingsTableViewController.swift custom class. It's simply not an option in the dropdown list of classes and so I can't configure my table of Settings options.
Here's the hierarchy I now have based on the suggestion from that thread:
Also, I've confirmed that my SettingsTableViewController.swift is subclassing UITableViewController.
I'm stumped and would really appreciate some help.
If you try this,
Add a UIViewController and a UINavigationController(this automatically comes with a UITableViewController.
For example sake, add a button to the UIViewController, right click and drag to the UINavigationController and setup the segue to the following show in the image.
Add another UIViewController and right click drag from the UITableViewController to the new UIViewController and use a push segue, which you can reference when you do 'didSelectRowAtIndexPath'.
You shouldn't need to connect things, because your UITableViewController is the rootViewController of a UINavigationController. If you use a UITableViewController the only thing you should have in it's hierarchy is the UITableView, if you want other things, you need to use a UIViewController and add a UITableView, but I don't think you need this because you can achieve your requirements with the default options.
Comment if this does not make sense, good luck,

Passing through Segues, Determining what view the user is on and NavigationController buttons not appearing

Sorry for the long and possibly confusing question. In this I have 2 main problems with my code, those being: 1- When I embed my viewControllers in a UINavigationController and add a bar button item, nothing appears, yet it appears when I add it to the pageViewController. Secondly, I am wondering if there is a way to do this differently and use one button on the pageView (which appears on all viewcontrollers in it) and just determine what the user was looking at when they pressed the button and are taken to another viewcontroller.
I am trying to build a page-based application, and I have set up the application with 7 view controllers (One for each day of the week). I then have an AddViewController, where users can add data to a certain day. I was wondering if there is a way to only use 1 addView linked to the NavBar on the PageViewController, as when I embed all other viewControllers and add a bar button, it does not show up.
With the pageViewController being embedded, this is what it looks like with a bar button on it.
This then leads to:
Which works well, however I am wanting to pass data to various arrays (one for each viewController), and I want to know which ViewController the user wishes to add to (based off what day they were on). Is there a way to determine this and then unwind to the viewController and append the right data to the right array or should I have one addView per dayViewController? If that is the case, I am coming across the issue whereby the bar button items do not appear on the viewControllers when they are embedded in a navigationController. It looks like this:
StoryBoard: (Example: MondayViewController)
The outcome is a missing barButton: (Keep in mind I changed the tint Colour to white so it would be visible)
I was wondering if anyone has the answer to either of my problems, and once again, thanks for taking the time to look at this array of questions in one problem.
Any suggestions are welcome !
Rowan,
You can do this:
Create an UINavigationViewController and then embed an UIPageViewController in it.
In the data source for the UIPageViewController implement these two methods:
- pageViewController:viewControllerBeforeViewController:
- pageViewController:viewControllerAfterViewController:
Here you will return the correct instance of your DayViewController for each position (or nil if you are on the first/last page). Your data model would also be set here.
Add your "Add" bar button to the navigation bar of the UIPageViewController and let it push your AddViewController. When pushing the AddViewController provide to it the info on which day is currently visible. You will probably need to keep track of this your self. Use the - pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted: method of the UIPageViewController delegate.

UINavigationController for infinite navigation (nested folders)

I need to navigate inside folders and files in directory (from server). The problem is that I don't know the number of folders so it's not possible to use performSegueWithIdentifier statically. How can I use navigation controller with dynamically number of view controllers in swift? I want to "push" a new view controller every time a user tap on a folder in order to list files/folders inside it and I want to do it with UINavigationController so the user have the possibility to go back with "previous" button.
Both storyboard and programmatically approaches are ok.
Thanks you
Storyboards and segues are just a crutch. Think about how you would do this without them. At each level, to go down a level, you would just instantiate a new view controller and push it onto the navigation controller stack with pushViewController:animated:.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/#//apple_ref/occ/instm/UINavigationController/pushViewController:animated:
And in fact it takes only one view controller class to do this, since any instance can create and push another instance of its own class. The display of one folder is exactly like the display of any other.
So if you wanted to configure this notion in a storyboard, you would have a circular segue, that is, the view controller would have a push / show segue leading to itself.
I agree with #matt's answer, just create the controller and push it. For sake of completeness, you can do this in a Storyboard with a segue.
Here's how:
So that you can call the segue programmatically, add an additional prototype cell to your tableView. (You do this because you don't want the segue to be automatically triggered when the tableViewCell is selected. By using an additional prototype cell, the segue can be wired up, but it will never be triggered automatically since this prototype cell will never actually be instantiated.)
Control-drag from this prototype cell to the viewController icon at the top of the tableViewController. Select "Show" from the pop-up.
Find this segue in the Document Outline View and give it an identifier such as "showFolderSegue" in the Attributes Inspector.
Now, when you want to trigger the segue, call: self.performSegueWithIdentifier("showFolderSegue", sender: self)
You can use prepareForSegue to set up the new tableViewController as you normally would.
This method too works with a single tableViewController.

Use XLForm with a toolbar

I want to launch a XLForms view controller as a Form Sheet. I want the controller to have a toolbar at the top and then the XLForm tableview underneath it. How?
The view controller isn't a navigation controller and so I need to add a toolbar at the top (or bottom) where I can add buttons. So how do I do this?
It turns out that this is not too difficult. I just wish that it was documented somewhere.
All the sample code I could find showed the top view controller inheriting from XLFormViewController. In this case, the IB controller only requires a topline view.
I wanted to expand the view controller to have other components in it other than just a "View" object. I wanted a toolbar across the top and a couple of other things.
So, here's how I did it. I'm not sure that this is the best approach but it did work.
Create the View Controller in IB and add all the components you want.
Include a TableView object someone in your design
Go into the "Assistant Editor" and hook the TableView object to the "tableView" object defined in XLFormViewController.h by ctrl-dragging and dropping on the IBOutlet tableView object.
All other controls work as usual.
Important:
Do not treat the tableView object like a regular object. In other words, do not implement UITableViewDataSource and UITableViewDelegate methods.
Hope this helps.

A permanent navigation bar with UI elements

Our app has some upper view, that is visible all the time.
This bar has a UITextField, UIButtons, side scroller, and segment control, and they are dynamic.
When you hit them, the view behind them(full screen) is changing.
I was thinking about navigation control, or tab bar, but seems that they can't have a text field and a scroller on them.
So my main thought was to create some COSTUM view of my own.
Question is , how can I create a view in storyboard, and add it as a constant view, than create some other views(+viewcontrollers) that will be changed according to that upper bar?
I want to create 5 views in storyboard, and switch between them according to the bar.
Sounds like a job for a containment view controller to me. I've used technique many times to both create a set of static controls on the screen which you describe and inject reusable content into an app in several locations.
The basic concept is:
Setup you Heads Up Display(HUD) with all the UI you want (this will be your base UIViewController).
Create a UIView in it and call it your contentView or something of the like. This is where all your dynamic content will appear.
Then your backing view controller adds another UIViewController as a child and tell it to show it's view in the contentView you specified.
Your view controller continues to remove and add children putting their content into the contentView as needed.
If you are unfamiliar with the technique there are many tutorials(by NSCookbook) of do a web search for "view controller containment tutorial". There is also a good WWDC (2011) video introducing the concept Session 102 - Implementing UIViewController Containment.

Resources