I have a #StateObject Slider. It is set to slide 1...5 step 1.
I need to have custom step [1,2,5,10,20] instead of step 1.
I have a setup where I have the slider work as an array index to my array of custom step. It is working. But It is jerky. Single slide registers slide value dozen times making my array to get picked up dozen times jerking the process. How can I have custom steps smooth.
I can adjust within the app but if Slider provides the exact number, logic of the app become much cleaner. Less translation, clear the logic.
Slider(value: $tSlider, in: 1...5, step: 1)
// How can I make above like below
Slider(value: $tSlider, in: 1...5, step: [1,2,5,10,20]
// What I have currently
#Published var tSteps:[Int] = [1,2,5,10,20]
#Published var tSlider: Double = 1
var tScale: Int { return tlSteps[Int(tlSlider)-1] }
Setting steps on Slider was a bad idea. Stepper was correct choice.
Stepper("Year Scale", onIncrement: {
switch tVM.tlScale {
case 1: self.tlScale = 2
case 2: self.tlScale = 5
case 5: self.tlScale = 10
case 10: self.tlScale = 20
default: self.tlScale = 20
},
onDecrement: {
switch tVM.tlScale {
case 20: self.tlScale = 10
case 10: self.tlScale = 5
case 5: self.tlScale = 2
case 2: self.tlScale = 1
default: self.tlScale = 1
}
})
referred to : post here and Skipjakk's answer. Strange Behavior of Stepper in SwiftUI
Related
I keep getting an error when I try to call my function on the button press. I am fairly new to swift so there might be an obvious mistake. The code here is what i have that should involve the error. I have searched for other answers to this but could not find anything. I dont know what i need to do to call a mutable function.
import SwiftUI
struct ContentView2: View {
#State public var weightLifted:Int
#State public var repsPerformed:Int
#State private var percentOfReps:Double = 0.0
#State private var oneRepMax:Double = 0.0
var weightAtEachPercent:Array = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
mutating func calcMax() {
switch repsPerformed {
case 1: percentOfReps = 1.0
case 2: percentOfReps = 0.975
case 3: percentOfReps = 0.95
case 4: percentOfReps = 0.925
case 5: percentOfReps = 0.9
case 6: percentOfReps = 0.875
case 7: percentOfReps = 0.85
case 8: percentOfReps = 0.825
case 9: percentOfReps = 0.8
case 10: percentOfReps = 0.75
case 11: percentOfReps = 0.725
case 12: percentOfReps = 0.7125
case 13: percentOfReps = 0.7
case 14: percentOfReps = 0.685
case 15: percentOfReps = 0.675
default:
percentOfReps = 0.5
}
oneRepMax = Double(weightLifted) / percentOfReps
weightAtEachPercent[0] = oneRepMax
weightAtEachPercent[1] = oneRepMax * 0.975
weightAtEachPercent[2] = oneRepMax * 0.95
weightAtEachPercent[3] = oneRepMax * 0.9
weightAtEachPercent[4] = oneRepMax * 0.875
weightAtEachPercent[5] = oneRepMax * 0.825
weightAtEachPercent[6] = oneRepMax * 0.75
weightAtEachPercent[7] = oneRepMax * 0.7125
weightAtEachPercent[8] = oneRepMax * 0.675
}
var body: some View {
Button(action: {
//Place of error
//I tried using self.calcMax() as well but same error
//Error "Cannot use mutating member on immutable value: 'self' is immutable
calcMax()
}) {
Text("Calculate")
}
}
}
Have you tried adding #State to the array?
and remember that #State is always considered to be private, because when you use #State, you're essentially saying SwiftUI owns that view.
A better solution is to use an #Binding or an #ObservableObject/#ObservedObject instead.
A better quick read on it can be found here:
Views are immutable. They can store information in #State variables that will be copied over to new immutable instances, but the View itself can't change. So View functions can't be mutating.
Each piece of information should have a single source of truth. If this information is entirely internal to the view, and nothing outside the view needs to see it, then mark it #State. If things outside the view need it, but the view needs to be able to signal that it's changed, make it a #Binding. If it's a model that the view needs to react to, make it an #ObservedObject.
In your case, the updated values are already #State, and changing state doesn't actually change a view (it triggers the creation of a new view). So you can just remove the mutating modifier.
I have the code below written in my program, but I was wondering if someone could help me structure in a more summarized way as using 'case' or 'caseif' from other languages.
var imagePressed: UIImageView
imagePressed = self.redImage
if color == 1 {
imagePressed = self.redImage
}
if color == 2 {
imagePressed = self.orangeImage
}
if color == 3 {
imagePressed = self.yellowImage
}
if color == 4 {
imagePressed = self.greenImage
}
imagePressed.alpha = 0.5
I would suggest to use Dictionary to avoid much code:
let images = [1 : redImage, 2 : orangeImage, 3: yellowImage, 4: greenImage]
if let image = images[color] {
imagePressed = image
}
Also consider replacing hardcoded numbers with a enum for color e.g.:
enum Color {
case red
case orange
...
}
Swift also provides the switch statement.
You could simply type
var imagePressed: UIImageView
switch color {
case 1: imagePressed = self.redImage
case 2: imagePressed = self.orangeImage
case 3: imagePressed = self.yellowImage
case 4: imagePressed = self.greenImage
default: // provide any default value
}
Note that Swift switch statement has no implicit fallthrough. That mean, if any case is matching, the code flow breaks there.
Use comma-separated conditions to match multiple cases.
I recommend to read the switch statement in their language guide:
https://docs.swift.org/swift-book/LanguageGuide/ControlFlow.html#ID129
Your syntax is quite inefficient anyway because the code checks always all conditions even if color is 1.
A better form is if - else if
var imagePressed : UIImageView
imagePressed = self.redImage
if color == 1 {
imagePressed = self.redImage
} else if color == 2 {
imagePressed = self.orangeImage
} else if color == 3 {
imagePressed = self.yellowImage
} else if color == 4 {
imagePressed = self.greenImage
}
imagePressed.alpha = 0.5
In this particular case I recommend to use a switch statement and drop the extra variable
switch color {
case 1: self.redImage.alpha = 0.5
case 2: self.orangeImage.alpha = 0.5
case 3: self.yellowImage.alpha = 0.5
case 4: self.greenImage.alpha = 0.5
default: break
}
I'm working with a swift playground for a project at Treehouse. I'm having trouble with adding an additional key:value pair to a dictionary inside of a for loop. Here is the code that I have:
var counter = 0
for (var player) in experiencedPlayers {
counter += 1
if counter % 3 == 0 {
for team in 1...3 {
switch team {
case 1:
teamSharks.append(player)
player["Team"] = "Sharks"
case 2:
teamDragons.append(player)
player["Team"] = "Dragons"
case 3:
teamRaptors.append(player)
player["Team"] = "Raptors"
default: break
}
}
}
}
This method does not error out, but it should be adding "Team": "Sharks", etc. to the player's dictionary but it is not. Any suggestions?
You need to modify player before appending player.
switch team {
case 1:
player["Team"] = "Sharks"
teamSharks.append(player)
case 2:
player["Team"] = "Dragons"
teamDragons.append(player)
case 3:
player["Team"] = "Raptors"
teamRaptors.append(player)
default: break
}
}
This is because player is a value type.
Note that will not have any effect on the data stored in experiencedPlayers, only the teamSharks, etc. arrays.
Because player is declared inside the scope in your for..in only. So as soon as you try to modify it it will work only inside this scope, it's like a copy. If you want to modify you need to reassign your player in your experiencedPlayers with your modified object
I'm rewriting a code from java to swift and need to break a multi-layered switches right way. In Java it looks like :
block0 : switch (topSwithch) {
case one: {
switch (innerSwitch) {
case insideCase: {
if (something){
break block0;
}
// etc
So, I'm breaking one switch from another. How do I do it in swift ?
This is what it'd look like in Swift. I did this in a playground with hardcoded values for the variables:
let topSwitch = 1
let innerSwitch = 4
let one = 1
let insideCase = 4
let something = true
block0 : switch (topSwitch) { //first switch labeled "block0", switching on topSwitch
case one: //topSwitch is 1, one is 1
switch (innerSwitch) { // switching on innerSwitch
case insideCase: // both are 1
if (something){ // if true
break block0; // break from "block0"
}
default: break // else
}
default: break // else
}
I am displaying different animation for each case whereas it seem they are getting add together and speeding up. I tried using stopAnimating() as well as removeAllAnimations(). None of them are working.
switch currentDrawType {
case 0:
for i in 0..<imageNames.count{
images.append(UIImage(named: imageNames[i])!)
}
self.starImage.animationImages = images
self.starImage.animationDuration = 0.5
case 1:
for a in 0..<imageA.count{
images.append(UIImage(named: imageA[a])!)
}
self.starImage.animationImages = images
self.starImage.animationDuration = 7.0
case 2:
for b in 0..<imageB.count{
images.append(UIImage(named: imageB[b])!)
}
self.starImage.animationImages = images
self.starImage.animationDuration = 0.5
default:
break
}