How to implement functions count and dropLast in swift, IOS? - ios

I am making calculator in Swift. Stuck in backspace button. If user press wrong digit then backspace button would help to delete digit off the display.
Though I wrote dropLast function and works. It return appropriate result. How to use count method, don't understand the return type of count method.
#IBOutlet weak var display: UILabel!
#IBAction func backspace() {
//how to use count method to check collection of elements
//dropLast drop the last digit and display result
let dropedDigit = dropLast(display.text!)
display.text = dropedDigit
}

How about something like this:
private func dropLast(text: String) -> String {
let endIndex = advance(text.endIndex, -1)
return text.substringToIndex(endIndex)
}
It calculates the index where you want to make the cut (endIndex of text - 1) and then returns the substring to this index. This function should drop the last character.
I am not using count method here, but for you reference Swift 1.2 introduces count(<#x: T#>) method that calculates length of sets including Strings.

I know this thread is outdated, but I just went through the process of making this work, myself, in Swift 2.2, and figured I could help answer it.
#IBAction func delButton(sender: AnyObject) {
if display.text != nil {
var tempString = Array(display.text!.characters)
tempString.removeLast(1)
display.text = ""
for num in 0..<tempString.count {
display.text = display.text! + String(tempString[num])
}
}
}
Basically, we're checking to see that the display label has stuff in it, so we don't throw an error, and if so, making a variable in the scope of the function to hold the label's characters individually in a string. After that, we remove the last character from the array, clear out the label to ensure we aren't adding what's already there to our new values, then iterating through the updated array of characters and adding it to the label.
It's important to note that we are casting the values contained in the array as String, because they've been put into the array as character values, which operate differently than the string value the label is expecting.
Like I said, I know the thread is a little out of date, but I've been going through courses in Swift, and have discovered that while there is a plethora of information out there for Objective-C, there is perilously little information out there for how to do a lot of those things in Swift. Since the language is being updated repeatedly, I've noticed a growing divide between the two languages.

Related

Checking if first 3 characters of UI TextField are numeric in Swift

I want to check if the first three characters entered in the UI Textfield are numbers. I could do this easily in Python, but for some reason in Swift it's a pain.
Here's my python if statements (which I want to 'translate' into swift as it works):
str = "123abc"
if str.isdigit():
if str[:3]:
print(str)
and here's my swift code
#IBOutlet weak var input: UITextField!
#IBAction func checkBarcodeRegion(_ sender: UIButton)
{
let text: String = input.text!
if text.prefix(3)
{
//if numeric
//do something
}
}
Can't get this to work. Any help appreciated.
Three alternatives:
Create an Int from the substring and check if for non-nil.
let isNumeric1 = Int(text.prefix(3)) != nil
Remove all digits from the substring with Regular Expression and check for empty string
let isNumeric2 = text.prefix(3).replacingOccurrences(of: "[0-9]", with: "", options: .regularExpression).isEmpty
Split the substring by the decimalDigits character set and check if the number of components is 4
let isNumeric3 = text.prefix(3).components(separatedBy: .decimalDigits).count == 4
Using prefix is the right direction to go. You can use allSatisfy after that to check if they are all digits. One of the ways to check for digits is to check if the unicode scalar is in the CharacterSet.decimalDigits set.
text.unicodeScalars.prefix(3)
.allSatisfy(CharacterSet.decimalDigits.contains)
This will check for all the digits in Unicode, including the ones that the Indians and Arabic use.
If by digits you mean the ASCII 0123456789, then you could use:
text.prefix(3).allSatisfy(("0"..."9").contains)

Swift - iterating through characters in string causes memory leak

