In my project I have implemented a protocol which makes some URL call and return result, and my intent is to show result in UILabel. Following is my code :
protocol RestAPIResult
{
func retriveDriverInfo()
}
class RestAPICall : RestAPIResult
{
func retriveDriverInfo()
{
self.dashBoardViewController.getDriverInfo(driverProfile)
// calling another function of Next View for Lable Setup
}
}
getDriverInfo is in NextView which has Outlet of textVIew
class DashBoardViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
restDeledate = RestAPICall()
restDeledate!.retriveDriverInfo()
// IF LABEL SET HERE NO ERROR
//totalTripLabel.text = "Testing" // NO ERROR
}
func getDriverInfo(driverInfoArray : NSArray)
{
totalTripLabel.text = "Testing" // HERE IS ERROR
}
}
If Text is set in ViewDidLoad() it doesn't crash. but when i tried to set value in delegate function it crash saying found null.
protocol RestAPIResult: NSObjectProtocol
{
func retriveDriverInfo(message: String)
}
class RestAPICall : RestAPIResult
{
override func viewDidLoad()
{
super.viewDidLoad()
//create an instance of your vc and
instance.delegate = self
//if you code for push vc then write this line there insatance.delegate = self
}
func retriveDriverInfo(message: String)
{
yourLbaelOutlet.text = message
}
}
class DashBoardViewController: UIViewController
{
weak var delegate: RestAPIResult!
override func viewDidLoad()
{
super.viewDidLoad()
}
func getDriverInfo(driverInfoArray : NSArray)
{
self.delegate.retriveDriverInfo(message: "youMessage")
}
}
*
Related
I am using delegates to get a string value from my modal. When the modal closes I am trying to update Label text using that string. However, I am getting error: Unexpectedly found nil while implicitly unwrapping an Optional value: file. I am not sure how to fix this. I think it's happening because the view is not yet active.
import Cocoa
class ViewControllerA: NSViewController, SomeDelegate {
#IBOutlet weak var msgLabel: NSTextField!
var s: String = "";
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func setDetails(s: String) {
self.user = s;
print("Notified", self.s) // <-- prints: Notified hello again
msgLabel.stringValue = self.s <-- DOESN'T WORK
}
func showModal() -> Void {
msgLabel.stringValue = "hello" // <--- WORKS
let cbvc: NSViewController = {
return self.storyboard!.instantiateController(withIdentifier: "ControllerBVC")
as! NSViewController
}()
self.presentAsModalWindow(cbvc);
}
#IBAction func onBtn(_ sender: Any) {
self.showModal();
}
}
protocol SomeDelegate {
func setDetails(s: String)
}
class ViewControllerB: NSViewController {
#IBOutlet weak var textF: NSTextField!
var delegate: SomeDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
let vc = ViewControllerA()
self.delegate = vc
}
#IBAction func onBtn(_ sender: Any) {
DispatchQueue.main.async {
self.delegate?.setDetails(s: self.textF.stringValue)
self.dismiss("ControllerAVC")
}
}
}
You have a number of problems.
In ViewControllerB.viewDidLoad you are assigning a new instance of ViewControllerA to the delegate property. Don't do that. Your viewDidLoad method should look like this:
override func viewDidLoad() {
super.viewDidLoad()
}
In the showModal method ViewControllerA should assign itself as the delegate on ViewControllerB before ViewControllerB it is presented.
func showModal() -> Void {
let cbvc: NSViewController = {
let vc = self.storyboard!.instantiateController(withIdentifier: "ControllerBVC")
as! ViewControllerB
vc.delegate = self
return vc
}()
self.presentAsModalWindow(cbvc);
}
In the setDetails method just assign the string to your text field directly:
func setDetails(s: String) {
msgLabel.stringValue = s
}
Struggling to learn the basics of passing data via delegates. I am trying to pass a string from my viewController to my viewController2 and print it. I am getting the error:
"Type ViewController2 has no member delagate" in my view controller 2.
I cannot figure out where I have gone wrong.
viewController 1:
protocol datadelagate {
func printThisString(string: String)
}
class ViewController: UIViewController {
var delegate: datadelagate?
override func viewDidLoad() {
delegate?.printThisString(string: "This was passed from first controller to second controller")
}
}
This is my viewController 2:
class ViewController2: UIViewController, datadelagate {
func printThisString(string: String) {
print(string)
}
override func viewDidLoad() {
super.viewDidLoad()
ViewController2.delagate = self
print(String.self)
}
}
If you want ViewController2 to print some value from ViewController, you might have to do it this way:
protocol datadelagate {
func printThisString(string: String)
func getStringFromVC1() -> String
}
class ViewController: UIViewController, datadelagate {
let someString: String = "From VC1"
func printThisString(string: String) {
print(string)
}
func getStringFromVC1() -> String {
return someString
}
override func viewDidLoad() {
ViewController2.delagate = self
}
}
class ViewController2: UIViewController {
var delegate: datadelagate?
override func viewDidLoad() {
super.viewDidLoad()
//This is how something from VC2 is sent to VC1's scope.
delegate?.printThisString(string: "Calling the delegate to print something from ViewController2 on first ViewController")
//The below call gets you some value from VC1. (This is what you wanted, I belive...)
print(delegate?.getStringFromVC1())
}
}
Now for some explanation:
For simple understanding, assume a delegate as a person who does some specific job (protocol).
You have a `delegate'
You ask your delegate to work with your friend, and your friend acknowledges. (assigns your delegate by You.delegate = self, where self is your friend)
Now, through your delegate, you can do something with your friend, by asking your delegate to do some job (defined in protocol).
EDIT
The code above won't work, as non-static data members are trying to be accessed without creating an instance
Working code
import UIKit
class ViewController2: UIViewController {
static let sharedInstance = ViewController2()
weak var delegate: DataDelagate?
override func viewDidLoad() {
super.viewDidLoad()
//This is how something from VC2 is sent to VC1's scope.
delegate?.printThis(string: "Calling the delegate to print something from ViewController2 on first ViewController")
//The below call gets you some value from VC1. (This is what you wanted, I belive...)
print(delegate?.getStringFromVC1() ?? "s")
}
}
class ViewController: UIViewController {
static let sharedInstance = ViewController2()
var someString: String = "From VC1"
override func viewDidLoad() {
super.viewDidLoad()
ViewController2.sharedInstance.delegate = self
}
}
extension ViewController: DataDelagate {
func printThis(string: String) {
print(string)
}
func getStringFromVC1() -> String {
return someString
}
}
protocol DataDelagate: AnyObject {
func printThis(string: String)
func getStringFromVC1() -> String
}
I am using Xcode 10.3. I have protocol which method is not calling. What is wrong?
My first view controller with protocol:
protocol MyProtocol: class {
func doGetUpdateInfo(valu1:String,value2:String);
}
class Class_A : UIViewController{
weak var myprotocolDelegate:MyProtocol? = nil;
override func viewDidLoad() {
super.viewDidLoad()
myprotocolDelegate?.doGetUpdateInfo(account_no:value1, account_title: value2)
}
}
My second view controller
class Class_B: UIViewController,UpdateBeneficiaryProtocol {
var class_a = Class_A()
override func viewDidLoad() {
super.viewDidLoad()
class_a.myprotocolDelegate = self;
}
func doGetUpdateInfo(value1: String, value2: String) {
print("not calling****")
}
}
What is the wrong with it?
Please see the below example. you are creating a new class for A but so it will not be called. you need to provide a reference for the current class
protocol MyProtocol: class {
func doGetUpdateInfo(valu1:String,value2:String);
}
class Class_A : UIViewController{
weak var myprotocolDelegate:MyProtocol? = nil;
override func viewDidLoad() {
super.viewDidLoad()
myprotocolDelegate?.doGetUpdateInfo(account_no:value1, account_title: value2)
}
func navigateToClassB() {
let classb = Class_B()
classb.class_a = self
self.navigationController?.pushViewcontroller(classb, animated:true)
}
}
And class b should be
class Class_B: UIViewController,UpdateBeneficiaryProtocol {
var class_a : Class_A?
override func viewDidLoad() {
super.viewDidLoad()
class_a.myprotocolDelegate = self;
}
func doGetUpdateInfo(value1: String, value2: String) {
print("not calling****")
}
}
Push controller Class_b as per display in method navigateToClassB.
If you face still issue comment here I will assist you.
And just that I'm exercising the delegated pattern. I created a simple application where a delegate sends a message to UIViewController saying if you stop or start UIActivityIndicatorView. Unfortunately I get the following error: error atal: unexpectedly found nil while unwrapping an optional value.
It would seem that UIActivityIndicatorView is not initialized. I can not understand where I'm wrong.
protocol ProgressBarDelegate {
func UpdateProgressBar(progress: Bool)
}
class Dao: NSObject {
var delegate: ProgressBarDelegate?
override init() {
super.init()
//DELEGATO
//I who should I send the message? to FirstViewController
let messaggero = FirstViewController()
self.delegate = messaggero
scriviUnMessaggio(progress: true)
}
func scriviUnMessaggio(progress: Bool){
print("I'm writing a message ...")
delegate?.UpdateProgressBar(progress:progress)
}
My controller
class FirstViewController: UIViewController,ProgressBarDelegate {
#IBOutlet var activity: UIActivityIndicatorView!
func UpdateProgressBar(progress: Bool){
print("I received the message from Dao class (the delegate)")
switch progress{
case true:
// At this point I get the following error:Fatal error: unexpectedly found nil while unwrapping an Optional value
self.activity.startAnimating()
case false:
self.activity.stopAnimating()
default:
self.activity.startAnimating()
}
}
override func viewDidLoad() {
super.viewDidLoad()
let dao = Dao()
/// dao.caricamentoDati()
The problem is that you're creating a new object of FirstViewController in init of Dao. Since FirstViewController object is not created via xib/storyboard hence the outlet is not connected. That's why it's giving crash at self.activity.startAnimating()
Set the delegate to self in viewDidLoad
Change your Doa's init method as follow
class Dao: NSObject {
var delegate: ProgressBarDelegate?
init(delegate: ProgressBarDelegate) {
super.init()
//DELEGATO
//I who should I send the message? to FirstViewController
self.delegate = delegate
scriviUnMessaggio(progress: true)
}
func scriviUnMessaggio(progress: Bool){
print("I'm writing a message ...")
delegate?.UpdateProgressBar(progress:progress)
}
Then in viewDidLoad do this
override func viewDidLoad() {
super.viewDidLoad()
let dao = Dao(delegate: self)
}
I have a parent ui view controller and it has a method responsible for printing data to the console:
func printSomeData() {
print("printing some data")
}
It also has a container with embedded UITableViewController. The table itself has a pull to refresh functionality implemented and it prints the string when user pulls the table:
func refresh(refreshControl: UIRefreshControl) {
print("Refreshing!!")
refreshControl.endRefreshing()
}
Now I want to call printsomeData from the refresh method.
This is what I try:
parent UIViewController:
class MainMenu: UIViewController, printing{
func printSomeData() {
print("some date")
}
}
embedded UITableViewController:
protocol printing{
func printSomeData()
}
class MainMenuTableViewController: UITableViewController {
var delegate: printing?
func refresh(refreshControl: UIRefreshControl) {
print("Refreshing!!")
if let _ = delegate{
delegate?.printSomeData()
}
refreshControl.endRefreshing()
}
But now when I pull the table I only see Refreshing!!, there is no way I could see printing some data. What am I doing wrong?
Where are you assigning the delegate?
And write the optional method call as a single line
delegate?.printSomeData()
or like that:
if self.delegate != nil {
self.delegate!.printSomeData()
}
Inside MainMenu
override func viewDidLoad() {
super.viewDidLoad()
// tableViewController is placeholder for `MainMenuTableViewController` reference
tableViewController.delegate = self
}
If i have understand you correctly and the MainMenu has a ContainerView with MainMenuTableViewController than should this solve your problem:
class MainMenu: UIViewController, Printer {
func printSomeData() {
print("some date")
}
}
protocol Printer {
func printSomeData()
}
class MainMenuTableViewController: UITableViewController {
var printer: Printer? {
guard let printer = self.parentViewController as? Printer else {
return nil
}
return printer
}
func refresh(refreshControl: UIRefreshControl) {
print("Refreshing!!")
printer?.printSomeData()
refreshControl.endRefreshing()
}
}