Int doesn't reach 11 in UILabel - ios

I have a nihoshim UILabel that his last character is 0, and I want to update it by one everyTime the else statement is true and called, everything works fine until it get to 10 and then it suddenly equal 1,
guard var yoo = Int(nihoshim.text!.suffix(1)) else {
return
}
var alephbet = ["א","ב","ג","ד","ה","ו","ז","ח","ט","י","כ","ל","מ","נ","ס","ע","פ","צ","ק","ר","ש","ת"]
nihoshim.text! = "ניחושים: " + String(yoo)
if gameLabel.text!.count <= 3 && (sender.tag == 18 || sender.tag == 20) {
gameLabel.text = gameLabel.text! + alephbet[alpha.index(after: tag) - 1]
sender.isHidden = true
} else if sender.tag == 10 && !(gameLabel.text?.contains("יי"))!{
sender.isHidden = false
gameLabel.text = gameLabel.text! + alephbet[alpha.index(after: tag) - 1]
}
else {
yoo += 1
nihoshim.text! = "ניחושים: " + String(yoo)
sender.isHidden = true
print(yoo)
}
When I print it, even the value of yoo is changing to 0 without any reason. and when I updated it to yoo += 20 I click on it a few times and its still 20 and one more click it goes to 1.

The problem is that you are only checking the last character, you need to get the whole number at the end of your string, for example with:
let numberString = nihoshim.text!.split(separator: " ").last ?? nihoshim.text!.suffix(0)
In your code it would look like this:
let numberString = nihoshim.text!.split(separator: " ").last ?? nihoshim.text!.suffix(0)
guard var yoo = Int(numberString) else {
return
}
var alephbet = ["א","ב","ג","ד","ה","ו","ז","ח","ט","י","כ","ל","מ","נ","ס","ע","פ","צ","ק","ר","ש","ת"]
nihoshim.text! = "ניחושים: " + String(yoo)
if gameLabel.text!.count <= 3 && (sender.tag == 18 || sender.tag == 20) {
gameLabel.text = gameLabel.text! + alephbet[alpha.index(after: tag) - 1]
sender.isHidden = true
} else if sender.tag == 10 && !(gameLabel.text?.contains("יי"))!{
sender.isHidden = false
gameLabel.text = gameLabel.text! + alephbet[alpha.index(after: tag) - 1]
}
else {
yoo += 1
nihoshim.text! = "ניחושים: " + String(yoo)
sender.isHidden = true
print(yoo)
}

Related

How to make a full decimal point for a calculator on swift?

I've just started to study Xcode.
I've made all digits and math signs, but have no clue how to make a dot for calculator.
This is what I've done (deleted some repeating parts of math operations):
class ViewController: UIViewController {
var numberFromScreen: Double = 0
var firstNum: Double = 0
var operation: Int = 0
var mathSign: Bool = false
#IBOutlet weak var result: UILabel!
#IBAction func digits(_ sender: UIButton) {
if mathSign == true {
result.text = String (sender.tag)
mathSign = false
}
else {
result.text = result.text! + String (sender.tag)
}
numberFromScreen = Double (result.text!)!
}
#IBAction func buttons(_ sender: UIButton) {
if result.text != "" && sender.tag != 10 && sender.tag != 15 {
firstNum = Double (result.text!)!
if sender.tag == 11 {// divine
result.text = "/"
}
operation = sender.tag
mathSign = true
}
else if sender.tag == 15 {// calculate
if operation == 11 {
result.text = String(firstNum / numberFromScreen)
}
}
else if sender.tag == 10 {
result.text = ""
firstNum = 0
numberFromScreen = 0
operation = 0
}
}
}
In your case using the NumberFormatter would be a good option.
You can define it as follows:
private var formater: NumberFormatter {
let formater = NumberFormatter()
formater.maximumIntegerDigits = 9 // Change this value
formater.maximumFractionDigits = 9 // Change this value
formater.minimumFractionDigits = 9 // Change this value
formater.minimumIntegerDigits = 1 // Change this value
formater.maximumIntegerDigits = 9 // Change this value
formater.groupingSeparator = " "
formater.locale = Locale.current
formater.numberStyle = .decimal
return formater
}
And when you are setting the result to the label, you can go:
result.text = formater.string(from: NSDecimalNumber(value: yourValue))
If you are making a calculator I would recommend you that for bigger numbers or for numbers with many decimal places, you set the numberStyle property to .scientific.

