Get all the keys for a class - ios

Recently I work with the function func setValue(_ value: AnyObject?, forKey key: String) of the NSKeyValueCoding protocol to change the text color of a UIPickerDate in the following way:
class ColoredDatePicker: UIDatePicker {
var changed = false
override func addSubview(view: UIView) {
if !changed {
changed = true
self.setValue(UIColor(red: 0.42, green: 0.42, blue: 0.42, alpha: 1), forKey: "textColor")
}
super.addSubview(view)
}
}
Regarding the answer in this question. It works perfectly.
But my answer here is:
How do I know what names that the class provide like the textColor used above?.
I'm trying to find anything get all the names or in the documentation, but so far I don't find anything yet to get the keys provided by a class like in the above case.

The objective-c runtime provides this type of reflection for properties:
id UIDatePickerClass = objc_getClass("UIDatePicker");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(UIDatePickerClass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));
}
reference doc: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/c/func/class_copyPropertyList
edit - swift has basic reflection too: https://stackoverflow.com/a/24069875/1385467

For those we want a Swift solution like the #Adam, here is :
var propertiesCount : CUnsignedInt = 0
let propertiesInAClass = class_copyPropertyList(UIDatePicker.self, &propertiesCount)
var propertiesDictionary : NSMutableDictionary = NSMutableDictionary()
for var i = 0; i < Int(propertiesCount); i++ {
var property = propertiesInAClass[i]
var propName = NSString(CString: property_getName(property), encoding: NSUTF8StringEncoding)
println(propName)
}
Swift 4.1:
var propertiesCount: CUnsignedInt = 0
let propertiesInAClass = class_copyPropertyList(UIDatePicker.self, &propertiesCount)!
var propertiesDictionary: NSMutableDictionary = [:]
for i in 0..<propertiesCount {
var property = propertiesInAClass[Int(i)]
let propName = NSString(cString: property_getName(property), encoding: String.Encoding.utf8.rawValue)
print(propName)
}

Some changes to #Victor Sigler & #dwlz, to get current values for all keys:
var propertiesCount : CUnsignedInt = 0
let propertiesInClass = class_copyPropertyList(UIDatePicker.self, &propertiesCount)
print("Prperties:\(propertiesCount)")
for i in 0..<propertiesCount
{
let property = propertiesInClass![Int(i)]
let name = NSString(cString: property_getName(property), encoding: String.Encoding.utf8.rawValue)
print("\(i + 1). Key:\(name!),value \(String(describing: self.value(forKey: name! as String)))")
}

Related

How can I change a UILabel into a number programmatically? [duplicate]

