How to navigate using Tab Bars in Swift using Xibs - swift

I am trying to use a tabbar to navigate to other view controllers using Xibs. However, I am not able to find tangible resources to proceed further. My current solution involves mapping and I cannot seem to see where the problem is.
import UIKit
class BottomNavViewController: UIViewController {
#IBOutlet weak var home: UITabBarItem!
#IBOutlet weak var assets: UITabBarItem!
#IBOutlet weak var transactions: UITabBarItem!
#IBOutlet weak var profile: UITabBarItem!
#IBOutlet weak var tabBar: UITabBar!
override func viewDidLoad() {
super.viewDidLoad()
navigateTab()
}
func navigateTab() -> Void{
let tabBarController = UITabBarController()
let homeVC = HomeViewController()
let assetsVC = AssetsViewController()
let transactionsVC = TransactionsViewController()
let profileVC = ProfileViewController()
let controllers = [homeVC, assetsVC, transactionsVC, profileVC]
tabBarController.viewControllers = controllers.map {
UINavigationController(rootViewController: $0)
}
}
}

Simply it is like this, You want use UITabbarController
class MYTabViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
let firstVC = FirstVC()
firstVC.tabBarItem = UITabBarItem(title: "Tab 1", image:(your image), tag: 0)
let secondVC = SecondVC()
secondVC.tabBarItem = UITabBarItem(title: "Tab 2", image: (your image), tag: 1)
viewControllers = [firstVC,secondVC]
}
}

Related

Swift transit from vc to another vc

ViewController has a label and a button for go to secondVC. And secondVC has a text field , label , button to write user-entered text in the text field on the label. When user press the back button of navigation bar, I want transit secondVC's label's text to ViewController's label's text. How can I do this ?
ViewController's code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var nameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func goVC2(_ sender: Any) {
performSegue(withIdentifier: "toVC2", sender: nil)
}
}
secondVC's code:
import UIKit
class secondVC: UIViewController {
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var resultLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func saveClicked(_ sender: Any) {
resultLabel.text = nameField.text
}
}
I tried prepare for segue in ViewController and but it was error. And I searched on google for this but I couldn't find solution.
Use protocol for pass data from second VC to first VC. you need to create your own delegate method and call on dismiss with pass data, check below code :----
ViewController's code:
import UIKit
class ViewController: UIViewController, Delegate {
#IBOutlet weak var nameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
func save(str : String) {
self.nameLabel.text = str
}
#IBAction func goVC2(_ sender: Any) {
if let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "secondVC") as? secondVC {
vc.delegate = self
self.present(vc, animated: true, completion: nil)
}
}
}
secondVC's code:
import UIKit
protocol Delegate : AnyObject {
func save(str : String)
}
class secondVC: UIViewController {
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var resultLabel: UILabel!
weak var delegate : Delegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func saveClicked(_ sender: Any) {
if let del = self.delegate {
let txt = nameField.text
del.save(str: txt)
self.dismiss(animated: true, completion: nil)
}
}
}

How to show containerview in viewcontroller in swift

I need to show containerview in viewcontroller, so i have taken one viewcontroller and designed and in that i have taken one containerview below to the buttons view
given containerview constraints: below to the buttonview
top = buttonview.bottom 10, leading, trailing, bottom = 0
there are two buttons indicates with green line.. initially i am in the "viewproposalvc" with red colour button.. here if i click gray colour button then i need to show containerview
here the viewproposalvc code:
class ViewProposalVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var postId: Int?
#IBOutlet weak var containerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
updateNavigationBar(with: "View Proposal")
containerView.isHidden = true
}
#IBAction func grayBtn(_ sender: Any) {
containerView.isHidden = false
let vc = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "ContainerVC") as? ContainerVC
vc.serviceId = self.viewproposalData?.result?.posted_services?.id
self.navigationController?.pushViewController(vc!, animated: true)
}
#IBAction func redBtn(_ sender: Any) {
containerView.isHidden = true
postedServicesCall()
}
}
this is containervc code:
class ContainerVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
}
}
but here containervc not coming below to the buttonsview.. its coming in separate viewcontroller, why?
o/p of containervc: i dont want separate viewcontroller.. i need containervc to show below to the buttonsview of the viewproposalvc
first time i am working with container views, please do help
The reason why is because you are calling
self.navigationController?.pushViewController(vc!, animated: true)
ContainerView is just a generic UIView with an embedded segue, that is triggered from viewDidLoad of the hosted VC. If you need to do additional setup of that VC I suggest making an var on ViewProposalVC and making desired changes from there.
as in
class ViewProposalVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var postId: Int?
#IBOutlet weak var containerView: UIView!
#IBOutlet weak var secondaryController: UIViewController!
override func viewDidLoad() {
super.viewDidLoad()
updateNavigationBar(with: "View Proposal")
containerView.isHidden = true
}
#IBAction func grayBtn(_ sender: Any) {
containerView.isHidden = false
self.secondaryController.serviceId = self.viewproposalData?.result?.posted_services?.id
}