Issue with emojis in TextView in Swift

I’m using the below code to get the cursor position when the user types something in the textView.
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
inputChar = text
inputRange = range
inputIndex = inputRange?.upperBound
self.presenter.hashtagDataArray.removeAll()
if(text == "\n") {
textView.resignFirstResponder()
toggleTableView(toggle: true)
return false
}
let str = (textView.text + text)
if str.utf16.count <= MediaPostViewController.descCharacterLimits {
return true
}
let numberOfChars = str.utf16.count
lbbbl_DescCount.text = "\(textView.text.utf16.count)/\(MediaPostViewController.descCharacterLimits)"
return (numberOfChars <= MediaPostViewController.descCharacterLimits) || (str.utf16.count < textView.text.utf16.count)
}
func textViewDidChange(_ textView: UITextView) {
var indexPosition : Int?
updateCharacterCount()
self.mainScrollView.isScrollEnabled = false
if textView.text != "" {
inputIndex = (String(textView.text.utf16) as NSString?)?.substring(with: NSRange(location: 0, length: inputRange!.location)).count
cursorPosition = inputIndex! + 1
inputText = textView.text!
textViewEndIndex = textView.text.unicodeScalars.endIndex.utf16Offset(in: textView.text)
if #available(iOS 10.2, *) {
inputText = textView.text.replaceEmoji(with: "#")
} else {
//Fallback on earlier versions
}
if inputChar == "" || inputChar == " "{
indexPosition = cursorPosition!-2
}
else {
indexPosition = cursorPosition!-1
}
guard let enteredText = inputText?.utf16.subString(from: 0, to: indexPosition!) else { return }
guard let lastdelimiterposition = enteredText.lastIndexPosition(of: "#") else { return }
hashwordstartIndex = lastdelimiterposition
checkhashinword = inputText?.utf16.subString(from: lastdelimiterposition, to: indexPosition!)
if inputChar == "" || inputChar == " "{
spaceCharactersCheck = 1
}
if spaceCharactersCheck == 1{
checkhashword = checkhashinword?.components(separatedBy: " ").filter({!$0.contains("#")}).joined(separator: " ")
checkhashedword = checkhashinword?.components(separatedBy: " ").filter({$0.contains("#")}).joined(separator: " ")
}
if let checkhashinword = checkhashinword {
if checkhashinword.utf16.count > 1 && !(checkhashinword.contains(" ")){
self.presenter.returnHashTagsData((checkhashinword.utf16.subString(from: 1, to: checkhashinword.utf16.count-1))!)
}
}
}
else {
self.toggleTableView(toggle: true)
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let rowSelected = tableView.cellForRow(at: indexPath)?.textLabel?.text
var textViewValue : String?
textViewValue = textView_Desc.text!
let startIndex = String.Index(utf16Offset: hashwordstartIndex!, in: String(textViewValue!))
let hashwordendIndex = String.Index(utf16Offset: inputIndex!, in: String(textViewValue!))
let range = startIndex...hashwordendIndex
if var strNewText = textViewValue?.components(separatedBy: "#") {
if strNewText.count > 1 {
if let textlabel = rowSelected {
strNewText[strNewText.count - 1] = textlabel
}
}
if var rowSelected = rowSelected {
if let checkhashword = checkhashword
{
if checkhashword != ""
{
rowSelected = rowSelected.appending(" ").appending(checkhashword).appending(String(checkhashedword!))
}
}
if textViewValue != ""{
if textViewEndIndex != inputIndex {
do {
if let result = textViewValue?.replaceSubrange(range, with: rowSelected)
{
print("result:\(result)")
}
else {
throw RangeException.notaValidRange
}
}
catch {
}
}
}
spaceCharactersCheck = 0
checkhashword = ""
checkhashedword = ""
}
let combinedText = strNewText.joined(separator: "#")//.appending(" ")
if combinedText.count-1 > MediaPostViewController.descCharacterLimits {
if textView_Desc.text.count-1 > MediaPostViewController.descCharacterLimits {
toggleTableView(toggle: true)
return
}
}
if textViewEndIndex != inputIndex {
textView_Desc.text = textViewValue
}
else {
textView_Desc.text = combinedText.replacingOccurrences(of: "##", with: "#")
}
lbbbl_DescCount.text = "\(textView_Desc.text.count)/\(MediaPostViewController.descCharacterLimits)"
}
toggleTableView(toggle: true)
self.hideScrollView.isHidden = false
self.view.bringSubviewToFront(hideScrollView)
}
}
Use case :
Trying to implement hashtags similar to Instagram.
Approach:
There is a textView and I’ve added a tableView beneath that. The tableView gets data from API call based on the user input in textView. For instance, if user types #a then I show the tableView and tableView is loaded with suggestions like (#abc,#abcd, etc) from API call. The user can select a row and after selection, I hide the tableView. It works perfectly fine when the user enters hashtags between a text like #abc #insta and say if the user tries to type #ba between this #abc #insta it gets perfectly inserted after user chooses a suggestion from tableView (like #abc#bat#insta)
Problem:
When I have emojis the text replaces the emoji. For eg: if the user enters emoi#a then it will get a list starting with #a (like #abc,#ab etc) and now if the user selects #abc then it populates the textView like #abc#a and emoji disappears.
I don’t see a solution to this problem in any Github repositories.
Has anyone faced a similar problem?

