Swift 4 Delegate doesn't work from childViewController - swift

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.

Related

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
}

Error in calling method from another class when using delegates

I have tried to run Second ViewController to change appearance on my first ViewController and progressBar(Progress View) cause error, but if I try to call method keyButtonResponse() from First View Controller error doesn`t appear
First ViewController:
import UIKit
import AVFoundation
import UserNotifications
protocol SomeDelegate {
func keyButtonResponse()
}
class FirstViewController: UIViewController, SomeDelegate{
#IBOutlet weak var label: UILabel!
#IBOutlet weak var progressBar: UIProgressView!
func keyButtonResponse(){
//some code
progressBar.progress = 0.01 //Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
}
}
Second ViewController:
class SecondViewController: UIViewController {
var delegate: SomeDelegate?
func keyButtonResponse(){
delegate?.keyButtonResponse()
}
#IBAction func leftButtonPressed(_ sender: UIButton) {
let myVar = WarningViewController()
let viewController = ViewController()
myVar.delegate = viewController
myVar.keyButtonResponse()
}
}
You're setting the delegate to an instance of a view controller that's unrelated to FirstViewController here.
let viewController = ViewController()
myVar.delegate = viewController
You need to set the delegate to the existing instance of FirstViewController.
If you're using a segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? SecondViewController, segue.identifier == "firstVCToSecondVCSegue" {
vc.delegate = self
}
}
or
if let vc = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController {
vc.delegate = self
self.navigationController?.pushViewController(vc, animated: true)
}
This should be placed within FirstViewController, not SecondViewController.

How do you update the value you delegated from one class to the other?

I'm having an issue with Delegating. I'm relatively new to the concept, and but conceptually I get it and it's importance. I'm just having trouble using it. I can't seem to pass data from one class to the other. I know there are existing examples of delegation out there on stack overflow but they aren't quite capturing my misunderstanding. I get the use of protocols, delegation, and calling it in a class. I believe there just some small nuance that I'm missing... And it's visible in the lack of functionality in my code
//my protocol:
protocol StingHolder {
func StringPasser(ThisText text: String)
}
Creating the delegate protocol relation, places data to be passed then dismisses the View Controller
// my classes for placing data to be passed
class changeLabel: UIViewController,UITextFieldDelegate{
var Delegate: StingHolder?
#IBOutlet weak var TexrBeingPassed: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
TexrBeingPassed.delegate = self
// Do any additional setup after loading the view.
}
#IBAction func ButtonPassingDataOtherView(_ sender: Any) {
Delegate?.StringPasser(ThisText: TexrBeingPassed.text!)
dismiss(animated: true, completion: nil)
}
}
Creates an instance of the change lable class and its delegate and sets itself to be the delegate *supposedly changes the label, but It doesn't
///class to receive data
class ViewController: UIViewController{
#IBOutlet weak var LableName: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
var lableChange = changeLabel()
lableChange.Delegate = self
// Do any additional setup after loading the view.
}
#IBAction func EditController(_ sender: Any) {
var storyBoard = UIStoryboard(name: "Test", bundle: nil)
var ViewController = storyBoard.instantiateViewController(withIdentifier: "TestView")
self.present(ViewController, animated: true, completion: nil)
}
}
inherits the protocol and tells it to change the label to whatever the changelabel class delegate has passes
// extension view controller inheriting the protocol
extension ViewController : StingHolder{
func StringPasser(ThisText text: String){
print("Delegate is working")
LableName.text = text
///
}
}
I want the one view controller to edit the text label of another view controller
The object which you have self as a delegate of, is not the same object presented on the screen.
override func viewDidLoad() {
super.viewDidLoad()
// "labelChange.delegate" is set...
var lableChange = changeLabel()
lableChange.Delegate = self
// Do any additional setup after loading the view.
}
#IBAction func EditController(_ sender: Any) {
var storyBoard = UIStoryboard(name: "Test", bundle: nil)
// but "ViewController" is presented
var ViewController = storyBoard.instantiateViewController(withIdentifier: "TestView")
self.present(ViewController, animated: true, completion: nil)
}
labelChange and ViewController are two different, independent objects. One created by calling init directly, and the other created by calling storyBoard.instantiateViewController. You should set the delegate of the latter instead:
override func viewDidLoad() {
super.viewDidLoad()
// "labelChange.delegate" can be deleted
}
#IBAction func EditController(_ sender: Any) {
var storyBoard = UIStoryboard(name: "Test", bundle: nil)
if let ViewController = storyBoard.instantiateViewController(withIdentifier: "TestView") as? labelChange {
ViewController.delegate = self
self.present(ViewController, animated: true, completion: nil)
}
}

How to show another View controller when a label is clicked

Juts like clicking a button to show another view contoller, is there a way to do that with a label?
Call below function
NOTE: Please set identifier same which you are you in below code
class firstViewController: UIViewController {
#IBOutlet weak var yourlabel: UILabel
override func viewDidLoad() {
super.viewDidLoad()
self.addGesture()
}
func addGesture() {
let tap = UITapGestureRecognizer(target: self, action: #selector(self. labelTapped(_:)))
tap.numberOfTapsRequired = 1
self.yourlabel.isUserInteractionEnabled = true
self.yourlabel.addGestureRecognizer(tap)
}
#objc
func labelTapped(_ tap: UITapGestureRecognizer) {
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let SecondVC = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
self.navigationController?.pushViewController(SecondVC, animated: animated)
}
}
Second ViewController
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}

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