Handle Multiple UISlider - ios

I have 4 UISlider with minimum value 0, Maximum value 10. I have one constant value(Ex:20).
My goal is sum of 4 slider value doesn't go above that constant value.
Ex: if i drag and set to maximum value of 1st and 2nd slider(i.e 10), Now the sum of 4 slider is 20.
I don't want to allow other 2 sliders(3rd,4th) to increase. if i decrease any slider(1st or 2nd) value means then i can allow them(2,3,4) to increase sliders values.
help me to achieve this.
You can see this screen shot
You can see this screen shot

In the #IBAction sliderValueChanged, calculate the sum of all sliders. If the sum is greater the the maximum, just reset the value of the "causing" slider (e.g. the one that is currently being dragged by the user) to the maximum allowed value.
// ...
let maxSum = 20
// ...
#IBAction func sliderValueChanged(_ sender: UISlider) {
let sum = slider1.value + slider2.value + slider3.value + slider4.value // better: use outlet collection
if (sum > maxSum) {
let overflow = sum - maxSum
sender.value = sender.value - overflow
}
}

Have a central method that all the sliders call for the valueChanged event.
In that method, sum the values of all the sliders. As the sum changes, adjust the max of all the sliders so that increasing any one slider can't exceed your sum total value. (Each slider's new max would be the the difference between it's current value and max_sum_total - current_sum_total.
So if you set all the sliders to 5, your method would adjust the max for all the sliders to 5.
If Slider A was at 10, Slider B was at 5, and the others were at 0,
Slider A max would be MIN((20 - (A+B+C+D) - A), 10) //5
Slider B max would be MIN((20 - (A+B+C+D) - B), 10) //10
...and so on.

You can use the below code for rough start. i am using single method to handle all 4 UISliders. you can refactor code as you want
#IBAction func touchDrag(_ sender: UISlider) {
switch sender {
case slider1:
let f1 = (sender.value + slider2.value)
let f2 = (slider3.value + slider4.value)
if f1 + f2 > 20 {
sender.value = 20 - (slider2.value + slider3.value + slider4.value)
}
case slider2:
let f1 = (slider1.value + sender.value)
let f2 = (slider3.value + slider4.value)
if f1 + f2 > 20 {
sender.value = 20 - (slider1.value + slider3.value + slider4.value)
}
case slider3:
let f1 = (slider1.value + slider2.value)
let f2 = (sender.value + slider4.value)
if f1 + f2 > 20 {
sender.value = 20 - (slider1.value + slider2.value + slider4.value)
}
default:
let f1 = (slider1.value + slider2.value)
let f2 = (slider3.value + sender.value)
if f1 + f2 > 20 {
sender.value = 20 - (slider1.value + slider2.value + slider3.value)
}
}
}

Related

Two swift functions increasing compiling time dramatically

