I am trying to make an app that takes inputed string and then separates every character by space, and finally show it. For example, when I input "pizza" it should output "p i z z a". Unfortunately, the following code, which I wrote, does not work:
#IBOutlet var input: UITextField!
#IBOutlet var output: UITextField!
#IBAction func split(sender: AnyObject) {
I think the problem lies in the following for-in:
for character in input.text!.characters.indices {
input.text = String(input.text![character], terminator: "")
}
output.text = input.text
}
I am new to programming and I was trying to find the solution on the web, but I did not manage to. Could you help me?
You can create an array of your string characters and use joinWithSeparator to join it with a space:
extension String {
var spacedString: String {
return characters.map{String($0)}.joinWithSeparator(" ")
}
}
"pizza".spacedString
You make three mistakes here:
1) You are assigning new value to input.text every time in the loop, not append to the end of the result string.
2) You loop thru the input.text and at the same time, you are changing the value inside input.text which causes some problem when doing input.text![character]
3) You don't need to use String(input.text![character], terminator: ""). "\(input.text![character]) " should work well
Leo Dabus's answer should work for you but I also want to provide a lower level version:
var result = String()
for character in input.text!.characters {
result.appendContentsOf("\(character) ")
}
output.text = result.stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet())
Related
I have a TextField inside a SwiftUI body. I have bound it to a #State var through an intermediary binding which lets me get and set a computed value...
struct ExampleView: View {
#State var symbolToBeValidated: String = ""
var body: some View {
let binding = Binding<String> (get: {
return self.symbolToBeValidated
}, set: {
var newString = $0.uppercased()
self.symbolToBeValidated = newString // <- fig. 1: redundant assignment I wish I didn't have to put
newString = newString.replacingOccurrences(
of: #"[^A-Z]"#,
with: "",
options: .regularExpression
)
self.symbolToBeValidated = newString // <- fig. 2: the final, truly valid assignment
})
let form = Form {
Text("What symbol do you wish to analyze?")
TextField("ex.AAPL", text: binding)
// [...]
I'm using the intermediary Binding so that I can transform the string to always be an Uppercased format only containing letters A-Z (as referenced by my .regularExpression). (I'm trying to make it so that the TextField only shows a validly formatted Stock Symbol on each keypress).
This works, somewhat. The problem I discovered is that if I don't call the assignment twice (as seen in fig 1) the TextField will begin to show numbers and letters (even though it isn't included in the symbolToBeValidated string. This happens, I suspect, because SwiftUI is checking the oldValue against the newValue internally, and because it hasn't changed in the background, it doesn't call a refresh to get the internal value again. The way I've found to thwart this is to include an extra assignment before the .replacingOccurences call.
This results in the number or symbol being flashed on the screen for a blip as it is being typed by the user, then it is correctly removed by the .replacingOccurences call.
There must be a more elegant way to do this. I went down the Formatter class type and tried this alternative only because Formatter resulted in a similar behavior where the errant character would blip on the screen before being removed.
If someone knows a way for this to be intercepted before anything is displayed on the screen, I would appreciate it. This is super nit-picky, but I'm just fishing for the right answer here.
Try this:
extension Binding where Value == String {
public func validated() -> Self {
return .init(
get: { self.wrappedValue },
set: {
var newString = $0.uppercased()
newString = newString.replacingOccurrences(
of: #"[^A-Z]"#,
with: "",
options: .regularExpression
)
self.wrappedValue = newString
}
)
}
}
// ...
TextField("ex.AAPL", text: self.$symbolToBeValidated.validated())
This way also allows you to reuse and test the validation code.
Im stuck on this part of my code, I'm trying to get an average % from the numbers entered into my Textfields. I'm very new at this and would appreciate it if someone can help out and tell me where I'm going wrong and point me in the right direction.
class ingredientViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var abvTextFields: [UITextField]!
#IBOutlet var AbvTotal: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
AbvTotal.layer.cornerRadius = 8.0
}
func abvList(abvTextFields:Int...) -> Float {
let abv1 = Float(abvTextFields.reduce(0,+))
let abv2 = Float(abvTextFields.count)
let abv3 = abv1 / abv2
return abv3
}
Assuming abvTextFields is a valid outlet collection of text fields their content will be strings, therefore trying to sum them using reduce(0,+) won't work. You will need to convert them to Ints first:
let sum = abvTextFields.compactMap({Int($0.text ?? "")}).reduce(0,+)
let validNumbers = abvTextFields.compactMap({Int($0.text ?? "")}).count
let average = sum / validNumbers
The above handles the text fields being empty by nil coalescing an empty string for their content, and then tries to convert the string to an Int. If the string isn't numeric converting to an Int will return nil, so compactMap is used to drop these cases.
It would be possible to do all the conversion within a complex reduce block, but this demonstrates the steps more clearly.
EDIT Note the comment below. Just use Int($0.text!) without the nil coalescing.
I am trying to create a function within the ViewController class. I want to loop through a string and count the number of times a specific character occurs. Code looks like this:
var dcnt:Int = 0
func decimalCount(inputvalue: String) -> Int {
for chr in inputvalue.characters {
if chr == β.β {
++dcnt
}
}
return dcnt
}
The input string comes from a UILabel!
I get a warning: Immutable value βchrβ was never used.
How can I fix this problem
The problem, as so often in Swift, lies elsewhere. It's the curly quotes. Put this:
if chr == "." {
I Am trying to build a very simple app:
It will print elements of an array so here are my two questions
in my current code
#IBOutlet weak var moussarLabel: UILabel!
#IBAction func moussarButton(sender: AnyObject) {
var moussar = ["dzv","avazv","sdv dv","dvar3"]
for var i = 0; i<moussar.count; i++ {
moussarLabel.text = "\(moussar[i])"
}
}
I want to know two things:
when the code executes it automatically print the last element of the array without displaying the other elements
Say that I want the text in the array to be much much longer, how do i make UILabel to adapt to the text and to allow the user to scroll though the text?
thanks for the help
The final element in the array is the last thing the loop assigns to the text label. Sounds like its working as expected. Did you mean to concatenate (add) the strings?
You can do that with a UITextView https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextView_Class/
First of all, you can't scroll a UILabel so you'll have to use a UITextField. Read the documentation for details, it shouldn't be too hard when only displaying a single word. For getting the last element of the array, use moussarLabel.last which returns an optional. As the text property of a text view or a label, respectively, accepts nil as value, this isn't a problem.
You should make the array scoped to the class and not the function. In addition a counter variable can be used to access different elements.
To make the text scrollable you can use a UITextView:
#IBOutlet weak var moussarLabel: UITextView!
var moussar = ["dzv","avazv","sdv dv","dvar3"]
var moussarIndex = 0
#IBAction func moussarButton(sender: AnyObject) {
moussarLabel.text = "\(moussar[moussarIndex++])"
// if you want to cycle through the array use the following condition
if moussarIndex >= moussar.count {
moussarIndex = 0
}
}
This is my very first question on Stack Overflow so I hope I'm following the rules correctly.
I'm making a To-Do list app in Swift and I'm trying to prevent blank or empty spaces from being appended to the table.
My UITextField:
#IBOutlet weak var item: UITextField!
My addItem button:
#IBAction func addItem(sender: AnyObject) {
if item.text.isEmpty {
//Do not append item to array
}
Thank you for any help!
You can do this
if item.text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) != "" {
//addNew()
}
stringByTrimmingCharactersInSet : Returns a new string made by
removing from both ends of the receiver characters contained in a
given character set. The parameter NSCharacterSet.whitespaceCharacterSet removes the whitespace from both ends.
let trimmedString = item.text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
if countElements(trimmedString) > 0 {
// append the item
}
The more thorough solution might be to use the UItextFieldDelegate protocol and prevent people from typing blank spaces in the first place. Hard to do camel casing on mobile, so I apologize for typos.