this is my very first post! I'm relatively new to Swift, and don't have a computer science background, so I'm still prone to a lot of newbie problems - but I've been able to solve them all so far, partly from browsing the excellent answers on StackOverflow. However, I've come across something that's really stumped me, and I've spend a whole week trying to solve it with no luck.
What I'm trying to do is take text in Chinese from a UITextView and then convert this to an array of individual Chinese characters, which is then used for various processing and analysis. However, this causes a leak.
In this greatly simplified example, which reproduces the same leak, there is a TextView and a Button; when the user presses the button, the function makeArray is called, which converts the text to an array of characters (actually Strings of single characters, because I need it to be strings for some of the stuff I will do with it). The class TextProcessing that contains this function is used as a singleton (yeah, I know that apparently singletons are supposed to be bad, for reasons I don't fully understand, but for various reasons involving other parts of the code it works best when there is a single instance of this class), and the text from the UITextView is passed into it, where it's then converted to the array, as you can see below:
class ViewController: UIViewController {
#IBOutlet weak var textBox: UITextView!
#IBOutlet weak var doneButton: UIButton!
#IBAction func pressDoneButton(_ sender: Any) {
let textToAnalyze = textBox.text!
TextProcessing.textProcessing.makeArray(textToAnalyze)
}
}
class TextProcessing {
static let textProcessing = TextProcessing()
private let language = "Chinese"
private var sourceTextArray: [String]!
func makeArray (_ sourceText: String) {
if language == "Chinese" {
sourceTextArray = sourceText.characters.map { String($0) }
} else if language == "English" {
sourceTextArray = sourceText.components(separatedBy: " ")
}
// then do some stuff with this array
}
}
When I run this on the Leaks Instruments I get leaks of "Malloc 16 Bytes" and "CFString", with the number of instances of each being roughly the same as the number of array elements (thus the number of characters in the string). When I look at the Call Tree and drill down, the problem line is "sourceTextArray = sourceText.characters.map { String($0) }".
By the way, this happens with relatively long texts - with short ones, either there's no problem or Instruments doesn't detect it.
However, if I make an array by separating the string into words according to spaces, like I would want in a language like English, there's no leak - so if I change the language variable to "English" in the example code, it works fine (but of course doesn't give me the array that I want). I thought that maybe the problem was in the "map" method, since it uses a closure and it's easy to have leaks with closures, but when I try other ways of putting it into an array of characters, such as using a for loop and iterating over each character that way, it still has the same problem.
If, instead of getting the text from the UITextView, I do this instead:
class ViewController: UIViewController {
#IBOutlet weak var textBox: UITextView!
#IBOutlet weak var doneButton: UIButton!
#IBAction func pressDoneButton(_ sender: Any) {
let textToAnalyze = "blah blah put a long string of Chinese text here"
TextProcessing.textProcessing.makeArray(textToAnalyze)
}
}
there's no problem. Likewise, if in the makeArray function, if I ignore sourceText and instead do this:
func makeArray (_ sourceText: String) {
if language == "Chinese" {
let anotherText = "blah blah some text here"
sourceTextArray = anotherText.characters.map { String($0) }
}
// then do some stuff with this array
}
there's also no leak. So, something about the combination of getting the string from the text box, passing it into the function, and then putting it into an array of characters is causing the leak.
I've spent countless hours scouring the internet and reading everything about ARC in Swift, and I've tried all sorts of stuff with weak/unowned etc. and nothing seems to work. What's going on here and how could this be solved?
Edit:
So it appears that this might just be a problem with Simulator and/or Instruments. When I run it on the device, and just monitor memory usage in xcode debug, there's no increase even when doing it 100+ times, so I guess it's OK...it still seems weird that it would show a leak in Instruments though.
It's instruments bug(there is a lot of issues). Your code is OK.
I just filed a bug report (FB7684067).
The following simple macOS command line application will grow to over 1GB in only a few minutes:
import Foundation
let line = "124;5678;90123"
while true {
let fields = line.components(separatedBy: ";")
assert(fields[1] == "5678")
}

Trouble appending values to stack in swift

I've been trying to get this code to work but of no use!
So the interface has a few buttons with numerical numbers in them (like a calculator). The task is to get the numerical values (in string) by using currentTitle method, converting into double and appendig to a stack (operandStack).
I was able to get one value onto stack but after that, the button the does it greys out and I can't do anything more with it.
#IBAction func addOntoStack() {
operandStack.append(dispValueInDouble)
print("operandStack = \(operandStack)")
}
var dispValueInDouble:Double{
doubleLabel = NSNumberFormatter().numberFromString(label.text!)!.doubleValue
print("label: \(doubleLabel)")
return doubleLabel
}

SWIFT: var someVariable:int = textfield.text.toInt() x textfield2.text.toInt() and force unwrap

