Delegate keeps returning nil - swift

in my view controller, i have set up like this.
protocol MenuDelegate {
func updateIndexOfMenuExpanded(index: Bool)
}
class ViewController: UIViewController,UITableViewDataSource, UITableViewDelegate {
var delegate : MenuDelegate?
func performaction() -> Void{
delegate!.updateIndexOfMenuExpanded(false)
}
}
and in my baseviewcontroller
class BaseViewController: UIViewController, MenuDelegate{
func updateIndexOfMenuExpanded(index: Bool){
self.menuIsExpanded = index
}
}
please help. thank you.

You have to set the delegate first.
let viewController = ViewController()
let baseViewController = BaseViewController()
viewController.delegate = baseViewController
It would also be wise to make the delegate a weak reference and to not force unwrap with !.
class ViewController: UIViewController,UITableViewDataSource, UITableViewDelegate {
weak var delegate : MenuDelegate?
func performaction() {
delegate?.updateIndexOfMenuExpanded(false)
}
}

Delegate is used when you want to pass data between viewcontrollers.this aproach is one to one
Here is the answer how to pass data using delegate
in viewcontroller
define protocol in view controller
protocol ViewController1BackClicked {
func btnBackClicked(str : String)
}
class ViewController1: UIViewController {
var strTitle : String?
var delegate : ViewController1BackClicked?
override func viewDidLoad() {
super.viewDidLoad()
if strTitle != nil{
title = strTitle
}
}
override func viewWillDisappear(animated: Bool) {
delegate?.btnBackClicked("Krutarth")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
now Protocol is created.to pass data in another view controller
viewcontroller 1 we want to access data
func btnBackClicked(str: String) {
title = str
}
output : Krutarth
this is example how to use protocol

Related

How can I pass a textfield value from one ViewController to a second ViewController (MacOS Swift)?

I'm working on a project and my ViewController file is starting to get very long. Hence, I want to define all my functions in a second ViewController so I can delete some code from my first ViewController. This works, except for when I try to refer to a value from a textField defined in my FirstViewController, it returns nil. I am new to MacOS development so I would greatly appreciate simple/specific feedback.
This is an example of my first ViewController (it initializes variables and uses functions):
class FirstViewController: NSViewController, NSTextFieldDelegate {
#IBOutlet weak var firstName: NSTextField!
let lastName = "Smith"
#IBAction func buttonPressed(_ sender: Any) {
SecondViewController().printUserName()
}
}
This is my second ViewController (it defines functions):
class SecondViewController: NSViewController, NSTextFieldDelegate {
func printUserName() {
print(FirstViewController().firstName!) // this returns nil :(
print(FirstViewController().lastName) // this returns "Smith" :)
}
}
If you use the UINavigationController to move to the second VC, you can simply define a second view and then access the variables in that view.
example, FirstViewController
class FirstViewController: NSViewController, NSTextFieldDelegate {
#IBOutlet weak var firstName: NSTextField!
let lastName = "Smith"
#IBAction func buttonPressed(_ sender: Any) {
guard let secondView = self.storyboard?.instantiateViewController(identifier: "SecondViewController") as? SecondViewController else {
return
}
self.navigationController?.pushViewController(secondView, animated: false)
secondView.textValue = firstName.text
}
}
SecondViewController
class SecondViewController: NSViewController, NSTextFieldDelegate {
var textValue: String?
override func viewDidLoad() {
printUserName()
}
func printUserName() {
if let text = textValue {
print(text)
}
}
}

How to execute func present in a ViewController from another?

I am a beginner in Swift, and I do not yet understand all the elements.
I am trying to execute a function present in a ViewController (ProjectTabBarController) from another ViewController (ProjectInfosViewController). I end up with an error when I execute the function from the second.
For the context, it is for a navigation button of 3 UIViewController belonging to a UITabBarViewController, itself embedded in a UINavigationController
Thank you in advance ! (Sorry for my bad English)
import UIKit
//MARK:-TAB CONTROLLER
class ProjectTabBarController: UITabBarController {
#IBOutlet weak var ui_saveButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func saveAction(_ sender: Any) {
// code
disableSaveButton() // ALL IT'S FINE HERE
}
func enableSaveButton() {
ui_saveButton.title = "Save"
ui_saveButton.isEnabled = true
}
func disableSaveButton() {
ui_saveButton.title = "Saved"
ui_saveButton.isEnabled = false
} }
//MARK:-PROJECT INFORMATIONS
class ProjectInfosViewController: UIViewController, UITextFieldDelegate {
let superController = ProjectTabBarController()
override func viewDidLoad() {
super.viewDidLoad()
}
func textFieldDidChangeSelection(_ textField: UITextField) {
superController.enableSaveButton() // BUT HERE, DOESN'T
} }
//MARK:-PROJECT FIXTURES
class ProjectFixturesViewController: UIViewController, UITableViewDataSource {
}
//MARK:-PROJECT CONTACT
class ProjectContactViewController: UIViewController {
}
This
let superController = ProjectTabBarController()
is a new vc that's not presented , if the vc is inside the tabController then do
let res = self.tabBarController as! ProjectTabBarController
res.......// call what you need

Delegates is not working?

