Global View visible in all .xib ViewControllers - swift

I'm trying to create a "Global View" maybe it goes into AppDelegate, but I'm not sure. I would like my View to always be visible, no matter what ViewController .xib you are on in the app.
For now I have inserted the View in the first ViewController .xib but when I navigate in the other ViewControllers the View disappears.
This is the code:
import UIKit
class MonitoringViewController: UIViewController {
#IBOutlet var contentView: UIView!
#IBOutlet weak var viewForTab: UIView!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonTab1(_ sender: UIButton) {
}
#IBAction func buttonTab2(_ sender: UIButton) {
delegate?.navigateToAlertViewController()
let alert = AlertViewController(nibName: "AlertViewController", bundle: nil)
contentView.addSubview(alert.view)
alert.didMove(toParent: self)
}
#IBAction func buttonTab3(_ sender: UIButton) {
}
}

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 can I properly send values between classes in Swift?

I've been working on a text based adventure game using Swift. However, I can't seem to change the default values for specific classes.
Below is the code for the class that allows me to select my player class
import UIKit
class ClassSelectionController: UIViewController
{
//Default class values
var character = (0, 0, "", 0)
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//class button actions
#IBAction func fighterBtn(_ sender: Any)
{
character = (50, 60, "Steal Sword", 18)
performSegue(withIdentifier: "Character", sender: self)
}
#IBAction func wizerdBtn(_ sender: Any)
{
character = (25, 70, "Staff", 15)
performSegue(withIdentifier: "Character", sender: self)
}
#IBAction func thiefBtn(_ sender: Any)
{
character = (30, 60, "Dagger", 18)
performSegue(withIdentifier: "Character", sender: self)
}
#IBAction func archerBtn(_ sender: Any)
{
character = (50, 60, "Bow & Arrow", 16)
performSegue(withIdentifier: "Character", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: (Any)?)
{
//code for segue
var vc = segue.destination as! ViewController
vc.finalCharacter = self.character
}
}
And this is the class that receives the data for the player class and displays it.
import UIKit
class ViewController: UIViewController
{
var finalCharacter = (0, 0, "", 0)
//****************************************
//Setup for outlets go between these lines
//****************************************
#IBOutlet weak var healthLabel: UILabel!
#IBOutlet weak var damageLabel: UILabel!
#IBOutlet weak var weaponLabel: UILabel!
#IBOutlet weak var armorLabel: UILabel!
#IBOutlet weak var storyLabel: UILabel!
#IBOutlet weak var actionButton: UIButton!
#IBOutlet weak var northBtn: UIButton!
#IBOutlet weak var southBtn: UIButton!
#IBOutlet weak var eastBtn: UIButton!
#IBOutlet weak var westBtn: UIButton!
//****************************************
//Setup for outlets go between these lines
//****************************************
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
healthLabel.text = "Health: \(finalCharacter.0)"
damageLabel.text = "Damage: \(finalCharacter.1)"
weaponLabel.text = "Weapon: " + finalCharacter.2
armorLabel.text = "Armor : \(finalCharacter.3)"
}
//****************************************
//Setup for buttons go between these lines
//****************************************
#IBAction func actionButton(_ sender: Any)
{
}
#IBAction func northButton(_ sender: Any)
{
}
#IBAction func southButton(_ sender: Any)
{
}
#IBAction func eastButton(_ sender: Any)
{
}
#IBAction func westButton(_ sender: Any)
{
}
//****************************************
//Setup for buttons go between these lines
//****************************************
}
Even though my code does not currently show it I did put print values in the class buttons just so see if the values have changed when I select a class and I have seen that they do change when the button is pressed. I also poked around in ViewController and changed the finalCharacter values, just to see if that affected anything, which it didn't. So my educated guess is that the problem has to be in ClassSelectionController.
So the main problem is that I will click on the wizard player class, and I'd expect the class stats for the wizard to pop up (I.e. 25, 70, "Staff", 15), but I'll only get the default values that are in the ClassSelectionController (0, 0, "", 0).
What is happening here that you have multiple UIStoryboardSegue named "Character" linked with every button
so what happens is when you press the button the Segue is called before the Action button and in addition the UIStoryboardSegue is called again (if you place a debugger in the viewDidLoad you would see that it goes there two times).
Solution
Remove all the UIStoryboardSegue linked from the buttons
Make a new UIStoryboardSegue from the ClassSelectionController to the next ViewController name it 'Character'
You dont need to change anything from the code but should add a safe check
override func prepare(for segue: UIStoryboardSegue, sender: (Any)?)
{
if (segue.identifier == "Character") {
let vc = segue.destination as! ViewController
vc.finalCharacter = self.character
}
}