After going back and reading my app's build logs, there seems to be a strange issue where two (relatively) simple functions are both increasing the compiling time by one minute each (58 & 53 seconds respectively). This can be seen in my build logs below:
These functions are in my CAAgeViewController and both reference a UISlider in my storyboard. They make sure that both the max and min sliders are at most within 1 year of each other, and either function sets a label to "18-24 Years" or something to that respect. They are as follows:
#IBAction func minAgeChanged(_ sender: UISlider) {
if round(minAgeSlider.value / 1) < round(maxAgeSlider.value / 1) - 1 {
minAgeSlider.value = round(minAgeSlider.value / 1)
ageLabel.text = String(Int(round(minAgeSlider.value / 1))) + "-" + String(Int(round(maxAgeSlider.value / 1))) + " Years"
} else {
minAgeSlider.value = round(maxAgeSlider.value / 1) - 1
ageLabel.text = String(Int(round(minAgeSlider.value / 1))) + "-" + String(Int(round(maxAgeSlider.value / 1))) + " Years"
}
}
#IBAction func maxAgeChanged(_ sender: UISlider) {
if round(maxAgeSlider.value / 1) > round(minAgeSlider.value / 1) + 1 {
maxAgeSlider.value = round(maxAgeSlider.value / 1)
ageLabel.text = String(Int(round(minAgeSlider.value / 1))) + "-" + String(Int(round(maxAgeSlider.value / 1))) + " Years"
} else {
maxAgeSlider.value = round(minAgeSlider.value / 1) + 1
ageLabel.text = String(Int(round(minAgeSlider.value / 1))) + "-" + String(Int(round(maxAgeSlider.value / 1))) + " Years"
}
}
I am unsure what exactly is going wrong here. Any help is appreciated!
Your problem is the chained-plus. (It's always chained-plus; ok, not always but always…)
ageLabel.text = String(Int(round(minAgeSlider.value / 1))) + "-" + String(Int(round(maxAgeSlider.value / 1))) + " Years"
Replace this with:
ageLabel.text = "\(Int(round(minAgeSlider.value)))-\(Int(round(maxAgeSlider.value))) Years"
I'm fairly certain the /1 isn't helping you here. round + Int should do everything you meant.
The most likely cause of the slowdown is the way that you're concatenating strings with +. For some reason that I haven't been able to figure out, it's much faster (at least in Swift 2/3) to append strings with "\(string1) \(string2)" than to use string1 + string2. Same goes for arrays and their + operator. We saw a 100x decrease in compile time when we changed how we're doing concatenation.
Have you tried removing the division by 1 and casting your values to Double instead? They may already be Doubles, mind you. You may just need to call round().

swift: what does arc4andom_uniform() means

This might be a lame question and even have already answered in SO.i have even searched about this but could not understand in a proper way. what is happening here..??please help me out to understand this.
let size = Double(arc4random_uniform(5)) + 1
for index in 0..<ITEM_COUNT
{
let y = Double(arc4random_uniform(100)) + 50.0
let size = Double(arc4random_uniform(5)) + 1
entries.append(ChartEntry(x: Double(index) + 0.5, y: y, size: CGFloat(size)))
}
arc4random_uniform(x) returns a random value between 0 and x-1
Examples:
arc4random_uniform(2) -> returns 0 or 1 randomly
arc4random_uniform(2) == 0 returns true or false randomly
arc4random_uniform(6) + 1 returns a number between 1 and 6 (like a dice roll)
There are a multitude of reasons that arc4random_uniform(5) returns a number between 0 and 5, but the main one is that this is a basic functionality in programming, where numbers start at zero. An example of why this would be useful would be returning a random value from an array. Example:
func randomArrayValue(array: [Int]) -> Int {
let index = arc4random_uniform(array.count)
return array[index]
}
let arrayOfInt = [10,20,30]
print("Random Int: \(randomArrayValue(array: arrayOfInt))")
//"Random Int: 10"
//"Random Int: 20"
//"Random Int: 30"
For these three lines of code in your questions:
let y = Double(arc4random_uniform(100)) + 50.0
let size = Double(arc4random_uniform(5)) + 1
entries.append(ChartEntry(x: Double(index) + 0.5, y: y, size: CGFloat(size)))
y is a random variable between 50 and 149
size is a random variable between 1 and 5
you then add an item onto an array that goes onto a chart. The value being added specifies the x location (the index) and the y location (the random y value). Size is some code specific requirement, which we wouldn't be able to help with without seeing the functionality.

BAD INSTRUCTION arc4random_uniform

I was trying to do something about percentages but i think i did something wrong.
let randomNum = arc4random_uniform(25) + 71
let wrongNumber = 100 - Int(randomNum)
let firstWrong = wrongNumber - 10
var first = arc4random_uniform(UInt32(firstWrong))
var second = arc4random_uniform(UInt32(wrongNumber) - first)
var third = arc4random_uniform(UInt32(wrongNumber) - (first + second))
let plus = (UInt32(wrongNumber) - (first + second + third)) / 3
first = first + plus
second = second + plus
third = third + plus
let total = randomNum + first + second + third
if (total < 100) {
first += (100 - total)
}
It sometimes gives this BAD INSTRUCTION error
And it usually works fine
Your logic is completely flawed, consider the first few lines:
let randomNum = arc4random_uniform(25) + 71 // values 71 ... 95
let wrongNumber = 100 - Int(randomNum) //values 5 ... 29
let firstWrong = wrongNumber - 10 // -5 ... 19
The maximum randomNum is 95. Then wrongNumber is 5 and firstWrong is -5.
Then
var first = arc4random_uniform(UInt32(firstWrong))
has to crash when casting -5 to an unsigned number.
Similar errors can happen on other lines if the values get into negatives.

Need to restart numbering when it gets to 1 and jump to 99

How would I go about doing this? the code I have is
let myInt = Int(currentSaleLabel.text!)
let sale1Number = (myInt! - 1 + 100) % 100
let sale2Number = (sale1Number - 1 + 100) % 100
let sale3Number = (sale2Number - 1 + 100) % 100
let sale4Number = (sale3Number - 1 + 100) % 100
let sale5Number = (sale4Number - 1 + 100) % 100
let sale6Number = (sale5Number - 1 + 100) % 100
let sale7Number = (sale6Number - 1 + 100) % 100
let sale8Number = (sale7Number - 1 + 100) % 100
let sale9Number = (sale8Number - 1 + 100) % 100
let sale10Number = (sale9Number - 1 + 100) % 100
This works fine for numbers 0-99 but I need to eliminate the number 0 also.
One approach is to make a limit of 99 with modulo % operator, like this:
let sale1Number = (myInt! - 1 + 100) % 100
This decrements myInt, and wraps it to 99 when it gets negative. Adding 100 prior to applying % has no effect on numbers in range 0..99. Negative numbers above -100 will get processed correctly.
I am actually also trying to avoid the number 0
You can use a modified formula, like this:
let sale1Number = (myInt! - 2 + 100) % 100 + 1

Multiplication table in Swift ios

I am learning how to make a multiplication table in swift and used
override func viewDidLoad() {
let n = Int(str)!
while (i<=10) {
let st = "\(n) * \(i) = \(n * i)"
lbl.text = st
i += 1
}
this code. i have a label in which i want to show the table, but the problem is that only the last result which is say 2*10 = 20 is showing and not all the other value. i am confused what to do, please help what to do so that all the values are displayed.
Glad you've decided to learn Swift. You're on the right track, but as others have said, your final iteration of the loop is replacing the contents of lbl.text.
There are many ways to achieve what you want, but for problems like this I'd suggest starting off working in a playground rather than worrying about labels, viewDidLoad and suchlike.
Here's a nice Swift-y way to do what you want
let n = 12
let table = Array(0...10).map({"\(n) * \($0) = \(n * $0)"}).joinWithSeparator("\n")
print("\(table)")
Gives…
12 * 0 = 0
12 * 1 = 12
12 * 2 = 24
12 * 3 = 36
12 * 4 = 48
12 * 5 = 60
12 * 6 = 72
12 * 7 = 84
12 * 8 = 96
12 * 9 = 108
12 * 10 = 120
To break that down…
// Take numbers 0 to 10 and make an array
Array(0...10).
// use the map function to convert each member of the array to a string
// $0 represents each value in turn.
// The result is an array of strings
map({"\(n) * \($0) = \(n * $0)"}).
// Join all the members of your `String` array with a newline character
joinWithSeparator("\n")
Try it for yourself. In Xcode, File -> New -> Playground, and just paste in that code. Good luck!
That's because every time the loop iterates, it overwrites the previous value in label.text. You need to append the new value to existing string value in label, as suggested by RichardG.
let n = Int(str)!
while (i<=10) {
let st = "\(n) * \(i) = \(n * i)"
lbl.text = lbl.text + " " +st //Append new value to already existing value in label.text
i += 1
}
There is also a possibility of UI issue. You have to provide number of lines to the label or it will mess up the display. It also needs to be of size enough to hold your data. A better option would be UITextView which is scrollable, if you are unwilling to handle cases for label height and width. But if you want to stick with UILabel, the following code will resize the label depending on text for you:
lbl.numberOfLines = 0; //You only need to call this once. Maybe in `viewDidLoad` or Storyboard itself.
lbl.text = #"Some long long long text"; //here you set the text to label
[lbl sizeToFit]; //You must call this method after setting text to label
You can also handle that by Autolayout constraints.
Easy way to do it with SWIFT 2.0
var tableOf = 2 //Change the table you want
for index in 1...10 {
print("\(tableOf) X \(index) = \(index * tableOf)")
}
OUTPUT
repeat-while loop, performs a single pass through the loop block first before considering the loop's condition (exactly what do-while loop does).
1) repeat...while Loop
var i = Int()
repeat {
print("\(i) * \(i) = \(i * 11)")
i += 1
} while i <= 11
2) While Loop
var i = Int()
while i <= 11
{
print("\(i) * \(i) = \(i * 11)")
i += 1
}
3) For Loop
for n in 1..<11
{
print("\(n) * \(n) = \(n * 10)")
}

Resources