What's wrong with my delegate? - swift

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

Related

iOS 13 - Right Bar Button Item goes offset in Modal Sheet presentation

I have this strange problem with iOS 13 and its new sheet cards style modal presentation.
From ViewController1 I modal present ViewController2 embedded in a NavigationController, and everything works fine.
From ViewController2, I then modal present ViewController3 embedded in a NavigationController, and I get the Right Bar Button offset.
Here is a video of the problem: does anybody have a fix?
Main View Controller
import UIKit
let vc1identifier = "vc1identifier"
let vc2identifier = "vc2identifier"
class ViewController: UIViewController {
#IBAction func tap1(_ sender: UIButton) {
if let navigation = self.storyboard?.instantiateViewController(withIdentifier: vc1identifier) as? UINavigationController,
let nextVC = navigation.contentViewController as? UnoViewController {
//self.navigationController?.pushViewController(nextVC, animated: true)
self.present(navigation, animated: true, completion: nil)
}
}
}
extension UIViewController {
var contentViewController: UIViewController {
if let navcon = self as? UINavigationController {
return navcon.visibleViewController!
} else {
return self
}
}
}
Second View Controller
import UIKit
class UnoViewController: UIViewController {
#IBOutlet weak var barButton: UIBarButtonItem!
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
barButton.title = "GotoVC2"
}
#IBAction func pressThis(_ sender: UIBarButtonItem) {
if let navigation = self.storyboard?.instantiateViewController(withIdentifier: vc2identifier) as? UINavigationController,
let nextVC = navigation.contentViewController as? DueViewController {
self.present(navigation, animated: true, completion: nil)
}
}
}
I came across the same issue.
Solution is easy, you just need to tell navigationbar it needs layout like this
override public func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if #available(iOS 13.0, *) {
navigationController?.navigationBar.setNeedsLayout()
}
}

Swift 4 Delegate doesn't work from childViewController

I have to code simple program. Just one login screen waiting for some password and after setting proper one, change screen to "program itself" and its features.
I decided to do it by container View and its subviews. everything works fine but delegate which should be responsible for triggering this change doesn't respond. In any option I tried, nothing has changed... it still doesn't respond.
This is code of ViewController (main):
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var container: NSView!
var vc1 : ViewController1 = ViewController1()
var vc2 : ViewController2 = ViewController2()
override func viewDidLoad() {
super.viewDidLoad()
//initialise of delegate:
vc1.delegate = self
// set subviews:
vc1 = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil).instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "ViewController1")) as! ViewController1
vc2 = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil).instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "ViewController2")) as! ViewController2
self.addChildViewController(vc1)
self.addChildViewController(vc2)
// set first view:
vc1.view.frame = self.container.bounds
self.container.addSubview(vc1.view)
}
func changeViews()
{
for sView in self.container.subviews {
sView.removeFromSuperview()
}
// set second view:
vc2.view.frame = self.container.bounds
self.container.addSubview(vc2.view)
}
}
extension ViewController: ViewController1_Delegate {
func passwdEntered(_ correctPasswd: Bool) {
if correctPasswd == true{
changeViews()
}
}
}
and this is First (SubView) ViewController code, where I'm entering passwd:
import Cocoa
protocol ViewController1_Delegate: class {
func passwdEntered(_ correctPasswd: Bool)
}
class ViewController1: NSViewController{
#IBOutlet weak var passwordField: PasswordField!
weak var delegate: ViewController1_Delegate?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func passwordFIeldEdited(_ sender: PasswordField) {
delegate?.passwdEntered(true/*for testing purpose always true*/)
}
}
Finally Second (SubView) ViewController code:
import Cocoa
class ViewController2: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
What I'm doing wrong?
First you say this:
var vc1 : ViewController1 = ViewController1()
override func viewDidLoad() {
super.viewDidLoad()
vc1.delegate = self
Then you say this:
vc1 = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"),
bundle: nil).instantiateController(
withIdentifier: NSStoryboard.SceneIdentifier(
rawValue: "ViewController1")) as! ViewController1
So, you set yourself as delegate on a ViewController1 instance, but then, in the very next line, you throw away that ViewController1 and replace it with another!
Move the line v1.delegate = self down to after you set the real value of vc1.

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 to pass data from one view controller to another?

How do I pass the data from an array of one view controller to another view controller?
FirstViewController:
var myArray = ["some data"]
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
let destinationVC = segue.destination as! SecondViewController
destinationVC.passedArray = myArray
}
SecondViewController:
var passedArray = [String]()
override func viewDidLoad(){
super.viewDidLoad()
print(passedArray)
}
You can try this Solution for Data Transfer.
In FirstViewController.swift
let str = "Hello It's Done"
func callsecondViewController()
{
let controller = storyboard?.instantiateViewController(withIdentifier: "second") as! secondViewController
self.present(controller, animated: true, completion: nil)
}
func temp() -> NSString
{
return str as NSString
}
in SecondViewController.swift
var data = [NSString]()
override func viewDidLoad()
{
super.viewDidLoad()
let view = ViewController()
data = [view.temp()]
print(data)
}
and you get the output String as Hello It's Done

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)