I am new to IOS,
I would like to add a UINavigationBar to UITableViewController, I have tried this:
var navBar: UINavigationBar = UINavigationBar(frame: CGRect(x:0, y:0, width:320, height:80))
then,
self.view .addSubview(navBar)
Thanks
You can not simplly add a NavigationBar to UITableViewController like that.
The simplest way to have UINavigationController and NavigationBar is to do it from Storyboard.
Steps:-
Drag the UITableViewController Object from Object Library to the Storyboard.
Highlight the UITableViewController, go to Edit -> Embed In -> Navigation Controller like the screen shot below:-
Go to File -> New -> File.. -> iOS -> Cocoa Touch Class, and create a Custom TableViewController class like below screen shot:-
Finally, go back to storyboard and highlight the UITableViewController object. Under the identity inspector, choose the custom class that you have just created like the screen shot below:-
You may do whatever you want with the custom class file. You may also add a custom UINavigationController class as well if you want and you may attach the custom class to to the object inside the storyboard.
If this is merely the case of showing a modal UITableViewController with a navigation bar, the easiest way to do this from code is to present a UINavigationController with your UITableViewController as the rootViewController:
Presenting view controller:
let sourceSelectorTableViewController = SourceSelectorTableViewController()
let navigationController = UINavigationController(rootViewController: sourceSelectorTableViewController)
self.presentViewController(navigationController, animated: true, completion: nil)
Destination modal UITableViewController:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Plain, target: self, action: "cancel")
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: "done")
self.title = "Pick a Source"
}
func cancel() {
self.dismissViewControllerAnimated(true, completion: nil)
}
func done() {
//save things
self.dismissViewControllerAnimated(true, completion: nil)
}
Well the best solution will be presenting the
UITableViewController
as
UINavigationController
let topicsList = TopicsListViewController()
let topicsListNavContrl = UINavigationController(rootViewController: topicsList)
presentViewController(topicsListNavContrl, animated: true) { () -> Void in
print("completed")
}
you can do that programmatically .
DataTableViewController *vc = [[DataTableViewController alloc] initWithStyle:UITableViewStylePlain];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentViewController:nav animated:YES completion:nil];
Related
I have created CustomNavigationController and added some common methods to add UIBarButtonItems to it. Now I want to call those methods from my various viewControllers.
So my question is - How to call methods which belongs to customNavigationController from any other viewController.
I can achieve this in objectiveC by following way :
[(CustomNavigationController *)self.navigationController addLogoutButtonWithVC:self actionLogoutHandler:#selector(actionLogoutHandler)];
where "addLogoutButtonWithVC" is method belongs to CustomNavigationController.
I am trying somewhat in above lines in Swift but no luck.
[Note : I have already replaced NavigationController with CustomNavigationController in storyboard when embedded in, so all navigationControllers are now pointing to CustomNavigationController only]
"Update : Declaration of addLogoutButtonWithViewController and actionLogoutHandler inside CustomNavigationController"
func addLogoutButtonWithViewController(viewCont : UIViewController , selLogout : Selector) {
currentController = viewCont
var barButtonItem : UIBarButtonItem?
barButtonItem = UIBarButtonItem(image: UIImage(named: "Logout.png"), style: UIBarButtonItemStyle.plain, target: self, action: Selector("actionLogoutHandler"))
self.navigationController?.navigationItem.rightBarButtonItem = barButtonItem
}
#objc func actionLogoutHandler() {
print("Inside logout")
currentController?.navigationController?.popToRootViewController(animated: true)
}
Any help in this regard is highly appreciated.
You should try my code as below.
you need object of your navigation controller and use to set in button target.
if let navigationcontroller = self.navigationController as? CustomNavigationController {
navigationcontroller.addLogoutButton(withVC: self,
actionLogoutHandler:#selector(navigationcontroller.actionLogoutHandler(_:))
}
#objc func actionLogoutHandler() {
print("Inside logout")
self.popToRootViewController(animated: true)
}
It should looks like:
if let nav = self.navigationController as? CustomNavigationController {
nav.addLogoutButton(withVC: self,
actionLogoutHandler:#selector(CustomNavigationController .actionLogoutHandler(_:))
}
Try this:
guard let customNavigationController = self.navigationController as? CustomNavigationController else { return }
customNavigationController.addLogoutButtonWithVC()
I need your help.
I'm developing a app without Storyboard (using xib), in my project I have two views controllers.
In the main view (after a login) I need to put a button on top of the view to open a left side menu.
This is how I call the MainView on LoginViewController
#IBAction func logar(){
let vc = MainViewController(nibName: "MainViewController", bundle: nil)
self.navigationController!.pushViewController(vc, animated: true)
}
I imported SWRevealViewController, and this is my MainViewController:
import UIKit
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//hide BackButton
self.navigationItem.hidesBackButton = true
//image
var image = UIImage(named: "menuBtn")
image = image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
//lefBarButonItem
let newBackButton = UIBarButtonItem(image: image, style: .Plain, target: self, action: #selector(MainViewController.openMenu))
self.navigationItem.leftBarButtonItem = newBackButton;
}
func openMenu(){
let frontViewController = LeftMenuTableViewController()
let rearViewController = MainViewController()
//create instance of swRevealVC based on front and rear VC
let swRevealVC = SWRevealViewController(rearViewController: rearViewController, frontViewController: frontViewController);
swRevealVC.toggleAnimationType = SWRevealToggleAnimationType.EaseOut;
swRevealVC.toggleAnimationDuration = 0.30;
//set swRevealVC as rootVC of windows
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window!.rootViewController = swRevealVC
}
}
When I press the button the LeftMenu occupy all the view, not like a partial view.
Any help would be appreciated. Thank you!
I would like to use the solution provided by Travis M. to this question:
How to use dismiss an iPhone popover in an Adaptive Storyboard
However, I would need the below be translated to objective c.
Anyone could help out?
If what you want is a popover on your iPad but a modal sheet with a close button on your iPhone then you can do it without creating an extra navigation controller in storyboard for the popover.
In Xcode 6.3 storyboard, you simply hook up a view controller and designate the segue as a "Present as Popover"
The code below should go in the view controller that segues to the popover, not in the popover itself:
First you set up the popover delegate:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "myPopoverSegueName") {
let vc = segue.destinationViewController
vc.popoverPresentationController?.delegate = self
return
}
}
Then you add the delegate extension (below your view controller's code) and create the navigation controller / close button on the fly:
extension myViewController: UIPopoverPresentationControllerDelegate {
func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
let btnDone = UIBarButtonItem(title: "Done", style: .Done, target: self, action: "dismiss")
let nav = UINavigationController(rootViewController: controller.presentedViewController)
nav.topViewController.navigationItem.leftBarButtonItem = btnDone
return nav
}
}
Then you add the delegate extension (below your view controller's code) and create the navigation controller / close button on the fly:
extension myViewController: UIPopoverPresentationControllerDelegate {
func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? {
let btnDone = UIBarButtonItem(title: "Done", style: .Done, target: self, action: "dismiss")
let nav = UINavigationController(rootViewController: controller.presentedViewController)
nav.topViewController.navigationItem.leftBarButtonItem = btnDone
return nav
}
}
Then you add your dismiss function and you should be good to go:
func dismiss() {
self.dismissViewControllerAnimated(true, completion: nil)
}
It's not that different from objective-c. You could probably figure out what's going on just by looking at it. It's just setting up prepare for segue and implementing part of a protocol.
myViewController needs to declare itself as conforming to UIAdaptivePresentationControllerDelegate. Then this is the code.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"myPopoverSegueName"]) {
UIViewController *viewController = segue.destinationViewController;
viewController.popoverPresentationController.delegate = self
}
}
- (UIViewController *)presentationController:(UIPresentationController *)controller
viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style
{
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismiss)];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller.presentedViewController];
navController.topViewController.navigationItem.leftBarButtonItem = doneButton;
}
-(void) dismiss
{
[self dismissViewControllerAnimated:YES completion:nil];
}
You don't need to use an extension or category. Not going to vouch for whether this does what Travis M. says it does.
I'm a swift newbie and made a demo app which has a UIViewController and UITableViewController in the Storyboard. The UIViewController has a Collection View and an embedded navigation controller. On tapping a collection view cell, the app segues to the UITableViewController. I can come back to my UIViewController from the UITableViewController as well. All this works well. Now, some of the rows in my UITableViewController have URLs. On tapping a URL, I programmatically create a webview inside a UIviewcontroller and get the URL to load in it. The issue is that I can't dismiss the webview and get back to my UITableViewController after this. This is the code I have in my UITableViewController class :
// When user taps a row, get the URL and load it in a webview
let mywebViewController = UIViewController()
let webView = UIWebView(frame: mywebViewController.view.bounds)
webView.loadRequest(NSURLRequest(URL: url)) // url from the row a user taps
mywebViewController.view = webView
self.navigationController!.presentViewController(mywebViewController, animated: true, completion: nil)
How can I add a Done button to this programmatically created UIviewcontroller to dismiss the webview and get back to my UITableViewController
You can wrap the mywebViewController in a UINavigationController then set the rightBarButtonItem to UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "dismiss") like this:
let navController = UINavigationController(rootViewController: mywebViewController)
mywebViewController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: self, action: "dismiss")
self.navigationController!.presentViewController(navController, animated: true, completion: nil)
and add a dismiss function in your UITableViewController:
func dismiss() {
self.dismissViewControllerAnimated(true, completion: nil)
}
Add done button to your presented ViewController and make an action for it.
To dismiss ViewController try this :
self.dismissViewControllerAnimated(true, completion: nil)
You can do one thing.
As you are pushing your mywebViewController into the navigation controller, make the navigation bar visible.
By simply tapping on Back button in the navigation bar you can easily dismiss your mywebViewController.
Hope this helps you. :)
Add button in mywebViewController and in its #IBAction, call
self.dismissViewControllerAnimated(true, completion: nil)
Update for Swift 4 & 5
In the VC you're navigating from
navController.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.dismiss))
Have to declare your selector as an #objc func
#objc func dismiss(){
self.dismiss(animated: true)
}
After going through every single stackoverflow solution for this problem, it's still frustratingly not working for me.
//UIBarButtonItem declaration
UIBarButtonItem* button1 = [[UIBarButtonItem alloc] initWithTitle:#"Button Text"
style:UIBarButtonItemStyleBordered target:self action:#selector(myAction)];
//method 1
[self setToolbarItems:[NSArray arrayWithObjects: button1, nil] animated:YES];
//method 2
[self.navigationController.toolbar setItems:[NSArray arrayWithObject:button1]];
//method 3
self.navigationController.toolbarItems = [NSArray arrayWithObject:button1];
//displaying toolbar
[self.navigationController setToolbarHidden:NO];
None of the above methods work for displaying a button on the toolbar - all I get is a blank toolbar. Is there something obvious I'm missing here?
Move
//UIBarButtonItem declaration
UIBarButtonItem* button1 = [[UIBarButtonItem alloc] initWithTitle:#"Button Text"
style:UIBarButtonItemStyleBordered target:self action:#selector(myAction)];
//method 1
[self setToolbarItems:[NSArray arrayWithObjects: button1, nil] animated:YES];
//displaying toolbar
[self.navigationController setToolbarHidden:NO];
to viewDidAppear:(BOOL)animated this is the point where UINavigationController get toolbar items of UIViewController that it manages.
use
self.toolbarItems=[NSArray arrayWithObject:button1]
With Swift 3 / iOS 10, in the simplest case where your navigation controller will contain only one view controller, you may use the code below in order to display your view controller with a toolbar that contains a bar button item:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Show navigation controller’s built-in toolbar
navigationController?.setToolbarHidden(false, animated: false)
// Set the view controller toolbar items
let items = [UIBarButtonItem(title: "Button Text", style: .plain, target: nil, action: nil)]
setToolbarItems(items, animated: false)
}
}
However, if you plan to have several view controllers in your navigation controller's stack, you will have to call UINavigationController's setToolbarHidden(_:animated:) method in viewWillAppear() and viewWillDisappear() in order to properly show or hide the navigation controller’s built-in toolbar:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Set the view controller toolbar items
let items = [UIBarButtonItem(title: "Button Text", style: .plain, target: nil, action: nil)]
setToolbarItems(items, animated: false)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Show navigation controller’s built-in toolbar
navigationController?.setToolbarHidden(false, animated: false)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Hide navigation controller’s built-in toolbar
navigationController?.setToolbarHidden(true, animated: false)
}
}
For those looking for a Swift version, try this:
let someVC: UIViewController = ...
let someButton: UIBarButtonItem = ...
someVC.setToolbarItems([someButton], animated: true)
The UINavigationController.toolbar property documentation explicitly clarifies which API should be used for setting toolbar items:
Management of this toolbar’s contents is done through the custom view controllers associated with this navigation controller. For each view controller on the navigation stack, you can assign a custom set of toolbar items using the setToolbarItems:animated: method of UIViewController.
-- UINavigationController Class Reference