here is my protocol definition.
protocol ActivityIndicatorDelegate: class {
func showIndicator()
func hideIndicator()
func barcodeError()
func categoryError()
func descError()
func reasonError()
func costError()
}
Then in my Custom cell class I create weak reference and I call delegate function
class ProductTableViewCell: UITableViewCell {
weak var indicatorDelegate: ActivityIndicatorDelegate?
#IBAction func stockUpdate(_ sender: Any) {
indicatorDelegate?.categoryError()
}
}
Then in my UITableViewController class
class ProductTableViewController:
UITableViewController,ActivityIndicatorDelegate{
override func viewDidLoad() {
super.viewDidLoad()
let cellDelegate = ProductTableViewCell()
cellDelegate.indicatorDelegate = self
}
func categoryError() {
//self.showAlert(alertTitle: "Error!", alertMessage: "Category Should not be empty")
print("Error")
}
}
I have written all these in a single file. What I'm doing wrong here? Can some one help me to solve this. Thanks in advance.
You should not set the delegate in viewDidLoad. This will only set the delegate of the cell that you just created, instead of all the cells in the table view.
You should do this in celForRowAtIndexPath:
let cell = tableView.dequeue...
// configure the cell...
cell.indicatorDelegate = self

Setting delegate of another class with screen view to self

I'm fairly new at iOS programming. I have this setup:
ViewController view on IB, with class ViewController
SecondController view on IB, with class secondController
I have protocol:
protocol SecondControllerDelegate {
func getSomething() -> String
}
and I have delegate variable on SecondController:
class secondController: UIViewController {
var delegate: SecondControllerDelegate?
#IBOutlet weak var labelStatus: UILabel!
override func ViewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonTouch(sender: AnyObject) {
labelStatus.text = delegate?.getSomething()
}
func try () {
labelStatus.text = "testing"
}
}
Now, according to the hints everywhere, in order so I can call delegate?.getSomething() at SecondController.buttonTouch(), I need to set like this on viewController:
class ViewController: UIViewController, SecondControllerDelegate {
override func viewDidLoad () {
super.viewDidLoad()
SecondController.delegate = self
}
func doSomething () -> String {
return "testing"
}
}
But this generates error 'SecondController.type' does not have a member named 'delegate'.
Some other websites say:
class ViewController: UIViewController, SecondControllerDelegate {
var secondController = SecondController()
override func viewDidLoad () {
super.viewDidLoad()
secondController.delegate = self
}
func doSomething () -> String {
return "testing"
}
}
With this, there are no error. But if I do something on the second screen that should call the delegate, it doesn't call the delegate, like the SecondController is two different objects (one is created by StoryBoard, one is created manually within the ViewController), i.e. the labelStatus that should have changed to "testing", doesn't change at all. But it changes if function try() is called. How am I supposed to do this?
EDIT: I forgot to mention that I used NavigationController, and segue to transition from first screen to second screen.
Because you try to learn how to build a delegate in Swift, I have written you a plain delegate example below
protocol SecondViewControllerDelegate {
func didReceiveInformationFromSecondViewcontroller (information: String)
}
class ViewController: UIViewController, SecondViewControllerDelegate {
func openSecondViewController () {
if let secondViewControllerInstance: SecondViewController = storyboard?.instantiateViewControllerWithIdentifier("SecondViewController") as? SecondViewController {
secondViewControllerInstance.delegate = self
navigationController?.pushViewController(secondViewControllerInstance, animated: true)
}
}
func didReceiveInformationFromSecondViewcontroller(information: String) {
////Here you get the information, after sendInfoToViewController() has been executed
}
}
class SecondViewController: UIViewController {
var delegate: SecondViewControllerDelegate?
func sendInfoToViewController () {
delegate?.didReceiveInformationFromSecondViewcontroller("This ist the information")
}
}
UPDATE
Following the same thing in using Storyboard Segues
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let secondViewControllerInstance: SecondViewController = segue.destinationViewController as? SecondViewController {
secondViewControllerInstance.delegate = self
}
}

swift ios delegate runs simultaneously in multiple classes

H!
I using a tutorial learing swift and now I want to know if this is possible.
Or how to do this a better way.
AController.swift
protocol AControllerProtocol {
func updateGui()
}
class AController {
func doSomething(){
// here I get incomming data and other stuff
// then the gui in multiple views needs an update
self.delegate.updateGui()
}
var delegate: AControllerProtocol
init(delegate: AControllerProtocol) {
self.delegate = delegate
}
}
BViewController.swift
class BViewController: AController {
#IBOutlet var tableView: UITableView!
var acontroller : AController?
override func viewDidLoad() {
super.viewDidLoad()
acontroller = AController(delegate: self)
}
func updateGui() {
// dispatch_async(dispatch_get_main_queue(), {
self.tableView!.reloadData()
// works, it runs this method and this tables is inside this BViewController
// })
}
}
CViewController.swift
class CViewController: AController {
lazy var acontroller : AController = AController(delegate: self)
#IBOutlet weak var tracksTableView: UITableView!
func updateGui() {
// dispatch_async(dispatch_get_main_queue(), {
self.tracksTableView!.reloadData()
// din't run, this table is only in this CViewController
// it only did run BViewController updateGui()
// })
}
}
As you can see I have two views:
BViewController.swift
tableView
CViewController.swift
tracksTableView
AController get some data and then fires the delegate.
I thought it will run the delegate in both views, so it can work in multiple classes, but it don't.
It only runs inside the BViewController.swift
Then I thought, maybe this is not the correct way to do this, (pushing updates to other classes).
A simple other solution would be something like this ?
BViewController.swift
class BViewController: AController {
#IBOutlet var tableView: UITableView!
var acontroller : AController?
override func viewDidLoad() {
super.viewDidLoad()
acontroller = AController(delegate: self)
}
func updateGui() {
// dispatch_async(dispatch_get_main_queue(), {
self.tableView!.reloadData()
// get to know how to do this here
CViewController.tracksTableView!.reloadData()
// })
}
}
CViewController.swift
class CViewController {
#IBOutlet weak var tracksTableView: UITableView!
}
Greetings,
Martijn
Have a look at NotificationCenter.
A controller could fire a notification when data arrives and dispatch it to the NotificationCenter.
B and C view controller could listen for that notification and add an observer with NotificationCenter. Their handlers would be triggered when the notification is posted.