I am trying to added elements to an empty string array and I tried to follow this post add-value-to empty-array but none the options are helping me as they result in Xcode throwing errors each time.
here is the code if have tired:
var tasks = [String]()
tasks += ["something"]
This gave me 6 errors on x code with the first being Consecutive declaration on a line must be separated by ; then it says it's an invalid redeclaration of tasks followed by a bunch of errors saying to make it a func. When I try the .append func instead of += it gives the same errors
Now if I try this:
var tasks = [String]()
var tasks = ["Something"]
it only gives me the invalid redeclaration error but I do not believe this the correct way to add elements to the array
Hopefully, this helps explain my issue and sorry for the weird beginner question but thank for the help in advance
I looked at the code in your pastebin and the issue is that you had both the declaration and assignment on separate lines in the class definition.
class TableViewController: UITableViewController {
//temp list of tasks
var tasks = [Sting]()
//giving some default values in the cell
tasks.append(["something"])
You also spelled String wrong, but that is not relevant for the fix.
Another issue is a type mis-match. You declare an array of String, which would be [String]. However, you are attempting to add an array of String to an another array of String, which is wrong.
tasks.append(["something"])
Instead, you should have
tasks.append("something")
This now adds an element of String to your array of Strings.
Finally, you can do one of two things:
Assign the array at creation
var tasks = ["something"]
or assign it inside a function, like your ViewDidLoad
You can't use += with a [String] (array of Strings) and String.
Here's an example I ran in a playground:
var array: [String] = []
array.append("A")
print(array)
It prints ["A"]. Without seeing your code it will be hard to diagnose if there is another problem.
Update after looking at your code:
var tasks = [Sting]() // Should be String
tasks.append(["something"])
You can't append in the declaration, you'll need to add the append to a function (try viewDidLoad or viewWillAppear to test). ["something"] is an array of String, not a String. You'll need to use "something" instead.
Related
I'm trying to create a survey using SwiftUI, where the survey can have an arbitrary number of questions.
I'm trying to capture what values the user inputted through state variables such as:
#State var answer: String = ""
ForEach(survey) { surveyQuestion in
Text(surveyQuestion.question)
TextField(surveyQuestion.placeholder, text: $answer)
}
However, since I don't know how many questions are going to be in the survey beforehand, I don't know how many of these state variables to store the answers to make. I could create the variables on the fly inside the ForEach loop but then the variables would be out of scope when I actually go to submit the survey (since the submitting would happen outside of the ForEach loop).
How do I create an arbitrary number of state variables to capture the user's answers to the survey?
EDIT: I had tried making my answers variable a dictionary, where the keys are the IDs to the questions. My code looked like:
#State var answers: [String:String] = [:]
ForEach(survey) { surveyQuestion in
Text(surveyQuestion.question)
TextField(surveyQuestion.placeholder, text: $answers[surveyQuestion.id!])
}
However, I kept getting the error:
Cannot convert value of type 'Binding<String?>' to expected argument type 'Binding<String>'
So then I tried replacing $answers[surveyQuestion.id!] with $(answers[surveyQuestion.id!]!) but then the system gets confused and responds with:
'$' is not an identifier; use backticks to escape it
I had also tried adjusting my question model so that there's a field for an answer in the same struct. My code looked like this:
TextField(surveyQuestion.placeholder, text: $surveyQuestion.answer)
I kept getting the error:
Cannot find '$surveyQuestion' in scope
Using the strategy in the edit that you added, with the Dictionary, you could provide a custom Binding, like this:
func bindingForID(id: String) -> Binding<String> {
.init {
answers[id] ?? ""
} set: { newValue in
answers[id] = newValue
}
}
And you could use it like this:
TextField(surveyQuestion.placeholder, text: bindingForID(id: surveyQuestion.id))
In terms of adding this data to Firestore, you could trigger Firestore updates in the set closure from the custom binding. However, I'd probably recommend moving this logic to a #Published property on a view model (ObservableObject) where you could use Combine to do things like Debouncing before you send the data to Firestore (probably a little beyond the scope of this question).
Create a struct that holds id, question, and answer. Your #State var should be an array of those.
struct QA: Identifiable {
id: String
question: String
answer: String
}
…
#State private var myQAs: [QA] = myQAs() // or populate them in init, onAppear(if asynchronous) or however you see fit
…
ForEach(myQAs) { qa in
Text(qa.question)
TextField(placeholder, text: $qa.answer)
}
Xcode won't compile the creation of the dictionary, must i update anything or is there something that i am missing?
import Foundation
import UIKit
var dictionary: [String:Int]()
You have combined a type declaration (the colon) and a call to initializer (the empty parentheses after the type).
If you would like to keep the explicit type, you could do it like this:
var dictionary: [String:Int] = [String:Int]()
However, specifying the type is not necessary, because Swift figures out the type for you. This declaration is identical, but takes less space:
var dictionary = [String:Int]()
I know it gives me an 'explanation,' but I still don't really understand it.
I'm trying to print the contents of my UITextField each time it's updated.
Here's my code:
#IBAction func textUpdated(sender: UITextField) {
println("textFieldtext = %#", sender.text);
}
I get an error: Cannot invoke 'println' with an argument list of type '(StringLiteralConvertible, #Ivalue String!)'
What does that mean? What can I do to print this?
Try using this instead:
println("textFieldText = \(sender.text)")
This is called String Interopelation and it allows you to build a new string from various different types. The way you are doing it doesn't work because println only takes one argument.
EDIT: Added an explanation based on the info from the comments.
according to this page it is possible to add an entire dictionary to another
http://code.tutsplus.com/tutorials/an-introduction-to-swift-part-1--cms-21389
but running the code gave me compilation error
var dictionary = ["cat": 2,"dog":4,"snake":8]; // mutable dictionary
dictionary["lion"] = 7; // add element to dictionary
dictionary += ["bear":1,"mouse":6]; // add dictionary to dictionary
error :
[string: Int] is not identical to UInt8
is there a right way to do this functionality in swift ?
of i should add them 1 by 1 ?
The page you are referring to is wrong, += is not a valid operator for a dictionary, although it is for arrays. If you'd like to see all the defined += operators, you can write import Swift at the top of your playground and command+click on Swift, then search for +=. This will take you to the file where all of the major Swift types and functions are defined.
The page you linked to also includes some other erroneous information on quick glance in the array section where it says you can do this: array += "four". So, don't trust this page too much. I believe you used to be able to append elements like this to an array in earlier versions of Swift, but it was changed.
The good news is that with Swift you can define your own custom operators! The following is quick implementation that should do what you want.
func +=<U,T>(inout lhs: [U:T], rhs: [U:T]) {
for (key, value) in rhs {
lhs[key] = value
}
}
Almost invariably when swift complains something is not like UInt8, there's a casting error in your code that may not be obvious, especially in a complex expression.
The problem in this case is that the + and += operators are not defined for that data type. A very nifty way to join arrays is described here:
How do you add a Dictionary of items into another Dictionary
I have a basic question about swift function calling syntax. I have read documentation but not able to figure it out. So decided to put a query over here.
A piece of code i wrote
var string1 = NSString().stringByAppendingString("First string")
var string2 = NSString.stringByAppendingString("Second string")
println(string1)
println(string2)
Both string have same function calling but return type is different. And only difference here is (). I got out put like
First string
(Function)
Question is why its not giving a warning/error. Is it that var string2 holds method body of stringByAppendingString? Whats going on, New swift developer like me can easily make a this type of typo mistake and not able to figure out.
Can you please explain why its not return value?
This happens because swift methods are curried functions (you can find detailed explanation in Ole Begemann's post).
So what you actually got in the following line:
var string2 = NSString.stringByAppendingString("Second string")
is a function that takes a string as parameter and returns the result of
"Second string".stringByAppendingString(parameter)
You can check that by calling string2 as an ordinary function:
string2("123")
// Prints: "Second string123"