How do I present ViewController programatically?

import UIKit
//EventList ViewController
class EventPage: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
class EventForm: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
//IBOutlets
#IBOutlet weak var eventNameField: UITextField!
#IBOutlet weak var fromTimePicker: UIDatePicker!
#IBOutlet weak var toTimePicker: UIDatePicker!
#IBOutlet weak var colorPreview: UIView!
#IBAction func cancel(_ sender: Any) {
//empty text field
eventNameField.text = ""
}
#IBAction func save(_ sender: Any) {
if (eventNameField.hasText) {
//fix error handling
eventNameField.backgroundColor = UIColor.systemGray2
//pull data from fields
let text = eventNameField.text!
let fromTime = fromTimePicker.date
let toTime = toTimePicker.date
//initialize object
let currentEvent = EventModel(eventName: text, fromTime: fromTime, toTime: toTime, color: storedColor)
//append to data model
EventDataArray.append(currentEvent)
//transition
present(EventPage(), animated:true)
}
else {
eventNameField.backgroundColor = UIColor.systemRed
}
}
}
I currently have an EventPage class declared as type UIViewController, but upon pressing the save button with a populated text field a transition to a blank ViewController occurs. I've attached the class to the correct ViewController in main.storyboard.
The problem in here is that you are creating a new EventPage but it doesn't inherit from Storyboard.
1
Go to the inspector in your storyboard, select your View Controller, and write an identifier for your View Controller (can be anything)
Write it in Storyboard ID:
2
Replace
present(EventPage(), animated:true)
With
(don't forget to replace 'MYIDENTIFIER' with the id you entered earlier)
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MYIDENTIFIER") as! EventPage
// If you need to do any configurations to your view controller, do that in here.
// For example:
// viewController.label.text = "Hello, world!"
present(viewController, animated:true)
Note
If the name of your Storyboard file name is not called Main, replace "Main" in step 2 with the name of your storyboard file (excluding .storyboard)

Transfer TextField data between ViewControllers

I have ViewController, which has a textfield and a button. The user enters his name into the textfield and hits the DONE button. When he hits the button, he is segued to GifteeDetails, which is a different view controller. There is a label in that viewController that is supposed to display his name. But, his name doesn't show up. I don't receive an error.
Here's ViewController:
#IBOutlet weak var textGifteeName: UITextField!
#IBAction func toDetails(_ sender: Any) {
performSegue(withIdentifier: "toDetails", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destDetails: GifteeDetails = segue.destination as! GifteeDetails
destDetails.nametext = textGifteeName.text!
destDetails.agetext = "\(Int(age)! - 2000 + 17)"
destDetails.locationstext = labelGifteeLocationsPreview.text!
destDetails.intereststext = labelGifteeInterestsPreview.text!
}
Here's GifteeDetails:
var nametext = String()
var agetext = String()
var locationstext = String()
var intereststext = String()
#IBOutlet weak var labelGifteeName: UILabel!
#IBOutlet weak var labelGifteeAge: UILabel!
#IBOutlet weak var labelGifteeLocations: UILabel!
#IBOutlet weak var labelGifteeInterests: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
nametext = labelGifteeName.text!
agetext = labelGifteeAge.text!
locationstext = labelGifteeLocations.text!
intereststext = labelGifteeInterests.text!
}
Sorry about all the !. Swift gives me an error unless I have them.
You are updating the strings nametext and others, which are not connected to your labels.
You need to replace this piece of code:
destDetails.nametext = textGifteeName.text!
destDetails.agetext = "\(Int(age)! - 2000 + 17)"
destDetails.locationstext = labelGifteeLocationsPreview.text!
destDetails.intereststext = labelGifteeInterestsPreview.text!
With:
destDetails.labelGifteeName.text = textGifteeName.text!
destDetails.labelGifteeAge.text = "\(Int(age)! - 2000 + 17)"
destDetails.labelGifteeLocations.text = labelGifteeLocationsPreview.text!
destDetails. labelGifteeInterests.text = labelGifteeInterestsPreview.text!
nametext is a String object, and it is different from labelGifteeName.text which is the String of the label you want to update.
If you use segue then pls remove it, and then create action method of that button in the FirstviewController and use pushViewController to move on the SecondviewController.
Swift 3
Example:
#IBAction func toDetails(_ sender: Any)
{
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "SecondView") as! SecondView
UserDefaults.standard.set(self. textGifteeName.text, forKey: "savedStringKey")
UserDefaults.standard.synchronize()
self.navigationController?.pushViewController(vc,
animated: true)
}
In SecondView:
override func viewDidLoad() {
super.viewDidLoad()
self.labelGifteeName.text = UserDefaults.standard.string(forKey: "savedStringKey")!
}
Please Update your func viewDidLoad() method in GifteeDetailsVC with labelGifteeName.text! = nametext , labelGifteeAge.text!= agetext instead of your code because you have already assigned the value in to strings i.e, nametext and agetext in ViewController, you need to display string value in label

