passing value with protocol: ViewController to .xib file in swift - swift

So i have a class "CalendarioViewController" with one protocol "DateSelectedDelegate".
Protocol:
protocol DateSelectedDelegate {
func dateSelected (date: String)}
I declare a variable protocol type:
var dateDelegate: DateSelectedDelegate? = nil
Into my class "CalendarioViewController" i have a #IBAction button:
#IBAction func gotoHotelVC(_ sender: Any) {
if dateDelegate != nil {
if fechaSelected.text != nil {
let data = fechaSelected.text
dateDelegate?.dateSelected(date: data!)
}
}
}
In my secondVC or "FechasViewController" i use the protocol define early, i call the CalendarioViewController with two button. The FechasViewController is a xib file:
#IBAction func fechaArribo(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc:CalendarioViewController = storyboard.instantiateViewController(withIdentifier: "calendario") as! CalendarioViewController
vc.dateDelegate = self
self.window!.rootViewController = vc
}
#IBAction func fechaSalida(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc:CalendarioViewController = storyboard.instantiateViewController(withIdentifier: "calendario") as! CalendarioViewController
vc.dateDelegate = self
self.window!.rootViewController = vc
}
my #IBOutlet:
#IBOutlet weak var fechaArriboLabel: UILabel!
Use protocol:
extension FechasViewController: DateSelectedDelegate {
func dateSelected(date: String) {
fechaArriboLabel.text = date
print(date)
print(fechaArriboLabel.text!)
}
}
The line print(date) or print(fechaArriboLabel.text!) is work just fine... but my xib label don't not change anything:
here my xib:
and this is my Storyboard:
Put here my entire code:
enter image description here
Please...help!

Related

Is there a workaround to bring the method "present" in a UIimageView class?

I created a class for my Logo UIimageView which is on every ViewController in my app. Now I want to create a tapGesture to jump back to the Home ViewController when it is tapped like Logos on Homepages back to index. How can I get the present method to work in the class UIimageView?
import Foundation
import UIKit
class LogoImageView: UIImageView {
override func awakeFromNib() {
super.awakeFromNib()
self.isUserInteractionEnabled = true
let TapGesture = UITapGestureRecognizer(target: self, action: #selector(self.imageTapped))
self.addGestureRecognizer(TapGesture)
}
#objc func imageTapped() {
let mainStoryboad = UIStoryboard(name: "Main", bundle: Bundle.main)
guard let destinationViewController = mainStoryboad.instantiateViewController(withIdentifier: "ViewController") as? ViewController else {
return
}
present(destinationViewController, animated: true, completion: nil)
}
}
I´ve got the solution for my problem. I added an extension to check the current ViewController to use the present method. Now I´m able to add every UIimageview this class and it brings me back to the root viewcontroller.
import Foundation
import UIKit
class LogoImageView: UIImageView {
override func awakeFromNib() {
super.awakeFromNib()
self.isUserInteractionEnabled = true
let TapGesture = UITapGestureRecognizer(target: self, action: #selector(self
.imageTapped))
self.addGestureRecognizer(TapGesture)
}
#objc func imageTapped() {
let mainStoryboad = UIStoryboard(name: "Main", bundle: Bundle.main)
guard let destinationViewController = mainStoryboad.instantiateViewController(withIdentifier: "ViewController") as? ViewController else {
return
}
guard let currentViewController = UIApplication.shared.keyWindow?.topMostViewController() else {
return
}
destinationViewController.modalTransitionStyle = .flipHorizontal
currentViewController.present(destinationViewController, animated: true, completion: nil)
}
}
extension UIWindow {
func topMostViewController() -> UIViewController? {
guard let rootViewController = self.rootViewController else {
return nil
}
return topViewController(for: rootViewController)
}
func topViewController(for rootViewController: UIViewController?) -> UIViewController? {
guard let rootViewController = rootViewController else {
return nil
}
guard let presentedViewController = rootViewController.presentedViewController else {
return rootViewController
}
switch presentedViewController {
case is UINavigationController:
let navigationController = presentedViewController as! UINavigationController
return topViewController(for: navigationController.viewControllers.last)
case is UITabBarController:
let tabBarController = presentedViewController as! UITabBarController
return topViewController(for: tabBarController.selectedViewController)
default:
return topViewController(for: presentedViewController)
}
}
}

Push UIViewController with Alert without UINavigationController