Error when add negative numbers in calculator

I have this code:
class MainViewController: UIViewController {
#IBOutlet weak var summaryLbl: UILabel!
var actualNumber: Double = 0
var previousNumber: Double = 0
var operationMath: Bool = false
var operation = 0
#IBAction func numberPressed(_ sender: UIButton) {
if operationMath == true {
summaryLbl.text = String(sender.tag)
actualNumber = Double(summaryLbl.text!)!
operationMath = false
} else {
if summaryLbl.text == "0" {
summaryLbl.text = ""
}
summaryLbl.text = summaryLbl.text! + String(sender.tag)
actualNumber = Double(summaryLbl.text!)!
}
}
#IBAction func buttons(_ sender: UIButton) {
if summaryLbl.text != "" && sender.tag != 10 && sender.tag != 17 {
previousNumber = Double(summaryLbl.text!)!
if sender.tag == 13 {
summaryLbl.text = "/"
} else if sender.tag == 14 {
summaryLbl.text = "x"
} else if sender.tag == 15 {
summaryLbl.text = "-"
} else if sender.tag == 16 {
summaryLbl.text = "+"
} else if sender.tag == 11 {
var number: Double = Double(summaryLbl.text!)!
number.negate()
let rounded = number.rounded()
summaryLbl.text = String(rounded).replacingOccurrences(of: ".0", with: "", options: .literal, range: nil)
}
operation = sender.tag
operationMath = true
} else if sender.tag == 17 {
var result: Double = 0
var rounded: Double = 0
if operation == 13 {
result = previousNumber / actualNumber
} else if operation == 14 {
result = previousNumber * actualNumber
} else if operation == 15 {
result = previousNumber - actualNumber
} else if operation == 16 {
result = previousNumber + actualNumber
} else if operation == 12 {
result = previousNumber.truncatingRemainder(dividingBy: actualNumber)
}
rounded = result.rounded()
if (result == rounded) {
summaryLbl.text = String(result).replacingOccurrences(of: ".0", with: "", options: .literal, range: nil)
} else {
summaryLbl.text = String(result)
}
} else if sender.tag == 10 {
summaryLbl.text = "0"
previousNumber = 0
actualNumber = 0
operation = 0
}
}
override func viewDidLoad() {
super.viewDidLoad()
summaryLbl.text = "0"
previousNumber = 0
actualNumber = 0
operation = 0
}
}
This is simple calculator.
I have a problem with calculations.
When I click the buttons, for example: 2 + 5 * -
then the application turns off with an error. When I enter such a key combination: 2 + 5 =
This calculation will be done correctly.
 
