摘要git
知其然,更要知其因此然。前段时间用 String 转换 Int 处理时,发现一种状况返回 nil,就换成 String 转换 Double 的方式处理。今天就要来看看这种返回 nil 的状况是怎么形成的。swift
当有小数的 String 文本转换为 Int 类型时,返回的值并非我们想要的向下取整后的整数,而是 nil。less
// Int 转换为 String let intStr = "2.78" let int = Int(intStr) // nil
为何是nil?今天就来解解这个疑惑。this
首先com+鼠标左键
弹出选项,选择jump to Definition
(跳转到定义)一波操做,来到 Int 的定义地方,直接全局搜索一下 String
,直接看下定义。spa
/// Creates a new integer value from the given string. /// /// The string passed as `description` may begin with a plus or minus sign /// character (`+` or `-`), followed by one or more numeric digits (`0-9`). /// /// let x = Int("123") /// // x == 123 /// /// If `description` is in an invalid format, or if the value it denotes in /// base 10 is not representable, the result is `nil`. For example, the /// following conversions result in `nil`: /// /// Int(" 100") // Includes whitespace /// Int("21-50") // Invalid format /// Int("ff6600") // Characters out of bounds /// Int("10000000000000000000000000") // Out of range /// /// - Parameter description: The ASCII representation of a number. @inlinable public init?(_ description: String)
出处找到了,不想费力看注释的,直接看我给的结论:code
String 转换为 Int 类型,传入 Int 的 description 参数,必须是一个或者多个0-9组合的整数,整数前能够加“+”或者“-”。通俗说,这个 text 文本必须是一个整数。不然都返回 nil。orm
看到如今,大体能够明白了Int("2.78")
为何是 nil。ip
看完String 转换 Double 本质后,顺势也看下String 转换 Double 本质。一样的查找逻辑一波操做,找到它的定义ssl
extension Double : LosslessStringConvertible { /// Creates a new instance from the given string. /// /// The string passed as `text` can represent a real number in decimal or /// hexadecimal format or special floating-point values for infinity and NaN /// ("not a number"). /// /// The given string may begin with a plus or minus sign character (`+` or /// `-`). The allowed formats for each of these representations is then as /// follows: /// /// - A *decimal value* contains the significand, a sequence of decimal /// digits that may include a decimal point. /// /// let c = Double("-1.0") /// // c == -1.0 /// /// let d = Double("28.375") /// // d == 28.375 /// /// 此处省略 57 行注释------------------ /// /// - Parameter text: The input string to convert to a `Double` instance. If /// `text` has invalid characters or is in an invalid format, the result /// is `nil`. @inlinable public init?<S>(_ text: S) where S : StringProtocol @available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *) public init?(_ text: Substring) }
Double(string)
中的 string 文本能够是一个10进制、16进制或者浮点数的数(这个很是关键)。也能够添加“+”,“-”符号。ci
这里简单总结一下,Double 转换为 text,并保留几位小数的处理方法,加深一些印象
let double = Double(2.7895) // double 转换为 String print("\(double)") // 输出 "2.7895" // 保留两位小数 print(String(format:"%.2f", double) // 输出 "2.79"
看完了上面两个转换的定义以后,那么是否能够组合一下,解决可能出现的 nil?那是固然。
首先将文本转换为 Double,而后将 Double 转换为 Int。
Int(Double("2.78")!) // 2
代码验证没有问题,那么就看看,Double 转换 Int 作了什么事情。
/// Creates an integer from the given floating-point value, rounding toward /// zero. /// /// Any fractional part of the value passed as `source` is removed, rounding /// the value toward zero. /// /// let x = Int(21.5) /// // x == 21 /// let y = Int(-21.5) /// // y == -21 /// /// - Parameter source: A floating-point value to convert to an integer. /// `source` must be representable in this type after rounding toward /// zero. public init(_ source: Double)
定义中能够看到,Double 类型的数据,通过 Int 转换后,会生成一个只保留整数的数(小数部分略去)。因此也就支持了上节部分的处理方式。
在看 Double 转换 Int定义时,无心间发现一个好玩的定义,先上定义
/// Creates an integer from the given floating-point value, if it can be /// represented exactly. /// /// If the value passed as `source` is not representable exactly, the result /// is `nil`. In the following example, the constant `x` is successfully /// created from a value of `21.0`, while the attempt to initialize the /// constant `y` from `21.5` fails: /// /// let x = Int(exactly: 21.0) /// // x == Optional(21) /// let y = Int(exactly: 21.5) /// // y == nil /// /// - Parameter source: A floating-point value to convert to an integer. public init?(exactly source: Double)
定义说明,能够将一个精确标示的浮点数转换为 Int 类型。这里的精确标示就是没有小数的值。有了这个定义,那么岂不是能够解决某一个应用场景了吗?
显示存在须要保留2位小数的文本时,当浮点数是一个没有小数的数值,那么就显示整数。
// old String(format: "%.2f", 2.578) // 2.58 String(format: "%.2f", 2.0) // 2.00 // new if Int(exactly: 2.00) != nil { "\(Int(exactly: 2.00)!)" // 2 }
感谢看到这里,感受有一点收获,给个小赞。有分析的不到位,评论区留言帮我梳理。
偶尔有一些想要搞清楚的问题,评论区告诉我,我们一块儿解决。