Setting delegate of another class with screen view to self - swift

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
}
}

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

#IBDesignable with protocol

I have a UIview xib within a view controller, UIview class have two buttons with protocol function, but the protocol function never called when I press button, storyboard image like below
protocol method like below
import UIKit
#objc protocol TopViewDelegate: NSObjectProtocol {
#objc optional func pressRefreshButton()
#objc optional func pressMenuButton()
}
UIView class
#IBDesignable class OnJob_Top: UIView,TopViewDelegate {
weak var delegate : TopViewDelegate? = nil
#IBAction func refreshButtonTouchUpInside(_ sender: UIButton) {
delegate?.pressRefreshButton!()
}
#IBAction func menuButtonTouchUpInside(_ sender: UIButton) {
delegate?.pressMenuButton!()
print("come come")
}
view controller class
class HomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let topView = OnJob_Top()
topView.delegate = self
}
}
extension HomeViewController:TopViewDelegate {
func pressMenuButton() {
print("come") // never come here
}
func pressRefreshButton() {
print("come") // never come here
}
}
Consider this code:
let topView = OnJob_Top()
topView.delegate = self
In the first line, you create a completely new OnJob_Top view.
In the second line, you make it the delegate.
In the third line... but there is no third line. The view vanishes in a silent puff of smoke. It is useless.
Meanwhile, the view in the storyboard never gets a delegate. So its delegate methods are never called.

How do I call a function from a different view controller?

I have what is basically a notes app, and I am trying to call a function that is in one view controller from another. How do I do this, or is there a better way I should do it?
Here's where I am trying to call the function from
class NoteDetailViewController: UIViewController
{
#IBOutlet weak var funcButton: UIButton!
#IBAction func funcButTouched(sender: UIButton)
{
// where i want to call the function
}
}
And where the function is
class ListTableViewController: UITableViewController
{
// the function
func wordCount()
{
var contentArr = Project.sharedInstance.content.componentsSeparatedByString(" ")
for (index, element) in contentArr.enumerate()
{
let location = conciseArr.indexOf(element)
if (location != nil)
{
contentArr[index] = inflatedArr[location!]
afterStr = contentArr.joinWithSeparator(" ")
Project.sharedInstance.after = afterStr
}
}
}
}
I've tried just creating an instance of ListTableViewController and just calling the function that way but I get an error.
You could use delegation.
First, declare a delegate protocol. This should be in your NoteDetailViewController.swift file but outside of the class declaration:
protocol NoteDetailViewControllerDelegate: class {
func noteDetailViewControllerButtonTouched(controller: NoteDetailViewController)
}
Next, add a delegate property to your NoteDetailViewController:
weak var delegate: NoteDetailViewControllerDelegate?
Now, we use the #IBAction to tell the delegate, which will be the ListTableViewController:
#IBAction func funcButTouched(sender: UIButton)
{
delegate?.noteDetailViewControllerButtonTouched(self)
}
Finally, back in ListTableViewController (assuming this controller is the one directly before a NoteDetailViewController is shown), conform to the protocol and use prepareForSegue to set the delegate to itself:
class ListTableViewController: UITableViewController, NoteDetailViewControllerDelegate {
// ... more stuff ...
// Implement the delegate protocol
func noteDetailViewControllerButtonTouched(controller: NoteDetailViewController) {
// Do something! The button was pressed!
wordCount()
}
// Set ourselves as delegate when we are about to show the other view controller
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let yourVC = segue.destinationViewController as? NoteDetailViewController {
yourVC.delegate = self
}
}
}
You should finish with something like this:
NoteDetailViewController.swift:
class NoteDetailViewController: UIViewController
{
#IBOutlet weak var funcButton: UIButton!
weak var delegate: NoteDetailViewControllerDelegate?
#IBAction func funcButTouched(sender: UIButton)
{
delegate?.noteDetailViewControllerButtonTouched(self)
}
}
protocol NoteDetailViewControllerDelegate: class {
func noteDetailViewControllerButtonTouched(controller: NoteDetailViewController)
}
ListTableViewController.swift:
class ListTableViewController: UITableViewController, NoteDetailViewControllerDelegate
{
// the function
func wordCount()
{
var contentArr = Project.sharedInstance.content.componentsSeparatedByString(" ")
for (index, element) in contentArr.enumerate()
{
let location = conciseArr.indexOf(element)
if (location != nil)
{
contentArr[index] = inflatedArr[location!]
afterStr = contentArr.joinWithSeparator(" ")
Project.sharedInstance.after = afterStr
}
}
}
// Implement the delegate protocol
func noteDetailViewControllerButtonTouched(controller: NoteDetailViewController) {
// Do something! The button was pressed!
wordCount()
}
// Set ourselves as delegate when we are about to show the other view controller
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let yourVC = segue.destinationViewController as? NoteDetailViewController {
yourVC.delegate = self
}
}
}
Just follow bellow code its very simple :-
NoteDetailViewController.swift:
class NoteDetailViewController: UIViewController
{
#IBOutlet weak var funcButton: UIButton!
var parentListTableView : ListTableViewController!
#IBAction func funcButTouched(sender: UIButton)
{
parentListTableView.wordCount()
}
}
ListTableViewController.swift:
class ListTableViewController: UITableViewController
{
// the function
func wordCount()
{
var contentArr = Project.sharedInstance.content.componentsSeparatedByString(" ")
for (index, element) in contentArr.enumerate()
{
let location = conciseArr.indexOf(element)
if (location != nil)
{
contentArr[index] = inflatedArr[location!]
afterStr = contentArr.joinWithSeparator(" ")
Project.sharedInstance.after = afterStr
}
}
}
// Set ourselves as delegate when we are about to show the other view controller
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let yourVC = segue.destinationViewController as? NoteDetailViewController {
yourVC.parentListTableView = self
}
}
}

Delegate keeps returning nil

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