How do I add commas to numbers?
Does anyone know how to fix the above problems?
A calculator is a Finite State Machine. It can be very complex but in its simplest form it resembles this:
So if we keep things simple and take the above machine as our target, after 2 + 5, our machine expects equals(=) to calculate the result or if an operator is added (like * in our case) it will expect a digit next. giving an operator (minus in our case) will result in an error.
The complexity is limited only by your imagination. You can add support for decimal point numbers, brackets, powers etc. The more sugar you want to add the more complex the FSM will become.
I suggest starting with the simplest one. Maintain your states, the transitions allowed next and error handling in case of wrong transition.
Check this repo on github for Finite State Machine in swift: https://github.com/vishalvshekkar/SwiftFSM
And the corresponding article:
https://blog.vishalvshekkar.com/finite-state-machine-in-swift-ba0958bca34f

Make PanGesture becoming to slider

I made a PanGuesture as a slider, Here blow is the responds func:
func respondsToPenGesture(sender: UIPanGestureRecognizer) {
if (sender.state == UIGestureRecognizerState.Began) {
if noFilterEffectButton.selected == false {
startPanLocation = sender.locationInView(self.newEffectView)
persentageNumber.text = String(startNumber)
persentageNumber.hidden = false
}
} else if (sender.state == UIGestureRecognizerState.Changed) {
let stopLocation = sender.locationInView(self.newEffectView)
let abscissaChange = stopLocation.x - startPanLocation!.x
if newEffectView.hidden == false {
if abs(abscissaChange) > 0 {
if noFilterEffectButton.selected == false{
if let effectCurrent = self.currentEffect {
effectCurrent.adjustParams(CGFloat(abscissaChange/6))
}
}
}
if noFilterEffectButton.selected == false {
var printChangingNumber = startNumber + Int(abscissaChange)
if printChangingNumber > 100 {
printChangingNumber = 100
} else if printChangingNumber < 0 {
printChangingNumber = 0
}
persentageNumber.text = String(printChangingNumber)
}
}
} else if (sender.state == UIGestureRecognizerState.Ended) {
let stopLocation = sender.locationInView(self.newEffectView)
let abscissaChange = stopLocation.x - startPanLocation!.x
startNumber = startNumber + Int(abscissaChange)
if startNumber > 100 {
startNumber = 100
} else if startNumber < 0 {
startNumber = 0
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5*Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
self.persentageNumber.text = String(self.startNumber)
self.persentageNumber.hidden = true
}
}
}
percentageNumber is a label show the changes on the screen. And the adjustParams() function:
func adjustParams(value: CGFloat) {
newValue = value + newValue
self.adjust = newValue
print("AdjustNumber")
print(adjust)
}
And I override this function for exactly one effect:
override func adjustParams(value: CGFloat) {
super.adjustParams(value)
lastAutValueChange = lastAutValueChange + value/200
lastIntensityChange = lastIntensityChange + value/200
var currentAutValue = lastAutValueChange
var currentIntValue = lastIntensityChange
currentIntValue = currentIntValue < -1.0 ? -1.0 : currentIntValue
//value = value > 1.0 ? 1.0 : value
//autValue = value < -1.0 ? -1.0 : autValue
if (currentIntValue >= 0) {
currentIntValue = 1.0
} else {
currentIntValue += 1
}
if (currentAutValue <= 0) {
currentAutValue = 0
} else {
if currentAutValue > 1 {
currentAutValue = 1
}
}
print(currentIntValue)
print(currentAutValue)
self.autoTuneModule.setIntensity(Float(currentIntValue))
self.audioUnit.finalMix = Double(currentAutValue)
}
The test answer is not matchable for the exactly changes and the percentNumber shows on the screen. How could I change my functions to make them matchable for each others?
(By the way, I want to do something like the slider in Prisma, if there is something like it, please let me know about it).

