How to check if segues are linked properly in code and storyboard? Exclamation point in "as!" is also not highlighted? - ios

I am creating a simple quiz app in xcode that has an intro, question, and results view controller. When I try to link my "QuestionViewController" to my "ResultsViewController" with the prepare for segue method in code, the exclamation point in "as!" keyword is not highlighted in pink.. It gives me a "Thread 1: signal SIGABRT". Yes I have linked it in the storyboard previously.
I've tried checking the identifiers of the segues in the storyboard and they look fine. Here is the code I was talking about:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ResultsSegue" {
let resultsViewController = segue.destination as! ResultsViewController
resultsViewController.responses = answersChosen
}
}
It is supposed to pass the data of answersChosen to my resultsViewController, but I am getting a "Thread 1: signal SIGABRT" error. And like I said, the "!" after "as" is not highlighted in pink like "as" is. In the iBook the "!" is pink.. that indicated to me something is not connected right.
Also in the console:
Could not cast value of type 'UINavigationController'
(0x112186760) to 'CityQuiz.ResultsViewController' (0x10a61e698)
2019-07-01 14:45:35.043824-0400 CityQuiz[29761:429223] Could not
cast value of type 'UINavigationController' (0x112186760) to
'CityQuiz.ResultsViewController' (0x10a61e698)
Isn't it supposed to say cast value of type "QuestionsViewController" instead of "UINavigationController" as well? How else do I check if things are linked properly besides actually clicking on the segues in the storyboard?
Edit #1: Turns out I had an extra navigation controller, that I somehow didn’t notice. I’m new to this, thanks for the responses. I am now getting some “NSUncaughtKeyException” but I found some other posts about those errors.

why don't you present view controller programmatically ? It's much more simple than this method. I assume the problem you have in your case is that the segue "ResultsSegue" is attached to the embedded navigation controller. And you probably should not force unwrapped view controller like that. To check optional is a better way to handle presentation like below.
if let resultsViewController = segue.destination as? ResultsViewController {
resultsViewController.responses = answersChosen }

Related

xcode sigabrt error when using array

I'm trying to get an array working on xcode 9.4.1 between viewcontrollers but keep getting a sigabrt error within part of the first few lines. When playing the simulation the segues that use the array information work, but the segues that don't rely on the array information or are linked to it in any way end up resulting in a SIGABRT error within the array's code. Anyone know what's going wrong?
This is the code;
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let VC = segue.destination as! ViewController_array
if segue.identifier == "grade1"{
VC.gradeLabel = "Grade 1"
VC.display = "information goes here1"
}
if segue.identifier == "grade2"{
VC.gradeLabel = "Grade 2"
VC.display = "information goes here2"
}
}
(and the last few lines continue on as such for each grade)
The error with the code is somewhere within the first line - the receiver on the other viewcontroller is perfectly fine and no other viewcontrollers relate to the same code, it's just something within this first one here.
The sender viewcontroller is named 'ViewController' and the receiver is 'ViewController_array'
The error message it's resulting in is;
objc[11314]: Class VCWeakObjectHolder is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/AVConference.framework/Frameworks/ViceroyTrace.framework/ViceroyTrace (0x12d8504d0) and /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/AVConference.framework/AVConference (0x12c97ce38). One of the two will be used. Which one is undefined.
Could not cast value of type 'UIViewController' (0x10fee11f0) to 'test2.ViewController_array' (0x10d40a710).
2018-08-18 21:06:07.764832+1000 test2[11314:111648] Could not cast value of type 'UIViewController' (0x10fee11f0) to 'test2.ViewController_array' (0x10d40a710).
(lldb)
You need to assign class name
ViewController_array
to the VC inside IB
Have a look at the error message:
Could not cast value of type 'UIViewController' (0x10fee11f0) to 'test2.ViewController_array'
That means that the view controller, that you are trying to segue to, is an instance of the class UIViewController and not ViewController_array. Forced casting UIViewController to ViewController_array will always fail since it is ViewController_array who is the subclass of UIViewController, not the other way around.
You have to make sure that you are setting the right view controller class in the identity inspector in the storyboard:

I am trying to pass data from one View Controller to another in Swift via 'prepare for segue' but it crashes