I have a button in UITableViewController. when I press this button, alert controller appears asks if the user wants to go to the cart page or stay in the same page, as follows,
if user?.uid != nil{
let title = "Item is added to your cart "
let alert = AlertController.instance(title: title)
present(alert, animated: true, completion: nil)
} else{
// Alert asks user to register..
}
AlertController is in different class and I created it with custom animation.
I want when user press (go to cart page) button, the cart page is displayed as if it was as (show,"push") segue.
This is how I pushed the view controller programmatically in alert controller class.
#IBAction func showCartButton(_ sender: Any) {
//---> go to cart page ...
print("cart button pressed")
//-----> this code is working fine with other UIviewcontrollers (however it is 'not working in UItableviewcontroller)
let storyBoard : UIStoryboard = UIStoryboard(name: "Cart", bundle:nil)
let CartViewController = storyBoard.instantiateViewController(withIdentifier: "CartPage")
navigationController?.pushViewController(CartViewController, animated: true)
//-----> this code shows the cart page without the navigation and tabs..
// let storyBoard : UIStoryboard = UIStoryboard(name: "Cart", bundle:nil)
// let CartViewController = storyBoard.instantiateViewController(withIdentifier: "CartPage")
// self.present(CartViewController, animated:true, completion:nil)
}
The push view controller is not working with Alert controller, I am not sure if it is because I used the navigation with the alert, and if so, is there a way I can push the view controller??
This is the whole AlertController Class I created in seperate storyboard and put it as initial view controller..
import UIKit
class AlertController: UIViewController{
#IBOutlet weak fileprivate var AddProductToCartLabel: UILabel!
#IBOutlet weak fileprivate var cartButton: UIButton!
#IBOutlet weak fileprivate var shoppingButton: UIButton!
#IBOutlet weak fileprivate var container: UIView!
var text = String()
override func viewDidLoad() {
setContainer()
setCartButton()
setShoppingButton()
}
override func viewDidLayoutSubviews() {
layoutContainer()
}
#IBAction func cancel(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
#IBAction func showCartButton(_ sender: Any) {
//---> go to cart page ...
print("cart button pressed")
let storyBoard : UIStoryboard = UIStoryboard(name: "Cart", bundle:nil)
let CartViewController = storyBoard.instantiateViewController(withIdentifier: "CartPage")
navigationController?.pushViewController(CartViewController, animated: true)
// let storyBoard : UIStoryboard = UIStoryboard(name: "Cart", bundle:nil)
// let CartViewController = storyBoard.instantiateViewController(withIdentifier: "CartPage")
// self.present(CartViewController, animated:true, completion:nil)
}
#IBAction func completeShopButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
fileprivate extension AlertController{
// to set the view above
func setContainer() {
let shape = CAShapeLayer()
shape.fillColor = UIColor.white.cgColor
container.backgroundColor = UIColor.clear
container.layer.insertSublayer(shape, at: 0)
}
func setCartButton(){
cartButton.clipsToBounds = true
//cartButton.layer.cornerRadius = 10
}
func setShoppingButton(){
shoppingButton.clipsToBounds = true
shoppingButton.layer.borderColor = UIColor.darkGray.cgColor
shoppingButton.layer.borderWidth = 1
//shoppingButton.layer.cornerRadius = 10
}
}
fileprivate extension AlertController{
// design the size of the container
func layoutContainer() {
let path = UIBezierPath(roundedRect: container.bounds, cornerRadius: 10)
let layer = container.layer.sublayers?.first as! CAShapeLayer
layer.path = path.cgPath
}
}
extension AlertController{
static func instance(title: String?) -> AlertController{
let storyboard = UIStoryboard(name: String(describing: self), bundle: Bundle(for: self))
let controller = storyboard.instantiateInitialViewController() as! AlertController
controller.text = title!
return controller
}
}
The problem is that when you try to push CartViewController, there is no navigation controller to push it on.
You present AlertController modally, and then try to do:
navigationController?.pushViewController(CartViewController, animated: true). If you put a breakpoint here and print out navigationController, I expect it is nil.
I suggest you have AlertController delegate back to your UITableViewController that is inside a navigation controller, and have the tableview controller push to the next screen. You could also present AlertController inside of a navigation view, but this seems unnecessary.

Storyboard initialization and deinit