changing characters.string from nil to ""

var addressTxtFldArray = addressTxtFld.text!.characters.split{$0 == " "}.map(String.init)
if addressTxtFldArray.count == 1 {
addressTxtFldArray[1] = ""
addressTxtFldArray[2] = ""
addressTxtFldArray[3] = ""
addressTxtFldArray[4] = ""
addressTxtFldArray[5] = ""
} else if addressTxtFldArray.count == 2 {
addressTxtFldArray[2] = ""
addressTxtFldArray[3] = ""
addressTxtFldArray[4] = ""
addressTxtFldArray[5] = ""
} else if addressTxtFldArray.count == 3 {
addressTxtFldArray[3] = ""
addressTxtFldArray[4] = ""
addressTxtFldArray[5] = ""
} else if addressTxtFldArray.count == 4 {
addressTxtFldArray[4] = ""
addressTxtFldArray[5] = ""
} else {
addressTxtFldArray[5] = ""
}
var cityTxtFldArray = cityTxtFld.text!.characters.split{$0 == " "}.map(String.init)
if cityTxtFldArray.count == 1 {
cityTxtFldArray[1] = ""
}
var stateTxtFldArray = stateTxtFld.text!.characters.split{$0 == " "}.map(String.init)
if stateTxtFldArray.count == 1 {
stateTxtFldArray[1] = ""
}
var addressTxtFldDestArray = addressTxtFldDest.text!.characters.split{$0 == " "}.map(String.init)
if addressTxtFldDestArray.count == 1 {
addressTxtFldDestArray[1] = ""
addressTxtFldDestArray[2] = ""
addressTxtFldDestArray[3] = ""
addressTxtFldDestArray[4] = ""
addressTxtFldDestArray[5] = ""
} else if addressTxtFldDestArray.count == 2 {
addressTxtFldDestArray[2] = ""
addressTxtFldDestArray[3] = ""
addressTxtFldDestArray[4] = ""
addressTxtFldDestArray[5] = ""
} else if addressTxtFldDestArray.count == 3 {
addressTxtFldDestArray[3] = ""
addressTxtFldDestArray[4] = ""
addressTxtFldDestArray[5] = ""
} else if addressTxtFldDestArray.count == 4 {
addressTxtFldDestArray[4] = ""
addressTxtFldDestArray[5] = ""
} else {
addressTxtFldDestArray[5] = ""
}
var cityTxtFldDestArray = cityTxtFldDest.text!.characters.split{$0 == " "}.map(String.init)
if cityTxtFldDestArray.count == 1 {
cityTxtFldDestArray[1] = ""
}
var stateTxtFldDestArray = stateTxtFldDest.text!.characters.split{$0 == " "}.map(String.init)
if stateTxtFldDestArray.count == 1 {
stateTxtFldDestArray[1] = ""
}
Hello, so as you can see I am breaking down strings into individual words on the string, and then if they are empty, change them to "" instead of nil. However, it seems like this is still returning nil. Any suggestions would be greatly appreciated.
I don't see how you're not getting "Index out of range" errors with this code.
If you simply want to make sure your addressTxtFldArray variable always has exactly 6 entries, I would suggest something like this:
var addressTxtFldArray = (addressTxtFld.text!.characters
.split{$0 == " "}.map(String.init)
+ Array(count:6, repeatedValue:"")
)[0..<6]
If you really need the text field array to be field with "" instead of nil, I suggest you create a secondary array to save you from doing all the if comparisons and setting it to "".
var arrayContainer = [String](count: 10, repeatedValue: "")
let addressTxtFldArray = text.characters.split{$0 == " "}.map(String.init)
for (index,value) in addressTxtFldArray.enumerate()
{
arrayContainer[index] = value
}
print( arrayContainer)

Resources