Error passing value to view controller on dismiss | Swift 5 - ios

Error transferring value from one view controller to another on dismiss.
I have a value in ViewController2 that I would like to transfer to ViewController1 on dismiss. In view ViewController2 I do the following to dismiss:
func OtherFunction() {
passAndDismiss(scannedScript: stringCodeValue)
}
Note: stringCode value is indeed being passed as a String to scannedScript
func passAndDismiss(scannedScript: String) {
dismiss(animated: true, completion: {
let viewcontroller = ViewController1()
viewcontroller.Textfield1.text = scannedScript
})
}
The error occurs on line:
viewcontroller.Textfield1.text = scannedScript
The error I get is:
Unexpectedly found nil while implicitly unwrapping an Optional value

Two fatal issues:
ViewController1() is a new instance of the controller which is not the instance in the storyboard.
Solution: You need the real instance either with a segue or with instantiation from the storyboard.
Even if ViewController1() was the expected controller the outlets are not connected right after the initialization.
Solution: You have to declare a temporary property for the string in ViewController1 and assign the value to the label in viewDidLoad

Here you are initialising viewcontroller with wrong way. You should load from xib or storyboard.
In your way not initialise xib or storyboards’ ui element objects. Here textfield object nil and you are trying to access text property of that. That’s why app crashed. You should use following way:
let myViewController = MyViewController(nibName: "MyViewController", bundle: nil)
OR
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "someViewController")
If you are not using xib or storyboard then please initialise textfield object in that controller’s init method

Related

can't cast LaunchViewController to UINavigationController

I am trying to check the network status from the AppDelegate.swift instead of checking from LaunchViewController.
I have written showOfflinePage in AppDelegate when I shut down my network I have this error cast
Could not cast value of type
'reachability_playground.LaunchViewController' (0x1095b5f20) to
'UINavigationController' (0x114bb2a20). 2019-01-06
16:42:04.079430-0500 reachability-playground[2781:93635] Could not
cast value of type 'reachability_playground.LaunchViewController'
(0x1095b5f20) to 'UINavigationController' (0x114bb2a20).
private func showOfflinePage() -> Void {
DispatchQueue.main.async {
let storyboard = UIStoryboard(name: "Main", bundle: nil);
let viewController: LaunchViewController = storyboard.instantiateViewController(withIdentifier: "LaunchViewController") as! LaunchViewController;
// Then push that view controller onto the navigation stack
let rootViewController = self.window!.rootViewController as! UINavigationController
rootViewController.pushViewController(viewController, animated: true);
}
}
As per the exception message, your root view controller is an instance of LaunchViewController, not an instance of UINavigationController so the forced downcast fails.
You need to check your storyboard and ensure that the entry point scene is a navigation controller.

unwrap optional value nil

I am new in ios developer.I pass my data to one view controller to another using function
var vc = MessageViewController()
vc.printSomething(address: address,id: id)
I pass address and id to MessageViewController.In MessageViewController
func printSomething(address: String,id: String) {
print("address",address)
print("id",id)
address_text.text = "\(address)"
}
Above code I print address,id but when i set address on UITextField address.text I got unwrapping error.
I used to create a class method to instantiate view controller from storyboard like this...
class MessageViewController: UIViewController {
//other methods
//MARK:- Class Method
class func viewController() -> MessageViewController {
return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "<Storyboard Id>") as! MessageViewController
}
}
You need to just use to instantiate view controller
var vc = MessageViewController.viewController()
You can set storyboard identifier like in below image.
Hi it is the issue with variable not assigned to address_text beacuse xib not initialized at that time of your method(printSomething) calling, before that take two varibles for saving the address and id in MessageViewController and assign id and address to those variables in printSomething method and you can assing those values to address_text in viewdidload method of MessageViewController

Setting Init VC in App Delegate?