I'm trying to work out how to cast an Int into a String in Swift.
I figure out a workaround, using NSNumber but I'd love to figure out how to do it all in Swift.
let x : Int = 45
let xNSNumber = x as NSNumber
let xString : String = xNSNumber.stringValue
Converting Int to String:
let x : Int = 42
var myString = String(x)
And the other way around - converting String to Int:
let myString : String = "42"
let x: Int? = myString.toInt()
if (x != nil) {
// Successfully converted String to Int
}
Or if you're using Swift 2 or 3:
let x: Int? = Int(myString)
Check the Below Answer:
let x : Int = 45
var stringValue = "\(x)"
print(stringValue)
Here are 4 methods:
var x = 34
var s = String(x)
var ss = "\(x)"
var sss = toString(x)
var ssss = x.description
I can imagine that some people will have an issue with ss. But if you were looking to build a string containing other content then why not.
In Swift 3.0:
var value: Int = 10
var string = String(describing: value)
Swift 4:
let x:Int = 45
let str:String = String(describing: x)
Developer.Apple.com > String > init(describing:)
The String(describing:) initializer is the preferred way to convert an instance of any type to a string.
Custom String Convertible
Just for completeness, you can also use:
let x = 10.description
or any other value that supports a description.
Swift 4:
Trying to show the value in label without Optional() word.
here x is a Int value using.
let str:String = String(x ?? 0)
To save yourself time and hassle in the future you can make an Int extension. Typically I create a shared code file where I put extensions, enums, and other fun stuff. Here is what the extension code looks like:
extension Int
{
func toString() -> String
{
var myString = String(self)
return myString
}
}
Then later when you want to convert an int to a string you can just do something like:
var myNumber = 0
var myNumberAsString = myNumber.toString()
in swift 3.0 this is how we can convert Int to String and String to Int
//convert Integer to String in Swift 3.0
let theIntegerValue :Int = 123 // this can be var also
let theStringValue :String = String(theIntegerValue)
//convert String to Integere in Swift 3.0
let stringValue : String = "123"
let integerValue : Int = Int(stringValue)!
for whatever reason the accepted answer did not work for me. I went with this approach:
var myInt:Int = 10
var myString:String = toString(myInt)
Multiple ways to do this :
var str1:String="\(23)"
var str2:String=String(format:"%d",234)
let intAsString = 45.description // "45"
let stringAsInt = Int("45") // 45
Swift 2:
var num1 = 4
var numString = "56"
var sum2 = String(num1) + numString
var sum3 = Int(numString)
Swift String performance
A little bit about performance
UI Testing Bundle on iPhone 7(real device) with iOS 14
let i = 0
lt result1 = String(i) //0.56s 5890kB
lt result2 = "\(i)" //0.624s 5900kB
lt result3 = i.description //0.758s 5890kB
import XCTest
class ConvertIntToStringTests: XCTestCase {
let count = 1_000_000
func measureFunction(_ block: () -> Void) {
let metrics: [XCTMetric] = [
XCTClockMetric(),
XCTMemoryMetric()
]
let measureOptions = XCTMeasureOptions.default
measureOptions.iterationCount = 5
measure(metrics: metrics, options: measureOptions) {
block()
}
}
func testIntToStringConstructor() {
var result = ""
measureFunction {
for i in 0...count {
result += String(i)
}
}
}
func testIntToStringInterpolation() {
var result = ""
measureFunction {
for i in 0...count {
result += "\(i)"
}
}
}
func testIntToStringDescription() {
var result = ""
measureFunction {
for i in 0...count {
result += i.description
}
}
}
}
iam using this simple approach
String to Int:
var a = Int()
var string1 = String("1")
a = string1.toInt()
and from Int to String:
var a = Int()
a = 1
var string1 = String()
string1= "\(a)"
Convert Unicode Int to String
For those who want to convert an Int to a Unicode string, you can do the following:
let myInteger: Int = 97
// convert Int to a valid UnicodeScalar
guard let myUnicodeScalar = UnicodeScalar(myInteger) else {
return ""
}
// convert UnicodeScalar to String
let myString = String(myUnicodeScalar)
// results
print(myString) // a
Or alternatively:
let myInteger: Int = 97
if let myUnicodeScalar = UnicodeScalar(myInteger) {
let myString = String(myUnicodeScalar)
}
I prefer using String Interpolation
let x = 45
let string = "\(x)"
Each object has some string representation. This makes things simpler. For example if you need to create some String with multiple values. You can also do any math in it or use some conditions
let text = "\(count) \(count > 1 ? "items" : "item") in the cart. Sum: $\(sum + shippingPrice)"
exampleLabel.text = String(yourInt)
To convert String into Int
var numberA = Int("10")
Print(numberA) // It will print 10
To covert Int into String
var numberA = 10
1st way)
print("numberA is \(numberA)") // It will print 10
2nd way)
var strSomeNumber = String(numberA)
or
var strSomeNumber = "\(numberA)"
let a =123456888
var str = String(a)
OR
var str = a as! String
In swift 3.0, you may change integer to string as given below
let a:String = String(stringInterpolationSegment: 15)
Another way is
let number: Int = 15
let _numberInStringFormate: String = String(number)
//or any integer number in place of 15
If you like swift extension, you can add following code
extension Int
{
var string:String {
get {
return String(self)
}
}
}
then, you can get string by the method you just added
var x = 1234
var s = x.string
let Str = "12"
let num: Int = 0
num = Int (str)

Unable to assign class objects to dictionary member of another class object in Swift 3