First post here so please be gentle. Am fairly new to coding and am trying to get my head around SWIFT and its optionals. Would really appreciate some advice from the pros!
I am writing a simple app whereby textfields are entered by the user and then some multiplication occurs in app before spitting out an answer into another textfield on the press of a button: "calculateTM".
I am having some trouble with the calculation itself and perhaps it's because I am trying to do too much on one line - take the textfield entry, convert to integer, multiply with another textfield entry converted to an integer, essentially what I wrote in the title:
var someVariable: Int = textfield.text.toInt() * textfield2.text.toInt()
The problem is, Xcode is wanting my to force unwrap and add an ! to the end of both toInt(). This is fine, except of course when the user doesn't enter anything into the boxes and presses calculate, at which point the nil value causes the program to crash, e.g.:
var someVariable: Int = textfield.text.toInt() x textfield2.text.toInt()
var someVariable2: Int = textfield3.text.toInt() x textfield4.text.toInt()
where the user doesn't enter anything into textfield3 or 4
Following this simple arithmetic, the code updates the labels (which are textfields) as such:
label1.text = String(someVariable)
label2.text = String(someVariable2)
So this final conversion back to a string might also create some issues as to how the optionals are treated in the first part of the code.
Apologies for the long-winded explanation, and I hope I've been clear enough, but I imagine I am missing something really basic with the first part of the code. I have tried using the optional ? and also the nil-coalescing operator (to set to 0 in case of nil) but can't get it to work. Please help?
Many thanks in advance!
Use if let for optional binding:
if let var1 = textField.text?.toInt(),
let var2 = textField2.text?.toInt() {
someVariable = var1 * var2 // or directly label1.text = String(var1 * var2)
}
The method toInt() actually returns an optional type 'Int?' that can be nil or integer value, so you need to check if the String->Int cast successful returns an Int or a nil.
For the most basic way:
var intValue: Int? = text.toInt()
if intValue != nil {
// operations using intValue!
}
In swift, you can try:
if let intValue = text.toInt() {
// operations
}

Swift Converting Character to String

I have an issue with converting character type to String type. First of all, I have below extension of String for finding nth character within String.
extension String {
func characterAtIndex(index: Int) -> Character? {
var cur = 0
for char in self {
if cur == index {
return char
}
cur++
}
return nil
}
}
I get what I want with this class extension. However when I use that nth character for title of my custom UIButton, gives an error. My Uibutton Class is
class hareketliHarfler: UIButton {
init(frame: CGRect) {
super.init(frame: frame)
// Initialization code
}
func getLetter(letter:String!){
self.titleLabel.text = letter
}
}
The error show when i try to access "getLetter(letter:String)" function. Here is example of main view Controller codes:
var harfim = hareketliHarfler(frame: CGRectMake(100,100,100,100))
var str="This is my String"
var bufi=str.characterAtIndex(3)
harfim.getLetter(bufi as AnyObject) ****
In * section I try .getLetter(bufi), .getLetter(bufi as String) also I try to change parameter type of function. Look like: func getLetter(letter:Character!) or func getLetter(letter:AnyObject!)...etc
Didn't find a way. Need a help on that. Thank you
How about the simple
String(theCharacter)
Works in Swift 4 and Swift 5
Your problem is quite simple: your characterAtIndex function returns a Character, and self.titleLabel.text is a String. You can't convert between the two implicitly. The easiest way would be to turn the Character into a String using the String initialiser:
// ch will be Character? type.
if let ch = str.characterAtIndex(3) {
// Initialise a new String containing the single character 'ch'
harfim.getLetter(String(ch))
} else {
// str didn't have a third character.
}
Unlike other solutions, this is safe for unusual Unicode characters, and won't initialise a potentially large array or iterate the whole String just to get the third character.
Change this:
var bufi=str.characterAtIndex(3)
harfim.getLetter(bufi as AnyObject)
to this:
harfim.getLetter(String(Array(str)[3]))
So what happening here:
we create an array from our string. Array elements are symbols from original string. Such break down correctly tracks symbols that are presented with a sequences of two or more code points. E.g. emoji or flag as noted by #MartinR.
We access element at 4-th position.
Note that as we crate an array from initial string then performance wise is better to use this method only with short strings and avoid it in oft-repeated routines. But in your case it seems to be OK.
Can also use Character(text).isNumber if you want to get localised numbers.
Reference:
https://developer.apple.com/documentation/swift/character/3127015-isnumber

Resources