IBOutlet always nil in ViewController methods but ok in IBAction & Viewdidload - ios

I try to access some IBOutlet outside of Viewdidload and IBAction, and always get nil value. In Viewdidload and IBAction, those value are ok. Did i miss a part to declare or initialize something ?
The value are modified after viewdidload() because viewdidload is called bu the IBAction.
The View is created in storyboard, coming from a UINavigation Controller.
connection table between ViewController and UIView:
The loginServer method is called by userCredential delegate, as below:
protocol userCredentialDelegate {
func didUpdateCredential (sender:String, credential: Bool?)
}
class userCredential: NSObject {
var delegate:userCredentialDelegate?
// self.delegate = ViewController() removed
func loginServer (name: String, pwd: String) -> Bool {
dispatch_sync(dispatch_get_main_queue())
{
self.delegate?.didUpdateCredential ("login", credential: credentialStatus)
}
}
Main controller:
class ViewController: UIViewController, userCredentialDelegate {
// set the shared instance
let user = userCredential.sharedInstance
#IBOutlet weak var incorrectCredentials: UITextField!
#IBOutlet weak var username: UITextField!
#IBOutlet weak var password: UITextField!
#IBOutlet weak var logButton: UIButton!
#IBAction func logButton(sender: UIButton) {
print (incorrectCredentials?.hidden)
if logButton.titleLabel!.text == "Log Out" {
user.logoutServer ()
} else {
user.loginServer(username.text!, pwd: password.text!)
}
}
func didUpdateCredential (sender: String, credential: Bool?) {
switch sender {
case "login":
if credential! {
performSegueWithIdentifier("loginSegue", sender: self)
} else {
incorrectCredentials?.hidden = false
}
default: break
}
if let credentialResponse = credential {
loginStatus = credentialResponse
}
}
var loginStatus: Bool = false {
didSet {
if loginStatus {
incorrectCredentials?.hidden = true // always nil before, now ok
} else {
incorrectCredentials?.hidden = false // always nil before, now ok
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
user.delegate = self
incorrectCredentials.hidden = true // can work here
user.getUserInfo ()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
connection table:

You need to set the delegate to your user model in your viewDidLoad function.
Before doing user.getUserInfo() make user.delegate = self
currently you create a new Instance on the user model, that has nothing todo with you real loaded ViewController.

Related

Changing Label text on main controller after modal closed swift macOS

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
}

Protocol implementation method not calling in Swift

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.

How to receive tag pressed event using tagListView?

I'm using cocoa pod of TagListView https://github.com/ElaWorkshop/TagListView. And I need to catch the tagPressed event. I know that I should implement the delegate TagListViewDelegate, but I don't know where and how. Sorry for bad eng.
Here's my code
import UIKit
import TagListView
class MoreInfoViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet weak var tagListView: TagListView!
#IBOutlet weak var tagNameTextField: UITextField!
#IBAction func addTagButtonPressed(_ sender: UIButton) {
guard tagNameTextField.text != "" else { return }
let tagName = tagNameTextField.text!
tagNameTextField.text = ""
tagListView.addTag(tagName)
}
}
Quoting directly from the documentation,
You can implement TagListViewDelegate to receive tag pressed event:
// ...
{
// ...
tagListView.delegate = self
// ...
}
func tagPressed(title: String, tagView: TagView, sender: TagListView) {
print("Tag pressed: \(title), \(sender)")
}
Simply define your delegate and place the function within the controller and touch events should be called to this function.

unexpectedly found nil while unwrapping an Optional value On UILabel

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")
}
}
*

Swift Barcode Scanning

I am attempting add barcode scanning to my app using RSBarcodes. I'm having two issues: Not being able to update a label that displays the barcode scanned and the delegate to send the barcode to my calling view controller not working. Below is my code for the view controller that handles the scanning:
import UIKit
import AVFoundation
import RSBarcodes
class ScanViewController: RSCodeReaderViewController {
#IBOutlet weak var label1Label: UILabel!
#IBOutlet weak var label2Label: UILabel!
#IBOutlet weak var scanLabel: UIButton!
var delegate: barcodesScannedDelegate?
var codes:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
var code=""
// Do any additional setup after loading the view.
focusMarkLayer.strokeColor = UIColor.redColor().CGColor
cornersLayer.strokeColor = UIColor.yellowColor().CGColor
tapHandler = { point in
//println(point)
}
barcodesHandler = { barcodes in
for barcode in barcodes {
if !contains(self.codes, barcode.stringValue) {
self.codes.append(barcode.stringValue)
code = barcode.stringValue
}
}
println(code)
self.label1Label.text = code
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func finishedPressed(sender: UIButton) {
delegate?.barcodesScanned(self.codes)
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func cancelPressed(sender: UIButton) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
Just to ensure I did the delegate correctly, here is my code in Protocol.swift:
protocol selectCarrierDelegate {
func selectCarrier(carrierID: String,carrier: String)
}
protocol barcodesScannedDelegate {
func barcodesScanned(barcodes: [String])
}
And the relevant code in the controller that should receive the barcode:
class InBoundViewController: UIViewController,selectCarrierDelegate,UIAlertViewDelegate,UITableViewDelegate,UITableViewDataSource,barcodesScannedDelegate {
func barcodesScanned(barcodes: [String]) {
println("codes=\(barcodes)")
}
Anyone have any ideas why the label won't change and the delegate isn't working?
You need to update all UI in the main thread.
Try this:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.label1Label.text = code
})
Swift 4:
DispatchQueue.main.async {
self.label1Label.text = code
}

Resources