I have a class ChessSquare with its own attributes and methods. I have another class ChessBoard, which has an attribute of dictionary type.
class ChessBoard {
var squares: [ Int : ChessSquare ] = [:]
.....
One of the methods of the ChessBoard class builds the chessSquare object and assigns it to chessBoard object as below.
self.squares[squareName] = chessSquare
Before Swift3 this code was working fine. After upgrading to Swift3 the assignment stopped working.
Using breakpoints I see that chessSquare objects are built as expected. squareName variable has the expected value. The "self", which is the chessBoard object has proper initial values. But the dictionary assignment gets skipped without any error in the above mentioned code.
Is this anything related to Swift3. I browsed and could not get specific solution to my case.
Adding more code for clarity.
class ChessSquare {
let squareColor: UIColor
let squareShade: Int
let squareName: Int
let squareSize: CGSize
let minXY: CGPoint
let maxXY: CGPoint
let squareOrigin: CGPoint
var hasPiece = false
weak var chessPiece: ChessPiece?
let squareSprite: SKSpriteNode
let squareType: SquareType
//more data members
init(squareColor: UIColor, squareShade: Int, squareName: Int, squareSize: CGSize, minXY: CGPoint, maxXY: CGPoint, squareOrigin: CGPoint, squareSprite: SKSpriteNode, squareType: SquareType) {
self.squareColor = squareColor
self.squareShade = squareShade
self.squareName = squareName
self.squareSize = squareSize
self.minXY = minXY
self.maxXY = maxXY
self.squareOrigin = squareOrigin
self.squareSprite = squareSprite
self.squareType = squareType
}
//more methods
}
class ChessBoard {
var squares: [ Int : ChessSquare ] = [:]
var byteBoard: [UInt8] = [UInt8](repeating: UInt8(0), count: 66)
var byteBoardHashVal: Int = 0
// [ byteBoardHashVal : ((byteBoard, evalnVal), repCnt) ]
var byteBoards: [Int : (([UInt8],Double?), Int)] = [:]
var TT: [Int : Double] = [:]
var TTReuseCount = 0
var whitePawnlessFileByte: UInt8 = 255
var blackPawnlessFileByte: UInt8 = 255
var maxXY: CGPoint = CGPoint()
var minXY: CGPoint = CGPoint()
var oldTouchedSquare: ChessSquare?
init() {
squares = [:]
byteBoard = [UInt8](repeating: UInt8(0), count: 66)
byteBoardHashVal = 0
byteBoards = [:]
TT = [:]
TTReuseCount = 0
whitePawnlessFileByte = 255
blackPawnlessFileByte = 255
}
func drawFlippedChessBoard(_ view: SKView, scene: GameScene) {
....
....
for row in 0..<8 {
for col in 0..<8 {
let squareName = row * 8 + col
....
let chessSquare = ChessSquare(squareColor: currentColor, squareShade: squareShade, squareName: squareName, squareSize: squareSize, minXY: minXY, maxXY: maxXY, squareOrigin: squareOrigin, squareSprite: squareSprite, squareType: squareType)
....
self.squares[squareName] = chessSquare
....
}
....
}
....
}
//more methods
}
I have a difficulty in understanding if squareName is a string or a integer. It sounds like a string, I would suggest to name it chessSquareIndex or squareIndex if in case it is Int and you want to index chess square.
Based on your comment above I did a small test to verify that it works correctly if squareName is Int and here is the result,
class ChessSquare { }
class ChessBoard {
var squares: [ Int : ChessSquare ] = [:]
func getChessSquare(at squareIndex: Int) {
let chessSquare = ChessSquare()
return squares[squareIndex] = chessSquare
}
}
And this seems to work fine with Swift 3. Also notice that it is not required to call self, unless you are inside escaping closures.

Replace numeric of different length in a string with different text length

Problem: Numeric is of different length could be 1, 200, 1000, 39 99995 etc. And need to replace with a text eg. "Apple" which is of different lenth comapring to the numeric values.
let str: String = "hello i have 1313 object of 10 string class with 1 object, similar to 9999 errors"
Expected Result = "hello i have Apple object of Apple string class with Apple object, similar to Apple errors"
I have tried with below code:
var originalString: String = "hello i have 1313 object of 10 string class with 1 object, similar to 9999 errors"
let strippedString: NSMutableString = NSMutableString(capacity: originalString.characters.count)
var numArray: [String] = []
var locArray: [NSNumber] = []
var scanner: NSScanner = NSScanner(string:originalString)
let numbers: NSCharacterSet = NSCharacterSet(charactersInString: "0123456789")
while scanner.atEnd == false {
var buffer: NSString?
if scanner.scanCharactersFromSet(numbers, intoString: &buffer) {
strippedString.appendString(buffer! as String)
numArray.append(buffer! as String)
locArray.append(scanner.scanLocation)
}
else {
scanner.scanLocation = (scanner.scanLocation + 1)
}
}
for (index, _) in numArray.enumerate() {
var loc : Int = Int(locArray[index] ) - (String(numArray[index]).characters.count)
let len = String(numArray[index]).characters.count
let dupStr = "Apple"
if(index != 0 && len != dupStr.characters.count)
{
loc = loc + (dupStr.characters.count - len) + 1
}
originalString.replaceRange(originalString.startIndex.advancedBy(loc)..<originalString.startIndex.advancedBy(loc + len), with: dupStr)
}
print(originalString)
Swift 2
NSScanner is great, but if you want a simpler solution for this task, you could use componentsSeparatedByString, map, Int() and joinWithSeparator, like this:
let originalString = "hello i have 1313 object of 10 string class with 1 object, similar to 9999 errors"
let tokens = originalString.componentsSeparatedByString(" ")
let newTokens = tokens.map { (token) -> String in
if let _ = Int(token) {
return "Apple"
}
return token
}
let result = newTokens.joinWithSeparator(" ")
print(result)
Prints:
hello i have Apple object of Apple string class with Apple object, similar to Apple errors
There's also a short version for the mapping:
let newTokens = tokens.map { Int($0) != nil ? "Apple" : $0 }
Swift 3
componentsSeparatedByString(_:) is now components(separatedBy:), and joinWithSeparator(_:) is now joined(separator:).
let tokens = originalString.components(separatedBy: " ")
let newTokens = tokens.map { Int($0) != nil ? "Apple" : $0 }
let result = newTokens.joined(separator: " ")
var str: String = "hello i have 1313 object of 10 string class with 1 object, similar to 9999 errors"
var comp: [AnyObject] = [AnyObject](array: str.componentsSeparatedByString(" "))
for var i = 0; i < comp.count; i++ {
var numberRegex: NSRegularExpression = NSRegularExpression.regularExpressionWithPattern("^[0-9]", options: NSRegularExpressionCaseInsensitive, error: nil)
var regexMatch: Int = numberRegex.numberOfMatchesInString(comp[i], options: 0, range: NSMakeRange(0, (String(comp[i])).length))
if regexMatch != 0 {
comp[i] = "Apple"
}
}
var result: String = comp.componentsJoinedByString(" ")
print(result)

How do I send data from a GKPlayer to another in a match?

I would like to send NSData from a GKPlayer to another in a match. Therefore, the method sendDataToAllPlayers(_:withDataMode:error:) would be the most ideal.
func sendDataToAllPlayers(data: Int,
withDataMode Reliable: GKMatchSendDataMode,
error: NSErrorPointer) -> Bool {
return true
}
Though, how can I use the method above to send an Int variable?
var score:Int = 0
extension Int {
var data: NSData {
var source = self
return NSData(bytes: &source, length: sizeof(Int))
}
}
extension Double {
var data: NSData {
var source = self
return NSData(bytes: &source, length: sizeof(Double))
}
}
extension NSData {
var integerValue:Int {
var result = 0
getBytes(&result, length: sizeof(Int))
return result
}
var doubleValue:Double {
var result:Double = 0
getBytes(&result, length: sizeof(Double))
return result
}
}
let myIntegerData = 123.data // _NSInlineData
let backToInt = myIntegerData.integerValue // 123
let myDoubleData = 123.456789.data // _NSInlineData
let backToDouble = myDoubleData.doubleValue // 123.456789
This version for encapsulating an Int (or other type) into or extracting it fromNSData should work even between devices with different byte orders:
// at sender before sending data
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWithMutableData: data)
archiver.encodeInteger(score, forKey: "score")
archiver.finishEncoding()
// at receiver after receiving data
let unarchiver = NSKeyedUnarchiver(forReadingWithData: data)
let score = unarchiver.decodeIntegerForKey("score")
unarchiver.finishDecoding()