Unable to perform segue from UIView connected to XIB

This is UIView file's owner of XIB
import UIKit
class sideBarContent: UIView {
#IBOutlet weak var userName: UILabel!
#IBOutlet var sideBarContentView: UIView!
let mapviewcontroller = MapViewController()
#IBAction func userProfile(_ sender: UIButton) {
mapviewcontroller.performSegueFromView(stringFromView: "userprofile")
}
Whereas inside my UIviewcontroller
class MapViewController: UIViewController
{
func performSegueFromView(stringFromView:String){
performSegue(withIdentifier: "\(stringFromView)", sender: nil)
}
}
It says that my segue identifier does not exist, please help, i'm quite lost. And i couldn't perform segue in UIView as well, and i tried to use storyboard ID method too, but the present(vc,animated:true,completion:nil) not showing up.
First things first, I think you should not access the view controller from your view. It is better to model the controller logic in the view controller rather than in the view.
That said, you can use a delegate pattern to implement your functionality.
import UIKit
class SideBarContent: UIView {
#IBOutlet weak var userName: UILabel!
#IBOutlet var sideBarContentView: UIView!
let delegate: SideBarContentDelegate? = nil
#IBAction func userProfile(_ sender: UIButton) {
self.delegate?.performSegueFromView(withIdentifier: "userprofile")
}
}
protocol SideBarContentDelegate {
func performSegueFromView(withIdentifier identifier: String)
}
class MapViewController: UIViewController, SideBarContentDelegate {
#IBOutlet private weak var sidebarView: SideBarContent!
override func viewDidLoad() {
super.viewDidLoad()
self.sidebarView.delegate = self
}
func performSegueFromView(withIdentifier identifier: String) {
self.performSegue(withIdentifier: identifier, sender: nil)
}
}
More info : https://stackoverflow.com/a/1340470/2603900

Swift: Pass multiple values between views

I have a view that has two text fields and a button.
#IBOutlet var inputURL: UITextField!
#IBOutlet var inputName: UITextField!
#IBAction func submitUrlButton(sender: AnyObject) {
}
and a second view that has two variables:
var submittedURL = ""
var submittedName = ""
println("Name \(submittedName)")
println("URL \(submittedURL)")
In Swift How do I pass the values entered in the two text fields and assign them to those variables in the second view?
Thanks
EDIT FOR THETOM:
import UIKit
class ViewController: UIViewController {
#IBOutlet var inputURL: UITextField!
#IBAction func submitBtn(sender: AnyObject) {
performSegueWithIdentifier("submissionSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
// Create a new variable to store the instance of the next view controller
let destinationVC = segue.destinationViewController as BrandsViewController
destinationVC.submittedURL.text = inputURL.text
}
}
You can use the method prepareForSegue.
In the first view (the one from which the segue is coming from) write the following code :
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
// Create a new variable to store the instance of the next view controller
let destinationVC = segue.destinationViewController as CustomViewController
destinationVC.submittedURL = inputURL.text
destinationVC.submittedName = inputName.text
}
Here CustomViewController is the custom class of the UIViewController to which the segue is going to.
To perform the segue programmatically in your button #IBAction do that :
#IBAction func buttonWasClicked(sender: AnyObject) {
performSegueWithIdentifier("submissionSegue", sender: self)
}
Since your view controllers are linked with segue you can override the prepareForSegue method in first view controller and pass data by doing so
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "secondViewController") { // here secondViewController is your segue identifier
var secondViewController = segue.destinationViewController as SecondViewController // where SecondViewController is the name of your second view controller class
secondViewController.submittedURL = inputURL.text
secondViewController.submittedName = inputName.text
}
}
And to performSegue inside your button action use perfromSegueWithIdentifier method
#IBAction func submitUrlButton(sender: AnyObject) {
//replace identifier with your identifier from storyboard
self.performSegueWithIdentifier("secondViewController", sender: self)
}
The simplest way of accessing values globally not neccessary to pass with segue
First View controller
import UIKit
var submittedURL:NSString? // declare them here
var submittedName:NSString? // Now these two variables are accessible globally
class YourViewController : UIViewController
{
#IBOutlet var inputURL: UITextField!
#IBOutlet var inputName: UITextField!
#IBAction func submitUrlButton(sender: AnyObject) {
if inputURL.text == "" && inputName.text == ""
{
//Show an alert here etc
}
else {
self.submittedURL.text = inputURL.text
self.submittedName.text = inputName.text
}
}
}
SecondView Controller
import UIKit
class SecondviewController: UIViewController
{
//inside viewDidload
println(submittedURL)
println(submittedName)
}