I have two strings, boughtString and profitString, which I am getting from the user (via the user). After, I am trying to multiply 100/95 and (boughtString+profitString).The way I do this is (and show)
Text("\(Int(Int(100/95)*Int(Int(boughtString)+Int(profitString))))")
But this doesn't seem to be understood properly by Swift, what am I doing wrong? I am doing this through SwiftUI
Int(string) returns an optional Int which must be unwrapped to be used. Since this is SwiftUI which doesn't like iterative code in the View builders, a good way to handle this would be to make read-only computed properties that turn boughtString and profitString into Ints.
Also, Int(100 / 95) is just going to be 1, because integer division discards the fractional part. I assume you don't just want to multiply by 1 because that will do nothing useful. Multiplying first by 100 and then dividing by 95 will give you the result I think you're looking for.
Here is an example of how this might be done:
struct ContentView: View {
#State private var boughtString = ""
#State private var profitString = ""
// Use nil-coalescing operator ?? to provide default values if
// the String is not a valid Int
var bought: Int { Int(boughtString) ?? 0 }
var profit: Int { Int(profitString) ?? 0 }
var body: some View {
VStack {
TextField("Bought", text: $boughtString)
TextField("Profit", text: $profitString)
Text("\(100 * (bought + profit) / 95)")
}
}
}
Related
I'm new in Swift and CoreData and I have a question on how to read data that was stored in CoreData (NsManagedObject) and save it to an data array which can than be used as input for a SwiftUI Line Chart.
My test data model is simple:
#NSManaged public var date: Date?
#NSManaged public var value: Double
I'm able to read the number of values by using this code:
private func fetchItem() {
withAnimation {
let fetchRequest: NSFetchRequest<Rate> = Rate.fetchRequest()
do {
let fetchedResults = try viewContext.fetch(fetchRequest)
print("#Entities: \(fetchedResults.count)")
} catch {
print(error)
}
}
}
Now I need the double values from Core Data stored in an array.
For the Line Chart demo (iLineChart) I have the following test data array:
let data = (1...100).map( {_ in Double.random(in: -1...10)} )
Question:
How can I create an array with double values from the NSManagedObject values?
Regards,
Ralf
You want to convert an array of Rate (ie [Rate]) into an Array of Double (ie Double), where it will be filled with the value of each Rate.
That's a job for map()!
It does exactly that: iterate over the initial array, for each element (here a Rate element) return what you want to extract from it (here just its property value).
Quick answer and "Swifty" one:
let data = fetchedResult.map { $0.value }
More explicit:
let data = fetchedResult.map { aRate in
return aRate.value
}
Manually done:
var data: Double = []
for aRate in fetchedResults {
data.append(aRate.value)
}
Note: The map is Swifty, in oneline, BUT no one should criticize the use of the manuel for loop. That's basic algorithm, and understanding them is a solid foundation on how to develop. So if it's still your level of knowledge, I'd recommend to use the for loop. Because if you need to change the output/result of the map, will you be able to do so? Let's say the value + an offset of 30 on the value, and all in absolute values?
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.
Consider the following code:
struct Card {
var name0: String
var name1: String
}
var cards = [Card]()
cards.append(Card(name0: "hello", name1: "world"))
// Need to perform array index access,
// every time I want to mutate a struct property :(
cards[0].name0 = "good"
cards[0].name1 = "bye"
// ...
// ...
// "good bye"
print(cards[0].name0 + " " + cards[0].name1)
Instead of having to perform multiple array index accessing every time I want to mutate a property in struct, is there a technique to avoid such repeating array index accessing operation?
// Ok. This is an invalid Swift statement.
var referenceToCardStruct = &(cards[0])
referenceToCardStruct.name0 = "good"
referenceToCardStruct.name1 = "bye"
// ...
// ...
There are a lot of good answers here, and you should not think of value types as "a limitation." The behavior of value types is very intentional and is an important feature. Generally, I'd recommend inout for this problem, like matt suggests.
But it is also certainly possible to get the syntax you're describing. You just need a computed variable (which can be a local variable).
let index = 0 // Just to show it can be externally configurable
var referenceToCardStruct: Card {
get { cards[index] }
set { cards[index] = newValue }
}
referenceToCardStruct.name0 = "good"
referenceToCardStruct.name1 = "bye"
print(cards[0].name0 + " " + cards[0].name1)
struct Card {
var name0: String
var name1: String
}
var cards = [Card]()
// every time I want to mutate a struct property :(
cards[0].name0 = "good"
cards[0].name1 = "bye"
Instead of having to perform multiple array index accessing every time I want to mutate a property in struct, is there a technique to avoid such repeating array index accessing operation?
No. When you have an array of struct, then in order to make a change to a struct within the array, you must refer to that struct by index.
If you don't want to see the repeated use of the index, you can hide it in a function using inout:
func mutate(card: inout Card) {
card.name0 = "good"
card.name1 = "bye"
}
for index in cards.indices {
mutate(card:&cards[index])
}
Some day, Swift may include for inout which will allow you to cycle through an array of struct and mutate each struct instance directly. But that day is not yet here.
In answer to the implied question whether it is worth switching to a class just to avoid this repeated use of the index, my answer would be No. There is a good reason for using structs — they are much easier to reason about than classes, and are one of Swift's best features — and I would keep using them if that reason matters to you.
struct is a value type you can't get a reference to it's object with assignment , you should go that way , use a mutating method like https://stackoverflow.com/a/52497495/5820010 or use a class instead
If you don't want to repeat the index, then create a variable from the value you want.
var cards = [Card]()
cards.append(Card(name0: "hello", name1: "world"))
var card = cards[0]
card.name0 = "good"
card.name1 = "bye"
// ...
// ...
cards[0] = card // update the array with the updated card
// "good bye"
print(card.name0 + " " + card.name1)
I think the mutating method is the way to go, as Sh_Khan points out.
In your case, I would do something like:
1> struct Card {
2. var name0: String
3. var name1: String
4. }
5.
6. var cards = [Card]()
7. cards.append(Card(name0: "hello", name1: "world"))
cards: [Card] = 1 value {
[0] = {
name0 = "hello"
name1 = "world"
}
}
8> extension Card {
9. mutating func setNames(name0: String, name1: String) {
10. self.name0 = name0
11. self.name1 = name1
12. }
13. }
14> cards[0].setNames(name0: "x", name1: "y")
15> cards
$R0: [Card] = 1 value {
[0] = {
name0 = "x"
name1 = "y"
}
}
Another approach is a wholesale update of cards[0].
Kind of makes you wish for record updating syntax (a la Haskell or Elm) or dictionary merging-type functionality. But look on the bright side. Maybe Swift's lack of making this easy is testament to the fact that it has static-typing-and-value-semantics-while-allowing-mutation and that combination of features, I think, makes the mutating func or full array element update all but required. I'm not sure Swift has a syntactic feature for updating multiple properties in one shot (without writing your own function or method).
I have a text view for the user to input an Int.
I am having an issue with saving the result into an Int variable as it default thinks its a string.
What would be the best solution to force the output as an Int? I am using a numerical only keyboard so the user cannot enter strings
code:
#IBOutlet weak var userExerciseWeight: UITextField!
var userExerciseWeightSet = Int()
if let userExerciseWeightSet = Int(self.userExerciseWeight.text!) {
}
You can simply use if let construct for this. textView always will be string. all you need to do is convert textView text to Int.
if let intText = Int(self.textView.text) {
print(intText)
}
I am having an issue with saving the result into an Int variable as it default thinks its a string.
Text view is a view, not a model. What it displays is always a string. When the string happens to represent an Int, your code is responsible for converting Int to String when setting the initial value, and then for converting String back to Int when reading the value back from the view.
if let intVal = Int(textView.text) {
... intVal from text is valid
} else {
... text does not represent an int - e.g. it's empty
}
The same approach applies to displaying and reading values of other types: your program is responsible for formatting and parsing the data into an appropriate type.
I wrote the following code in playground.
struct Product {
var randomNumber: Int?
init?(number: Int){
if number <3 {return nil}
randomNumber=number
}
}
var mug = Product(number: 5) // {{{…}}}
In the output on the right I get {{{…}}} as indicated by the comment. What do this symbols mean?
It's a shorthand notation that indicates different levels of wrapping. Xcode is just telling you what's in the variable mug The outermost curly-brackets are the wrapping around the optional. The second level of brackets wraps around your struct properties and the third level of wrapping is an optional wrapped around your randomNumber property. You can visualize it by doing this.
var mug = Product(number: 5) // {{{...}}}
var amug = mug! // {{Some 5}}
var bmug = mug!.randomNumber // {Some 5}
var cmug = mug!.randomNumber! // 5
{...} means you are getting an optional result from Product containing another optional randomNumber . You can use "if let" to safely unwrap your optionals as follow:
if let mug = Product(number: 5) {
if let mugRandomNumber = mug.randomNumber {
println(mugRandomNumber) // 5
}
}