I've created an App which has three storyboards. ( & multiple VC's) I am creating a global NavigationItem class, that I can enter in storyboard so every view controller inherits the same information and I only have to code one page rather than copying and pasting into each VC.
I want to set the title programmatically. The title can change depending on which storyboard is active and what size phone is present. i.e full title or shorthand if it is displaying on an iPhone SE.
I can't use. UIStoryboard as a bool, as it doesn't conform. How can I tell which storyboard I'm in, so it can set the title in an if statement? The code i've written is wrong and doesn't work for the storyboard.
My code setup so far for my NavigationItemCustom class is bellow I am finding it difficult to find which storyboard i'm in? Can anyone push me in the right direction, please. My code is as follows:
import UIKit
class NavigationBarSetUp: UINavigationItem {
override func awakeFromNib() {
super.awakeFromNib()
let currentstoryboard = UIStoryboard()
let screenWidth = UIScreen.main.bounds.width
let storyboard1 = UIStoryboard(name: "First", bundle: nil)
//let storyboard2 = UIStoryboard(name: "Second", bundle: nil)
//let storyboard3 = UIStoryboard(name: "Third", bundle: nil)
//Current title
self.title = nil
if currentstoryboard == storyboard1 && (screenWidth == 320) {
self.title = " diet 1"
print ("called short title")
} else if currentstoryboard == storyboard1 && (screenWidth > 320) {
// rest of screen sizes
self.title = " Welcome to diet 1"
print ("called full title")
}
// Repeat if statement for storyboards 2 & 3 with different titles.
// Rest of Class code - Bar Button Item Setup
self.hidesBackButton = false
self.leftItemsSupplementBackButton = true
// Left Side Button Setup
let buttonView = UIToolbar()
buttonView.frame = .init(x: 0, y:-7, width: 30, height: 30)
// Setting UIToolbar Transparency of the toolbar
buttonView.setBackgroundImage(UIImage(),
forToolbarPosition: .any,
barMetrics: .default)
buttonView.setShadowImage(UIImage(), forToolbarPosition: .any)
// This is a UIView the Toolbar will sit inside which will then be placed into the Navigationbar.
let navigationContainer = UIView()
navigationContainer.frame = .init(x: 0, y:0, width: 30, height: 30)
// ButtonBarItems Set Up
let ModalButton = UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(NotesButtonClicked))
let negativeSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: self, action: nil)
negativeSpace.width = -10
//Add ButtonBarItems into the UIToolbar ButtonView
buttonView.setItems([negativeSpace, ModalButton], animated: false)
// Add UItoolbar into UIView
navigationContainer.addSubview(buttonView)
//Icon Size to fit
buttonView.sizeToFit()
//Convert UIView into Barbutton Item to set in the Navigation Bar
let topLeft = UIBarButtonItem()
topLeft.customView = navigationContainer
self.setLeftBarButton(topLeft, animated: false)
// Setup of the Right Handside Menu Button
let BurgerButton = UIButton()
BurgerButton.frame = .init(x: -1, y: 0.5, width: 62, height: 25)
BurgerButton.setBackgroundImage(UIImage(named: "BurgerButton1.pdf"), for: .normal)
BurgerButton.addTarget(self, action: #selector(MenuClicked), for: .touchUpInside)
let topRight = UIBarButtonItem()
topRight.customView = BurgerButton
self.setRightBarButton(topRight, animated: true)
}
// Calls the Left Button Action.
func NotesButtonClicked(_ sender: UIBarButtonItem) {
print("Notes Modal Is Called")
//Code here
}
// Calls the Right Button Action.
func MenuClicked(_ sender: UIButton) {
print("Menu is Opened - Rightside")
//Code here
}
}
Well, you are doing a couple things that won't work:
let currentstoryboard = UIStoryboard()
You just created a NEW instance of a (empty) UIStoryBoard object...
let storyboard1 = UIStoryboard(name: "First", bundle: nil)
You just created a NEW instance of a UIStoryBoard object, referencing the Storyboard named "First" (assuming it exists in your app).
Those two instances could never be equal.
UIViewController has a .storyboard property, which is "The storyboard from which the view controller originated."
However, even if you tried:
let currentstoryboard = self.storyboard
let storyboard1 = UIStoryboard(name: "First", bundle: nil)
if currentstoryboard == storyboard1 { ... }
They will still never be equal, because storyboard1 is a new instance.
You might try:
let sbName = self.storyboard?.value(forKey: "name") as? String
if sbName == "First" { ... }
Unfortunately, that does not seem to be documented by Apple, and may very possibly and up getting your app rejected.
I'd think you would be much better off using your own variables / properties to keep track of what's what.
Related
I have an options button (that 3 vertical dotted button) on top of the view controller.
When I click that button, A list view should appear like in many other apps like WhatsApp...
I really don't know how to position it always near to the button programmatically.
Placing at the left-bottom of an existing view is quite easier:
func placeSubView(existingView: UIView)
{
let desiredWidth = CGFloat(50.0)
let desiredHeight = CGFloat(35.0)
let (x, y) = (existingView.frame.origin.x - desiredWidth, existingView.frame.origin.y + existingView.frame.size.height)
let desiredView = UIView(frame: CGRect(x: x, y: y, width: desiredWidth, height: desiredHeight))
existingView.superview?.addSubview(desiredView)
}
UPDATE:
In case you are looking for popupo menu like view, you should search about UIPopoverPresentationController.
Something like this.
Use this method and make PopoverViewController a table view controller if you want a list.
#IBAction func displayPopover(_ sender: UIBarButtonItem) {
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "PopoverViewController")
vc.modalPresentationStyle = .popover
let popover: UIPopoverPresentationController = vc.popoverPresentationController!
popover.barButtonItem = sender
present(vc, animated: true, completion:nil)
}
CNContactViewController navigation bar colour not appearing when i click Create New Contact option. See my screens for 1st time it's ok, but when i click Create New Contact i'm not getting navigation bar colour and not visible back button.
1st screen
2nd screen
In older versions
My code is
if #available(iOS 9.0, *) {
let store = CNContactStore()
let contact = CNMutableContact()
let homePhone = CNLabeledValue(label: CNLabelHome, value: CNPhoneNumber(stringValue : self.mobile ?? ""))
contact.phoneNumbers = [homePhone]
let controller = CNContactViewController(forUnknownContact : contact)
controller.contactStore = store
controller.delegate = self
if #available(iOS 10.0, *) {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.1 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {
//Set status bar background colour
let statusBar = UIApplication.shared.value(forKeyPath: "statusBarWindow.statusBar") as? UIView
statusBar?.backgroundColor = UIColor.red
//Set navigation bar subView background colour
for view in controller.navigationController?.navigationBar.subviews ?? [] {
view.tintColor = UIColor.white
view.backgroundColor = UIColor.red
}
})
}
navigationController?.pushViewController(controller, animated: true)
}
And one more is by default phone number: (913) 351-5518
I would suggest to display a CNConctactViewController within a UINavigationController in Popover Modal Presentation style, and add a few button to return to the main application. This implementation seams not trivial as reported by rumours over the net.
Let me share a few pieces of my code (swift 5).
The major class:
class MyViewController: UITableViewController, UIPopoverPresentationControllerDelegate {
var contactViewController = CNContactViewController()
...
#objc func dismissContactViewController() {
contactViewController.dismiss(animated: true, completion: nil)
}
}
The extension:
extension MyViewController: CNContactViewControllerDelegate {
func openCNContactViewController(willAppearWith: CNContact, type: ContactType) {
switch type {
case .forContact:
contactViewController = CNContactViewController(for: willAppearWith)
contactViewController.allowsEditing = false
break
case .forNewContact:
contactViewController = CNContactViewController(forNewContact: willAppearWith)
contactViewController.allowsEditing = true
break
case .forUnknowContact:
contactViewController = CNContactViewController(forUnknownContact: willAppearWith)
contactViewController.allowsEditing = true
break
}
contactViewController.allowsActions = true
contactViewController.contactStore = globalContactStore
contactViewController.hidesBottomBarWhenPushed = true
contactViewController.delegate = self
// define the button (or select a default one)
let button = UIButton(type: .custom)
button.setTitleColor(self.view.tintColor, for: .normal)
button.setTitle("My app name", for: .normal)
button.addTarget(self, action: #selector(dismissContactViewController), for: .touchUpInside)
let closeButton = UIBarButtonItem(customView: button)
closeButton.style = .plain
// add flexible space
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
// add to toolbar
contactViewController.setToolbarItems([flexibleSpace, closeButton, flexibleSpace], animated: false)
let navigationVC = UINavigationController(rootViewController: contactViewController)
// show toolbar
navigationVC.setToolbarHidden(false, animated: false)
// set navigation presentation style
navigationVC.modalPresentationStyle = .popover
// present view controller
self.present(navigationVC, animated: true, completion: nil)
}
The result
I'm new to Xcode/Swift. I have a center button I want to present a modal view from the current view (tab).
I've implemented a custom class for UITabBar that adds that button according to this guide.
This UITabBar has no view controller in self that I can find, so I get an error when I try to present a view.
Error: Value of type 'MainTabBar' has no member 'present'
Is there a way I can have this button present modal from the current view?
I'm not sure how to reach the current view from this custom class.
Should I point the button's addTarget to a uitabbar Delegate and watch for it in my other views?
Should I stop doing this and just do tabs with a tab that pulls up my modal view in a ViewDidAppear() on a different view?
I think I lose the ability to pop, or dismiss, back to the last view if I do that.
Here's the custom UITabBar class I'm working with.
class MainTabBar: UITabBar {
private var middleButton = UIButton()
override func awakeFromNib() {
super.awakeFromNib()
setupMiddleButton()
}
func setupMiddleButton() {
middleButton.frame.size = CGSize(width: 70, height: 70)
middleButton.backgroundColor = .blue
middleButton.layer.cornerRadius = 35
middleButton.layer.masksToBounds = true
middleButton.center = CGPoint(x: UIScreen.main.bounds.width / 2, y: 0)
middleButton.addTarget(self, action: #selector(test), for: .touchUpInside)
addSubview(middleButton)
}
#objc func test() {
let vc = createController()
vc.modalTransitionStyle = .crossDissolve
self.present(vc, animated: true, completion: nil)
}
}
Found a better implementation.
Created a custom class inherited from UITabBarController and named it MainViewController.
Setup the middle button in that controller instead of in the MainTabBar custom class.
self now has member present.
#objc func test() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc =
storyboard.instantiateViewController(withIdentifier: "createModal") as! createController
self.present(vc, animated: true, completion: nil)
}
https://github.com/drrost/Custom-Tabbar-Cetner-Button
am using navigation bar programmatically in swift, but am not able to show the bar button items in navigation bar,
this is the code what I did
override func viewDidLoad() {
super.viewDidLoad()
let navBar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: 420, height: 65))
self.view.addSubview(navBar)
navBar.backgroundColor = hexStringToUIColor("4DC8BD")
let navigationItem = UINavigationItem()
self.title = "Transport APP"
let btn1 = UIButton(type: .custom)
btn1.setImage(UIImage(named: "Menu1"), for: .normal)
btn1.frame = CGRect(x: 30, y: 30, width: 30, height: 30)
btn1.addTarget(self, action: #selector(HomeViewController.menubuttonclick(_:)), for: .touchUpInside)
let item1 = UIBarButtonItem(customView: btn1)
self.navigationItem.setRightBarButtonItems([item1], animated: true)
}
#IBAction func menubuttonclick(_ sender:UIBarButtonItem )
{
print("this menu button click")
}
I can try many ways but am not getting the results
how to show show bar button item in navigation bar,
You should add UINavigationItem to your UINavigationBar and in item1 need to be added in navitem Look at below code
let navitem = UINavigationItem()
navitem.rightBarButtonItem = item1
navBar.setItems([navitem], animated: true)
Swift 3+: Define the barbutton.
//:: Left bar items
lazy var leftBarItem: Array = { () -> [UIBarButtonItem] in
let btnBack = UIButton(type: .custom)
btnBack.frame = kBAR_FRAME
btnBack.addTarget(self, action: #selector(clickOnBackBtn(_:)), for: .touchUpInside)
let item = UIBarButtonItem(customView: btnBack)
item.tag = 3
return [item]
}()
Add this line into viewDidLoad
self.navigationItem.setLeftBarButtonItems(self.leftBarItem, animated: true)
Bar Button Action
#objc func clickOnBackBtn(_ sender: Any){
}
While the other mentioned solutions definitely work for programmatically defining the navigation item, some would prefer a storyboard solution. I searched for a Swift 4, Xcode 9 storyboard solution and was unable to find one, so I will show my solution.
Here is a screenshot of my storyboard before adding the bar button item.
The issue I was having is that while the Shops tableview is embedded in the navigation controller, and adding a bar button item was no issue; the Employees tableview is pushed via the navigation controller in the didSelectRowAt function.
extension ShopsViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedShop = fetchedResultsController.object(at: indexPath)
let st = UIStoryboardname: "Main", bundle: Bundle.main)
let vc = st.instantiateViewController(withIdentifier: "EmployeeViewController") as! EmployeeViewController
vc.shop = selectedShop
self.navigationController?.pushViewController(vc, animated: true)
}
}
The result is that I could not drag a bar button item from the storyboard. When I tried, the item would end up in the tab bar at the bottom:
I found an article that suggested embedding the second view controller in a navigation controller, but that adds other levels of complexity that I wanted to avoid. The work around I found is to drag a navigation item to the navigation bar area, and then you can add a bar button item with no problems.
Here is the result:
I know there is a lot of debate whether storyboards or programmatic layout is better. While I am still very much a beginning iOS developer and cannot personally speak to that, I am finding that sometimes the storyboard solution fits the problem best. I hope this helps other beginners.
if you've already created UINavigationController() you can set navigation items using self.navigationItem like this (in viewDidLoad function):
self.navigationItem.title = "Transport APP"
self.navigationItem.rightBarButtonItem = item1
but if you need to know how to create UINavigationController() for a view, you can do this in AppDelegate class:
let myView = ... //initial your view controller
let nav = UINavigationController()
nav.viewControlles = [myView]
and then everywhere you need, you should push nav view.
let rightBarButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(dismissVC))
self.navigationItem.rightBarButtonItem = rightBarButton
here is my code at the appdelegate:
func showMainView()
{
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController = storyBoard.instantiateViewController(withIdentifier: "PRODUCT_TABBAR_VC_ID")
let nav = UINavigationController()
nav.pushViewController(secondViewController, animated: true)
self.window!.rootViewController = nav
self.window!.makeKeyAndVisible()
}
simulator output:
basicaly i want when user press back button then came back main page . i mean initial page .
i am trying with this one but it not working at least one answer for me Navigate Back to previous view controller
Note : #matt said it is imposible. so could you tell me please what should i do . i am new to iOS
Update:
when user select Man that time tabviewcontroller two page only showing list of product about Man. so if user want to see Woman then user back to main page to select Woman then he will see Woman tabviewcontroller two page.
The back button is for returning to an earlier view controller pushed onto a UINavigationController. In your code, there is no back button because there is nothing to come back to; secondViewController is the only view controller pushed onto the UINavigationController.
You should create your hierarchy like so:
----> UIViewController
----> UINavigationController ----> UIViewController ----> UITabBarController
----> UIViewController
EDIT: It will look like that:
This way it will be possible to pop UIViewControllers contained in UITabBarController.
Place following lines within didFinishLaunchingWithOptions in AppDelegate.swift
self.window = UIWindow(frame: UIScreen.main.bounds)
let nav = UINavigationController(rootViewController: FirstViewController())
self.window!.rootViewController = nav
self.window!.makeKeyAndVisible()
Create FirstViewController.swift with following:
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button1 = UIButton(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
button1.setTitle("Man", for: .normal)
button1.tag = 1
self.view.addSubview(button1)
button1.addTarget(self, action: #selector(showAction(sender:)), for: .touchUpInside)
let button2 = UIButton(frame: CGRect(x: 0, y: 250, width: 200, height: 200))
button2.setTitle("Woman", for: .normal)
button2.tag = 2
self.view.addSubview(button2)
button2.addTarget(self, action: #selector(showAction(sender:)), for: .touchUpInside)
}
func showAction(sender: UIButton) {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController = storyBoard.instantiateViewController(withIdentifier: "PRODUCT_TABBAR_VC_ID")
if (sender.tag == 1) {
// SHOW MAN
} else if (sender.tag == 2) {
// SHOW WOMAN
}
self.navigationController?.pushViewController(secondViewController, animated: true)
}
}