When initializing a ViewController via a Storyboard (NS or UI), do you need to keep a reference to the storyboard or can you just ignore it when you are done with it and let it deinit?
class ViewController: NSViewController {
var secondarySB: NSStoryboard? = nil
#IBAction
func loadAndKeep(_ sender: NSButton) {
//keeping a reference
secondarySB = NSStoryboard.init(name: NSStoryboard.Name.init(rawValue: "Secondary"), bundle: nil)
let vc = secondarySB?.instantiateInitialController() as! Secondary
self.view.addSubview(vc.view)
}
#IBAction
func load(_ sender: NSButton) {
//ignoring the storyboard after I get the viewcontroller
let sb = NSStoryboard.init(name: NSStoryboard.Name.init(rawValue: "Secondary"), bundle: nil)
let vc = sb.instantiateInitialController() as! Secondary
self.view.addSubview(vc.view)
}
}
You do not need to keep a reference to the storyboard, but you do need to add the instantiated view controller as a child view controller.

How do i load a viewcontroller from a xib file?

I tried to load a viewcontroller from a custom cell using delegates.But i get nil from the set delegate!
Here is a sample if anyone can help!
1. In Cell
protocol hotelFindDelegate{
func modalDidFinished(modalText: String)
}
class hotelFindCell: UITableViewCell {
var delegate:hotelFindDelegate?
#IBAction func findButton(sender: AnyObject) {
self.delegate!.modalDidFinished("HELLO")
print("Damn nothing works")
}
2. In Main View
class MainViewController:hotelFindDelegate {
let modalView = hotelFindCell()
override func viewDidLoad() {
super.viewDidLoad()
self.modalView?.delegate = self
}
func modalDidFinished(modalText: String){
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("HotelListVC") as UIViewController
self.presentViewController(viewController, animated: false, completion: nil)
self.modalView.delegate = self
print(modalText)
}
To load view controller from XIB do the following steps.
let settingVC : SettingsViewController = SettingsViewController(nibName :"SettingsViewController",bundle : nil)
later on you can push the same view controller object like
self.navigationController?.pushViewController(settingsVC, animated: true)
NSBundle.mainBundle().loadNibNamed("viewController", owner: self, options: nil)

What's wrong with my delegate?

I am new to swift and right now I am learning delegate. I think I already do the right things but it is still not working.
What I am doing was passing data from my ViewController to TestViewController
ViewController:
protocol viewControllerDelegate: class {
func viewcontrollerdelegate(setviewcontrollerdelegate: ViewController)
}
class ViewController: UIViewController ,UITextFieldDelegate {
weak var delegate: viewControllerDelegate?
#IBAction func nextViewandDelegate(sender: AnyObject) {
self.delegate?.viewcontrollerdelegate(self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showTestSegue" {
if let testViewController = segue.destinationViewController as? TestViewController {
testViewController.address = address.text!
testViewController.phone = phone.text!
}
}
}
}
TestViewController:
class TestViewController: UIViewController {
var name: String?
var address: String?
var phone: String?
var trydelegate: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let VC = storyboard.instantiateViewControllerWithIdentifier("viewcontroller") as! ViewController
VC.delegate = self
}
override func viewWillAppear(animated: Bool) {
addressLabel.text = address!
phoneLabel.text = phone!
trydelegateLabel.text = trydelegate //always nil here
}
}
extension TestViewController:viewControllerDelegate {
func viewcontrollerdelegate(setviewcontrollerdelegate: ViewController) {
self.trydelegate = setviewcontrollerdelegate.address.text!
}
}
I used segue to pass address and phone and they worked well.
But I am suck with delegate. Can anyone help me a little bit with it? I know the question is a little easy for you here.
Thank you very much.
In TestViewController in viewDidLoad you create new object vc which is not he same as the one which call prepareForSegue so that's why it doesn't work.
To fix this remove the code from viewDidLoad:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("viewcontroller") as! ViewController
vc.delegate = self
And in prepareForSegue add one line:
testViewController.phone = phone.text!
// New line
self.delegate = testViewController
That should help.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showTestSegue" {
if let testViewController = segue.destinationViewController as? TestViewController {
testViewController.address = address.text!
testViewController.phone = phone.text!
self.delegate = testViewController
self.delegate?.viewcontrollerdelegate(self)
}
}
}
remove #IBAction func nextViewandDelegate(sender: AnyObject) and change that prepareforsegue
I fixed it......it is working right now but I dont know why