I am trying to init my core data stack with the init VC of my app. To do this I want to pass the core data manager i have created into the first VC upon loading.
I thought this code would make sense to pass the coredatamanager into the VC, however I get errors whichever way i write this code, im sure im missing something simple?
// Initialize Storyboard
let storyboard = UIStoryboard(name: "RoutineController", bundle: Bundle.main)
// Instantiate Initial View Controller
if let viewController = storyboard.instantiateInitialViewController() as? ViewController {
// Configure View Controller
viewController.coreDataManager = coreDataManager
// Set Root View Controller
window?.rootViewController = viewController
}
Error is simply:
Use of undeclared type 'ViewController'
However if i delete 'as? ViewController' I get an error on the following line that viewController has no property coreDataManager.
Is there some sort of delegate i need to define in the viewdidload of the view controller in sending to?
EDIT Revised my code to correct the storyboard ID, however the code inside the {} doesnt seem to execute, i get the printed error i wrote due to the if let failing, so this still isnt the right way to set the viewController...any ideas as to why?
// Initialize Storyboard
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
// Instantiate Initial View Controller
if let viewController = storyboard.instantiateInitialViewController() as? RoutineController {
// Configure View Controller
print("SENDING THIS INFO TO THE FIRST VC \(self.coreDataManager)")
viewController.coreDataManager = self.coreDataManager
// Set Root View Controller
window?.rootViewController = viewController
} else {
print("WE COULDNT SET VIEWCONTROLLER AS THE DESIGNATED VC SO MOC WASNT PASSED")
}
This is your problem:
as? ViewController
should be
as! UIViewController
alternatively this should also work:
as! RoutineController
Select the RoutineController in your storyboard and set the storyboard ID
Then use the Storyboard ID here:
if let viewController = storyboard.instantiateViewController(withIdentifier: "<storyboardID>") as? RoutineController {
The solution was that you need to define an identifier in the if let viewController to find it successfully, the working code is as follows:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let viewController = storyboard.instantiateViewController(withIdentifier: "TabBarController") as? TabBarController {
viewController.coreDataManager = self.coreDataManager
window?.rootViewController = viewController

Passing value over to next viewController

I am currently writing an app in Swift and I implemented all my UI programatically. I would it kind of exhausting, so recently I decided to use storyboard but I am stuck with a bug.
When passing over the mainContext from the AppDelegate to the FirstViewController, the value of the mainContext is nil. In the first place, when I wrote everything programmatically, my code looked like this:
let vc = FirstViewController()
vc.mainContext = mainContext
window?.rootViewController = vc
But now that I am working with StoryBoard, this is not valid anymore because I have to instantiate the view with its ID, like this:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var vc = storyboard.instantiateViewControllerWithIdentifier("FirstView") as! FirstViewController
vc.mainContext = mainContext
But in this case, the context is nil. If I don't instantiate the VC like this, my outlets are nil and I get this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Does someone know a way to pass my mainContext?
You're not accessing the rootViewController, you're creating a new view controller and not doing anything with it, to access the rootViewController replace this
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var vc = storyboard.instantiateViewControllerWithIdentifier("FirstView") as! FirstViewController
vc.mainContext = mainContext
with
if let vc = self.window?.rootViewController as? FirstViewController {
vc.mainContext = mainContext
}

How would I have one view controller access a variable from another view controller?

Everything I've seen on stack is passing the data from an input, onto another view controller on a button press. Let's say I have var banana that is an array of dictionaries, but once my function in ViewA.swift is done loading up banana, I want another viewController, say ViewB.swift to manipulate that data as it sees fit. I do NOT have a segue going from one view controller to the other.
EDIT: It's actually two TableViewControllers****
I've looked into NSNotificationCenter, but that doesn't seem to work with my variable type, which is an array of dictionaries
Use NSNotificationCenter for accessing data.
Try Below code
//Sent notification
let dictionary = ["key":"value"]
NSNotificationCenter.defaultCenter().postNotificationName("passData", object: nil, userInfo: dictionary)
//Receive notification
NSNotificationCenter.defaultCenter().addObserver(self,
selector:"myMethod:", name: "passData", object: nil)
//Receive notification method
func myMethod(notification: NSNotification){
print("data: \(notification.userInfo!["key"])")
Without using segue, you can instantiate the View controller, and set the public parameteres.
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("someViewController") as! ViewB
/* Here you have the reference to the view, so you can set the parameters*/
vc.parameterInViewB = banana
/* At this point you can present the view to the user.*/
self.presentViewController(vc, animated: true, completion: nil)
Make sure that you have given all ViewControllers an identifier, then instantiate them with:
guard let viewControllerB = storyboard?.instantiateViewControllerWithIdentifier("ViewControllerB") as? ViewControllerB else {
fatalError(); return
}
// then access the variable/property of ViewControllerB
viewControllerB.banana = whatEver
Added for clarification
This one works for me.
Just make sure that you have given the TableViewController an identifier otherwise you will not be able to instantiate it. Also make sure that you cast the result of instantiateViewControllerWithIdentifier to your TableViewController class otherwise you won't be able to access it's variables (I've seen that you were struggling with this; if you get an error that UIViewController doesn't have a member "myArray" then you probably have forgotten to cast the result)
class TableViewController: UITableViewController {
var myArray = [String]()
}
class ViewController: UIViewController {
func someEventWillTriggerThisFunction() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let tableViewController = storyboard.instantiateViewControllerWithIdentifier("TableViewController") as? TableViewController else {
fatalError(); return
}
tableViewController.myArray = ["Value1", "Value2", "Value3"]
/* if you want to present the ViewController use this: */
self.presentViewController(tableViewController, animated: true, completion: nil)
}
}

Resources