How can I pass data from a parent view controller to an embedded view controller in Swift?

I have a view controller embedded in another VC.
I would like to get the value of a variable from the main VC inside the embedded one. Specifically, I would like to change the text of label2 based on the value of label1.
I tried with "prepareForSegue", but it seems it's not triggered for embedded view controllers. I tried to isolate the problem in a test project:
Code for main VC:
class MyViewController: UIViewController {
#IBOutlet weak var label1: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label1.text = "Hello"
}
}
Code for embedded VC:
class EmbeddedVC: UIViewController {
#IBOutlet weak var label2: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
}
Thanks for your help :)
A way to achiŠµve this is to get the child view controller instance in the parent's viewDidLoad. It appears that the parent's viewDidLoad: gets called after the child's viewDidLoad:, which means the label is already created in the child's view.
override func viewDidLoad() {
super.viewDidLoad()
if let childVC = self.childViewControllers.first as? ChildVC {
childVC.someLabel.text = "I'm here. Aye-aye."
}
}
First of all you can't set directly EmbeddedVC's lable2.text In prepareForSegue
because call sequence following below
MainVC's prepareForSeque this time EmbeddedVC's label2 is nil
EmbeddedVC's viewDidLoad called then label2 loaded
MainVC's viewDidLoad called then label1 loaded
so if you assign MainVC's label1.text to EmbeddedVC's label2.text in prepareForSeque
both label1 and label2 are nil so did not work
There are two way to solve this question
First Solution
MainViewController has EmbeddedVC and when MainVC's viewDidLoad called, assign label1.text to embeddedVC.label2.text
class MyViewController: UIViewController {
#IBOutlet weak var label1: UILabel!
var embeddedVC: EmbeddedViewController? = nil
override func viewDidLoad() {
super.viewDidLoad()
label1.text = "Hello"
embeddedVC?.label2.text = label1.text
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let embeddedVC = segue.destination as? EmbeddedViewController {
self.embeddedVC = embeddedVC
}
}
}
class EmbeddedViewController: UIViewController {
#IBOutlet weak var label2: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
}
Second Solution, use protocol and get MainVC's label text when viewWillAppear or viewDidAppear (later viewDidLoad called)
protocol EmbeddedVCDelegate: class {
func labelText() -> String?
}
class MyViewController: UIViewController, EmbeddedVCDelegate {
#IBOutlet weak var label1: UILabel!
// MARK: EmbeddedVCDelegate
func labelText() -> String? {
return label1.text
}
override func viewDidLoad() {
super.viewDidLoad()
label1.text = "Hello"
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let embeddedVC = segue.destination as? EmbeddedViewController {
embeddedVC.delegate = self
}
}
}
class EmbeddedViewController: UIViewController {
#IBOutlet weak var label2: UILabel!
weak var delegate: EmbeddedVCDelegate? = nil
override func viewDidLoad() {
super.viewDidLoad()
}
override viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
label2.text = delegate?.labelText()
}
}
You should try to use prepareForSegue like this:
if segue.identifier == "identifier" {
guard let destinationViewController = segue.destination as? VC2 else { return }
destinationViewController.label2.text = mytext
}
Where the segue identifier you assign in storyboard