Good evening,
I am trying to pass data from one View Controller to another, but it crashes my program in the final View Controller. Can anyone help me?
This is the ViewController:
func updateAfterPlayAgain(){
labelSay.text = ">Result<"
scoreLabel.text = "Score: 0"
score = 0
seconds = 10
mainButton.isEnabled = true
userResult.isUserInteractionEnabled = true
}
This is the PopUpViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var fate: ViewController = segue.destination as! ViewController
fate.updateAfterPlayAgain()
}
It is from this one that I am trying to access the data from ViewController when it(PopUpViewController) closes. I would like to update the information in the ViewController when I close the PopUpViewController.
Thank you.
When prepareForSegue is called the destination view controllers' views haven't been loaded, so all of it's outlets will be nil.
Outlets are set up as implicitly unwrapped optionals, and that causes a crash if you try to reference an outlet that's nil. That's why you're crashing.
You should not call updateAfterPlayAgain() from prepareForSegue, since it tries to reference your outlets before they are connected. Instead call updateAfterPlayAgain() from viewWillAppear (or better yet from viewDidLoad, since that only gets called once when a view controller's views are first loaded.)
#Banjo, your question is not completely clear. Please add the crash it self so we will have more information ti help you.
From what I see, when you create a screen, the #IBOutlet labels, are still nil until the screen performs the "viewDidLoad" method, therefore, instead of updating the screen in the prepare(for segue), I'd set a flag using a boolean, i.e.: "requiresUpdate: Bool", and set it here, then in the viewDidAppear, check the flag and call updateAferPlayAgain.
If you are talking about dismissing a controller and updating the main controller instead, you should read about how to use "unwind segues" and handling their events, this way the parent controller gets the event of the displayed controller closing.
This article should help you with that:
https://spin.atomicobject.com/2014/10/25/ios-unwind-segues/
Good luck.

I do not understand what this code does(the code is about segues)

I am watching an iOS course video and the person in the course types up this code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let nextVC = segue.destination as! CreateTasksViewController
nextVC.tasksVC = self
}
The CreateTasksViewController is the view in the project that we are supposed to segue to. Also the "tasksVC" is the current view controller that in the app we are supposed to be on.I do not understand what this code mean and it would be helpful if someone could explain exactly what the function of the code is. Also what is "as!"?If you need any more details regarding my problem, feel free to ask in the comments.
That's not the best segue code. Here's how I'd code it (for the record, there are several ways to code this):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "[segue name here]" {
if let nextVC = segue.destination as? CreateTasksViewController {
nextVC.tasksVC = self
}
}
}
The code you posted has what is called a "forced unwrap" of the segue destination (that's the as! you asked about). Here's a question with a pretty good answer explaining the dangers of forced unwrapping. Scroll down to the divider in the answer.
While I'm sure the code compiles (and likely runs), the problem is code maintenance.
Suppose you have several segues defined between several scenes, each with their own view controller? My code, as matter of style, gives up a bit of "Swiftiness" for "explicitness":
(1) A check is made that the segue is the correct one
(2) An if let... as? is made to safely check if the segue destination if the correct view controller
(3) If everything passes the checks, then the code is executed. In this case, it looks like it passes the entire(!) view controller into a variable called tasksVC in the CreateTasksViewController.
I'm actually cautious about item 3 - why would anyone pass one view controller into another one as a variable? Most cases in prepare(for segue:) one or more variables inside the sending VC are passed to the destination. If I may offer this to you... find another tutorial!

UIViewController call function in container view viewcontroller

Using Swift 3. This question has been around and there are quite a few examples. Unfortunately none of them have worked for me. I have a uiviewcontroller that has a container view. This container view has a segue to another view controller. Everything loads up correctly and displays correctly the first time. The problem that I am facing is that I have a button on the main uiviewcontroller which by tapping it, it will refresh the container view. This is where the problem is. The outlets in the child controller are nil.
This is how I am trying to all the function in the child controller.
let wcvc = self.storyboard!.instantiateViewController(withIdentifier: "WeatherCurrentViewController") as! WeatherCurrentViewController
wcvc.callJson()
In the child controller the label is like this
#IBOutlet var currentweather: UILabel!
But in the function that is called I get an error of unexpectedly found nil while unwrapping an Optional value when I try to do
print(currentweather)
Anyone have an idea of what I can do to call a function in a view controller that is loaded by segue in a container view and still have the outlets be valid? Please let me know if more info is needed.
Found the solution. I needed to use segues identifiers and not the storyboard. Doing this
private var currentEmbeddedViewController: WeatherCurrentViewController!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let cvc = segue.destination as? WeatherCurrentViewController, segue.identifier == "CurrentWeather" {
self.currentEmbeddedViewController = cvc
}
}
And calling the function in the controller like so
self.currentEmbeddedViewController.callJson()
Was the solution. This question offered the solution. Sorry to waste everyones time. Hopefully, this will help someone else.
The reason why you get an exception is that your currentweather label will get loaded from the storyboard only when the view of that view controller loads. This means, that when you try to call callJson() the view is not yet loaded and thus no IBOutlets are loaded yet as well, meaning they are nil.
I would suggest passing some data to theWeatherCurrentViewController and only on viewDidLoad updating the views. viewDidLoad guarantees that view and all the outlets are loaded and are not nil

thread 1 exc_bad_instruction (code=exc_i386_invop subcode=0x0) when button is clicked

when you press a button in my app you should be transferred to another viewcontroller and a label in the second viewcontroller should be set to a new text, but it only works to be transferred to the second view controller not when i add the code so that the labels text should change. then this error pops up: thread 1 exc_bad_instruction (code=exc_i386_invop subcode=0x0)
And yes both viewcontrollers has the same view controllers set to them.
if you know the answer please leave a comment on this post :)
#IBAction func done(sender: UIButton) {
let countInMeters = count * 6
metersTest.text = "apr \(countInMeters) meters"
}
From the wording of your question it seems you are trying to modify a control on a target view controller within the code of a control belonging to the original view controller.
That would never work because, when you are in the original view controller's button code. Your metersTest.text is probably a member of the original controller and is probably not connected to anything. It certainly can't be connected to the target controller which is an entirely different object.
If you need to transfer data between view controller, you could intercept the transition between them at a point when you have access to both the original and the target. For example, if you override func prepareForSegue(_ segue: UIStoryboardSegue, sender sender: AnyObject?) in your original view controller, you can assign data to the target controller at that point.

Resources