Well, in my app i have to set the value of another view var, but it seems that the val i assign this var is null when it passes through the segue, the
code:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!)
{
if segue.identifier == "DetailSegue"
{
let detailViewController = ((segue.destinationViewController) as RowViewController)
let indexPath = self.table!.indexPathForSelectedRow()!
detailViewController.string = name.text
}
}
and in the second view i have something like this:
var string: String?
override func viewDidLoad() {
super.viewDidLoad()
descrip.text = string
...
Before you ask, name does have a value, but the segue seems to pass it nil :/ i really hope you guys could help me out on this one!
Basic debugging for a problem like this:
Step 1:
Check if the storyboard segue has the same identifier as the one you put in your code. Remember, lower case and upper case letters do matter.
Step 2:
Use plenty of println()s. This is one of the most useful, simple debugging tools in Xcode. You can print the values of your beginning label, your string on the next view controller, etc. Before you ask questions on Stack Overflow, try to figure it out for yourself -- that will make you a better programmer, and make you not have to rely on online communities as much.
Step 3:
Test out some other, simpler tasks with your problem to see if it is really a bug in Xcode or a mistake. Example, try to assign the value you are changing on the next view controller to a static piece of text instead of a label's text.
Hope this helped, and that you've fixed your problem.
Related
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 }
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 3 years ago.
I am currently working on an app and have problems with posting events.
I collect data in a sequence of several views (7 screens) and would like to store the data finally at once (or show all the data in the final view).
These data are, for example, location info, user info, event image, comments, event category, ...
I know how to store the data in the database/storage (firebase) if I collect the data in one or two views.
But in my use case I have seven views and I could not find any elegant method.
What's the best way to do that with Xcode 10?
You can use struct as below code. Make all required variable for all screen in this struct (like string, image etc..). And you can access this from any ViewController.
struct InputDetails {
static var details: InputDetails = InputDetails()
var city: String = ""
var lat: String = ""
var long: String = ""
}
Now to add value in this
InputDetails.details.city = textfiels.text
Now to access first screen value in last screen
print(InputDetails.details.city)
And once your API call or above struct usage is over, make sure to reset all details like below.
InputDetails.details = InputDetails()
There are several ways for passing data between View Controllers. For example you could use an instance property or a segue or the delegation method.
I recommend you study this article which paints a complete picture of the different methods and how to apply them:
How To: Pass Data Between View Controllers In Swift
Edit:
Upon examining the picture in your question I figured that using a segue would be the most appropriate solution here. As it seems from the picture you enter data in one View Controller, pass that onto the second View Controller and finally you upload all the data to Firebase.
I assume that you use storyboards (if not then consult the link above for other methods.) In this example below you will pass a string from one VC to another.
Step 1:
Add a segue between two view controllers. Storyboard -> press ctrl and click on VC one and drag your mouse -> you will see a blue arrow, drag that to VC two and release -> select manual segue: show -> click on the segue and give it an identifier
Step 2:
In VC two, make a string variable:
class SecondViewController: UIViewController {
var stringToPass: String = ""
override func viewDidLoad() {
super.viewDidLoad()
print(stringToPass)
}
Step 3:
In VC one, enter the following:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? SecondViewController {
vc.stringToPass = "This is the string we pass between two VC"
}
}
Step 4:
Then whenever you want to go to the SecondViewController perform the segue like this:
performSegue(withIdentifier: "identifierYouEntered", sender: self)
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!
So here is my first view controller class:
import UIKit
class AboutUsTableViewController: UITableViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let volunteerPageVC = segue.destination as! DedicatedVolunteerViewController
// Idk why I have to use 'as!' instead of 'as'. Xcode made me do it
volunteerPageVC.person = "John Smith"
}
}
Here is my second view controller class:
import IUKit
class DedicatedVolunteerViewController: UIViewController {
var person: String?
#IBOutlet weak var HeaderTitle: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
HeaderTitle.text = "About " + person!;
}
}
On my Main Storyboard, each of the cells on the AboutUsTableView segue to the DedicatedVolunteerViewController. I want to ability to have one view controller that can be used multiple times (i.e. people's profiles).
When I click on any of the cells in the table view, I get these errors:
2016-12-26 11:44:27.075 MyApp iOS[8350:493673] Unknown class _TtC20MyApp_iOS31DedicateVolunteerViewController in Interface Builder file.
2016-12-26 11:44:29.698 MyApp iOS[8350:493673] Unknown class _TtC20MyApp_iOS31DedicateVolunteerViewController in Interface Builder file.
I'm confused since when I compile the app, it gives no error saying about "Unknown class" or an error saying I need to add/import DedicatedVolunteerViewController into AboutUsTableViewController to be able to use it. I even tried to import it, but Xcode wouldn't let me and kept giving me errors.
P.S. I've a lot of trouble considering most places online give documentation on older versions of swift or obj-c which make it hard to find out how to use new versions of code.
It sounds like the class name is wrong in your storyboard scenes. Go follow the segue(s) from your table view controller to your second view controller. Then select the scene for the destination view controller, select the view controller itself, and select the "identify inspector." Check the class of the destination view controller. From the error you're getting, it sounds like it's class is _TtC20MyApp_iOS31DedicateVolunteerViewController instead of DedicateVolunteerViewController.
Swift uses 'optionals' which essentially means a nullable object. Optionals can have a valid value or nil. It is recommended that you use the 'guard' statement to handle optionals.
So, your prepareForSegue should look like:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let volunteerPageVC = segue.destination as? DedicatedVolunteerViewController else {
//Handle the nil value, log, etc
return
}
volunteerPageVC.person = "John Smith"
}
The ! is explicitly unwrapping the optional - meaning it MUST have a value or the app will crash. You should avoid using them where possible and use the ? as I show above instead with a guard statement. In the code above, it attempts to cast the segue.destination to a DedicatedVolunteerViewController but if it can't, it will fall into the guard statement (meaning the result was nil).
There's a lot of good information about optionals on Apple's site. Check out: Swift Basics
As for your specific error, it looks like a simple mis-spelling. The error is referring to 'DedicateVolunteerViewController' (missing a 'd') and your class name is 'DedicatedVolunteerViewController'
I want to be able to read the LAST console line and store that as a variable.
I want to do this because I've got a table view that has items in my array and I want to make my app so that when you press one of the cells, it changes the label text on the next screen to the text of cell selected.
Thus far, I have only got to being able to println the cell text but I don't know how to transfer it.
I think by being able to store the println as a variable and sending it over using the prepareForSegue may work.
e.g:
import UIKit
var storedString = String()
println("hello")
[What is here..???]
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var nextViewController: SecondViewController = segue.destinationViewController as SecondViewController
nextViewController.recievedString = storedString
}
Try storing the text in the cell rather than printing it, like where you're printing it, instead set storedString equal to it, kinda like
//You were doing something like this
println(cellText)
//instead do something like this
self.storedString = cellText
then, since your prepareForSegue method looks like it should pass storedString in as recievedString correctly, in the viewDidLoad method of SecondViewController add
self.labelName.text = self.recievedString
Hopefully that should work!