Converting String to Int with Swift

The application basically calculates acceleration by inputting Initial and final velocity and time and then use a formula to calculate acceleration. However, since the values in the text boxes are string, I am unable to convert them to integers.
#IBOutlet var txtBox1 : UITextField
#IBOutlet var txtBox2 : UITextField
#IBOutlet var txtBox3 : UITextField
#IBOutlet var lblAnswer : UILabel
#IBAction func btn1(sender : AnyObject) {
let answer1 = "The acceleration is"
var answer2 = txtBox1
var answer3 = txtBox2
var answer4 = txtBox3
Updated answer for Swift 2.0+:
toInt() method gives an error, as it was removed from String in Swift 2.x. Instead, the Int type now has an initializer that accepts a String:
let a: Int? = Int(firstTextField.text)
let b: Int? = Int(secondTextField.text)
Basic Idea, note that this only works in Swift 1.x (check out ParaSara's answer to see how it works in Swift 2.x):
// toInt returns optional that's why we used a:Int?
let a:Int? = firstText.text.toInt() // firstText is UITextField
let b:Int? = secondText.text.toInt() // secondText is UITextField
// check a and b before unwrapping using !
if a && b {
var ans = a! + b!
answerLabel.text = "Answer is \(ans)" // answerLabel ie UILabel
} else {
answerLabel.text = "Input values are not numeric"
}
Update for Swift 4
...
let a:Int? = Int(firstText.text) // firstText is UITextField
let b:Int? = Int(secondText.text) // secondText is UITextField
...
myString.toInt() - convert the string value into int .
Swift 3.x
If you have an integer hiding inside a string, you can convertby using the integer's constructor, like this:
let myInt = Int(textField.text)
As with other data types (Float and Double) you can also convert by using NSString:
let myString = "556"
let myInt = (myString as NSString).integerValue
You can use NSNumberFormatter().numberFromString(yourNumberString). It's great because it returns an an optional that you can then test with if let to determine if the conversion was successful.
eg.
var myString = "\(10)"
if let myNumber = NSNumberFormatter().numberFromString(myString) {
var myInt = myNumber.integerValue
// do what you need to do with myInt
} else {
// what ever error code you need to write
}
Swift 5
var myString = "\(10)"
if let myNumber = NumberFormatter().number(from: myString) {
var myInt = myNumber.intValue
// do what you need to do with myInt
} else {
// what ever error code you need to write
}
edit/update: Xcode 11.4 • Swift 5.2
Please check the comments through the code
IntegerField.swift file contents:
import UIKit
class IntegerField: UITextField {
// returns the textfield contents, removes non digit characters and converts the result to an integer value
var value: Int { string.digits.integer ?? 0 }
var maxValue: Int = 999_999_999
private var lastValue: Int = 0
override func willMove(toSuperview newSuperview: UIView?) {
// adds a target to the textfield to monitor when the text changes
addTarget(self, action: #selector(editingChanged), for: .editingChanged)
// sets the keyboard type to digits only
keyboardType = .numberPad
// set the text alignment to right
textAlignment = .right
// sends an editingChanged action to force the textfield to be updated
sendActions(for: .editingChanged)
}
// deletes the last digit of the text field
override func deleteBackward() {
// note that the field text property default value is an empty string so force unwrap its value is safe
// note also that collection remove at requires a non empty collection which is true as well in this case so no need to check if the collection is not empty.
text!.remove(at: text!.index(before: text!.endIndex))
// sends an editingChanged action to force the textfield to be updated
sendActions(for: .editingChanged)
}
#objc func editingChanged() {
guard value <= maxValue else {
text = Formatter.decimal.string(for: lastValue)
return
}
// This will format the textfield respecting the user device locale and settings
text = Formatter.decimal.string(for: value)
print("Value:", value)
lastValue = value
}
}
You would need to add those extensions to your project as well:
Extensions UITextField.swift file contents:
import UIKit
extension UITextField {
var string: String { text ?? "" }
}
Extensions Formatter.swift file contents:
import Foundation
extension Formatter {
static let decimal = NumberFormatter(numberStyle: .decimal)
}
Extensions NumberFormatter.swift file contents:
import Foundation
extension NumberFormatter {
convenience init(numberStyle: Style) {
self.init()
self.numberStyle = numberStyle
}
}
Extensions StringProtocol.swift file contents:
extension StringProtocol where Self: RangeReplaceableCollection {
var digits: Self { filter(\.isWholeNumber) }
var integer: Int? { Int(self) }
}
Sample project
swift 4.0
let stringNumber = "123"
let number = Int(stringNumber) //here number is of type "Int?"
//using Forced Unwrapping
if number != nil {
//string is converted to Int
}
you could also use Optional Binding other than forced binding.
eg:
if let number = Int(stringNumber) {
// number is of type Int
}
In Swift 4.2 and Xcode 10.1
let string = "789"
if let intValue = Int(string) {
print(intValue)
}
let integerValue = 789
let stringValue = String(integerValue)
OR
let stringValue = "\(integerValue)"
print(stringValue)
//Xcode 8.1 and swift 3.0
We can also handle it by Optional Binding, Simply
let occur = "10"
if let occ = Int(occur) {
print("By optional binding :", occ*2) // 20
}
Swift 3
The simplest and more secure way is:
#IBOutlet var textFieldA : UITextField
#IBOutlet var textFieldB : UITextField
#IBOutlet var answerLabel : UILabel
#IBAction func calculate(sender : AnyObject) {
if let intValueA = Int(textFieldA),
let intValueB = Int(textFieldB) {
let result = intValueA + intValueB
answerLabel.text = "The acceleration is \(result)"
}
else {
answerLabel.text = "The value \(intValueA) and/or \(intValueB) are not a valid integer value"
}
}
Avoid invalid values setting keyboard type to number pad:
textFieldA.keyboardType = .numberPad
textFieldB.keyboardType = .numberPad
In Swift 4:
extension String {
var numberValue:NSNumber? {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter.number(from: self)
}
}
let someFloat = "12".numberValue
Useful for String to Int and other type
extension String {
//Converts String to Int
public func toInt() -> Int? {
if let num = NumberFormatter().number(from: self) {
return num.intValue
} else {
return nil
}
}
//Converts String to Double
public func toDouble() -> Double? {
if let num = NumberFormatter().number(from: self) {
return num.doubleValue
} else {
return nil
}
}
/// EZSE: Converts String to Float
public func toFloat() -> Float? {
if let num = NumberFormatter().number(from: self) {
return num.floatValue
} else {
return nil
}
}
//Converts String to Bool
public func toBool() -> Bool? {
return (self as NSString).boolValue
}
}
Use it like :
"123".toInt() // 123
i have made a simple program, where you have 2 txt field you take input form the user and add them to make it simpler to understand please find the code below.
#IBOutlet weak var result: UILabel!
#IBOutlet weak var one: UITextField!
#IBOutlet weak var two: UITextField!
#IBAction func add(sender: AnyObject) {
let count = Int(one.text!)
let cal = Int(two.text!)
let sum = count! + cal!
result.text = "Sum is \(sum)"
}
hope this helps.
Swift 3.0
Try this, you don't need to check for any condition I have done everything just use this function. Send anything string, number, float, double ,etc,. you get a number as a value or 0 if it is unable to convert your value
Function:
func getNumber(number: Any?) -> NSNumber {
guard let statusNumber:NSNumber = number as? NSNumber else
{
guard let statString:String = number as? String else
{
return 0
}
if let myInteger = Int(statString)
{
return NSNumber(value:myInteger)
}
else{
return 0
}
}
return statusNumber
}
Usage:
Add the above function in code and to convert use
let myNumber = getNumber(number: myString)
if the myString has a number or string it returns the number else it returns 0
Example 1:
let number:String = "9834"
print("printing number \(getNumber(number: number))")
Output: printing number 9834
Example 2:
let number:Double = 9834
print("printing number \(getNumber(number: number))")
Output: printing number 9834
Example 3:
let number = 9834
print("printing number \(getNumber(number: number))")
Output: printing number 9834
About int() and Swift 2.x: if you get a nil value after conversion check if you try to convert a string with a big number (for example: 1073741824), in this case try:
let bytesInternet : Int64 = Int64(bytesInternetString)!
Latest swift3 this code is simply to convert string to int
let myString = "556"
let myInt = Int(myString)
Because a string might contain non-numerical characters you should use a guard to protect the operation. Example:
guard let labelInt:Int = Int(labelString) else {
return
}
useLabelInt()
I recently got the same issue. Below solution is work for me:
let strValue = "123"
let result = (strValue as NSString).integerValue
Swift5 float or int string to int:
extension String {
func convertStringToInt() -> Int {
return Int(Double(self) ?? 0.0)
}
}
let doubleStr = "4.2"
// print 4
print(doubleStr.convertStringToInt())
let intStr = "4"
// print 4
print(intStr.convertStringToInt())
Use this:
// get the values from text boxes
let a:Double = firstText.text.bridgeToObjectiveC().doubleValue
let b:Double = secondText.text.bridgeToObjectiveC().doubleValue
// we checking against 0.0, because above function return 0.0 if it gets failed to convert
if (a != 0.0) && (b != 0.0) {
var ans = a + b
answerLabel.text = "Answer is \(ans)"
} else {
answerLabel.text = "Input values are not numberic"
}
OR
Make your UITextField KeyboardType as DecimalTab from your XIB or storyboard, and remove any if condition for doing any calculation, ie.
var ans = a + b
answerLabel.text = "Answer is \(ans)"
Because keyboard type is DecimalPad there is no chance to enter other 0-9 or .
Hope this help !!
// To convert user input (i.e string) to int for calculation.I did this , and it works.
let num:Int? = Int(firstTextField.text!);
let sum:Int = num!-2
print(sum);
This works for me
var a:Int? = Int(userInput.text!)
for Swift3.x
extension String {
func toInt(defaultValue: Int) -> Int {
if let n = Int(self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)) {
return n
} else {
return defaultValue
}
}
}
Swift 4, Swift 5
There are different cases to convert from something to something data type, it depends the input.
If the input data type is Any, we have to use as before convert to actual data type, then convert to data type what we want. For example:
func justGetDummyString() -> Any {
return "2000"
}
let dummyString: String = (justGetDummyString() as? String) ?? "" // output = "2000"
let dummyInt: Int = Int(dummyString) ?? 0 // output = 2000
for Alternative solution. You can use extension a native type. You can test with playground.
extension String {
func add(a: Int) -> Int? {
if let b = Int(self) {
return b + a
}
else {
return nil
}
}
}
"2".add(1)
My solution is to have a general extension for string to int conversion.
extension String {
// default: it is a number suitable for your project if the string is not an integer
func toInt(default: Int) -> Int {
if let result = Int(self) {
return result
}
else {
return default
}
}
}
#IBAction func calculateAclr(_ sender: Any) {
if let addition = addition(arrayString: [txtBox1.text, txtBox2.text, txtBox3.text]) {
print("Answer = \(addition)")
lblAnswer.text = "\(addition)"
}
}
func addition(arrayString: [Any?]) -> Int? {
var answer:Int?
for arrayElement in arrayString {
if let stringValue = arrayElement, let intValue = Int(stringValue) {
answer = (answer ?? 0) + intValue
}
}
return answer
}
Question : string "4.0000" can not be convert into integer using Int("4.000")?
Answer : Int() check string is integer or not if yes then give you integer and otherwise nil. but Float or Double can convert any number string to respective Float or Double without giving nil. Example if you have "45" integer string but using Float("45") gives you 45.0 float value or using Double("4567") gives you 45.0.
Solution : NSString(string: "45.000").integerValue or Int(Float("45.000")!)! to get correct result.
An Int in Swift contains an initializer that accepts a String. It returns an optional Int? as the conversion can fail if the string contains not a number.
By using an if let statement you can validate whether the conversion succeeded.
So your code become something like this:
#IBOutlet var txtBox1 : UITextField
#IBOutlet var txtBox2 : UITextField
#IBOutlet var txtBox3 : UITextField
#IBOutlet var lblAnswer : UILabel
#IBAction func btn1(sender : AnyObject) {
let answer1 = "The acceleration is"
var answer2 = txtBox1
var answer3 = txtBox2
var answer4 = txtBox3
if let intAnswer = Int(txtBox1.text) {
// Correctly converted
}
}
Swift 5.0 and Above
Working
In case if you are splitting the String it creates two substrings and not two Strings . This below method will check for Any and convert it t0 NSNumber its easy to convert a NSNumber to Int, Float what ever data type you need.
Actual Code
//Convert Any To Number Object Removing Optional Key Word.
public func getNumber(number: Any) -> NSNumber{
guard let statusNumber:NSNumber = number as? NSNumber else {
guard let statString:String = number as? String else {
guard let statSubStr : Substring = number as? Substring else {
return 0
}
if let myInteger = Int(statSubStr) {
return NSNumber(value:myInteger)
}
else{
return 0
}
}
if let myInteger = Int(statString) {
return NSNumber(value:myInteger)
}
else if let myFloat = Float(statString) {
return NSNumber(value:myFloat)
}else {
return 0
}
}
return statusNumber }
Usage
if let hourVal = getNumber(number: hourStr) as? Int {
}
Passing String to check and convert to Double
Double(getNumber(number: dict["OUT"] ?? 0)
As of swift 3, I have to force my #%#! string & int with a "!" otherwise it just doesn't work.
For example:
let prefs = UserDefaults.standard
var counter: String!
counter = prefs.string(forKey:"counter")
print("counter: \(counter!)")
var counterInt = Int(counter!)
counterInt = counterInt! + 1
print("counterInt: \(counterInt!)")
OUTPUT:
counter: 1
counterInt: 2

Resources