如何在Swift中更好地使用类型转换?

时间:2014-09-30 12:11:10

标签: objective-c xcode casting swift

我遇到快速类型转换的问题,让我说我有这个变量

let anim = CABasicAnimation(keyPath: "position")
let sublayersCount : NSInteger = 4
let sublayerIdx :NSInteger = 2
let instanceDelay : CGFloat = 0.1;

我想对他们做一些数学计算。在目标c中,我这样写

anim.beginTime += (sublayersCount - sublayerIdx - 1) * instanceDelay;

但是在快速,同样感觉非常笨拙,有没有办法改善它?

anim.beginTime = CFTimeInterval(CGFloat(anim.beginTime) + CGFloat(sublayersCount - sublayerIdx - 1) * instanceDelay)

2 个答案:

答案 0 :(得分:2)

我同意这很麻烦。你可以通过提供临时重载来解决它,就像

一样
func * (lhs: Double, rhs: CGFloat) -> CGFloat {
    return CGFloat(lhs * Double(rhs))
}

func + (lhs: Double, rhs: CGFloat) -> CGFloat {
    return CGFloat(lhs) + CGFloat(rhs)
}

func - (lhs: Int, rhs: Int) -> Double {
    return lhs - rhs
}

anim.beginTime = CFTimeInterval(anim.beginTime + (sublayersCount - sublayerIdx - 1) * instanceDelay)

当然,这个特定的例子非常具体,但你明白了。

话虽这么说,有一个库提供了更广泛的方便重载,允许您隐式转换不同的数字类型。看看:https://github.com/seivan/ScalarArithmetic/blob/master/ScalarArithmetic/ScalarArithmetic.swift

答案 1 :(得分:0)

Swift中的类型转换是一场噩梦,老实说是个笑话。我无法相信苹果认为这是任何人想要的好主意。幸运的是,Swift具有强大的运算符重载和类型扩展,因此我们可以解决这个问题。

这不是所有类型的完整示例,但我们的想法是我们有运算符重载来将类型转换为更大的尺寸和/或符号或浮点数。

例如,UInt8 + Float返回一个Float(操作中最大的签名类型)。 UInt + Int返回Int(相同的大小,但朝向标志)。 UInt8 + Uint返回UInt(较大的大小)。假设我们想要保留数字的符号并通过转换为更大的大小来防止溢出(因此UInt8(255)+ 1.5返回Float(256.5)而不是截断或崩溃)。

注意:我不建议将其放在现有的代码库中,因为它破坏了Swift中的许多隐含假设。

/*

Arithmetic on integers (signed or unsigned) & floats casts up to Float
Arithmetic on signed integers & unsigned integers (of any size) casts up to Int
Arithmetic on unsigned integers & unsigned integers (of any size) casts up to UInt

Float + Int = Float
Float + UInt = Float

UInt + Int = Int
UInt + UInt = UInt
UInt8 + UInt = UInt
UInt8 + Int = Int

*/

// MARK: Floating Point Arithmetic Operators

protocol FloatingPointArithmetic {
    var toFloat: Float { get }
}

func + <T: FloatingPointArithmetic> (lhs: T, rhs: Float) -> Float { return lhs.toFloat + rhs }
func - <T: FloatingPointArithmetic> (lhs: T, rhs: Float) -> Float { return lhs.toFloat - rhs }
func * <T: FloatingPointArithmetic> (lhs: T, rhs: Float) -> Float { return lhs.toFloat * rhs }
func / <T: FloatingPointArithmetic> (lhs: T, rhs: Float) -> Float { return lhs.toFloat / rhs }

// MARK: Integer Arithmetic Operators

protocol IntegerArithmetic: FloatingPointArithmetic {
    var toSigned: Int { get }
    var toUnsigned: UInt { get }
}

protocol SignedIntegerArithmetic: IntegerArithmetic {}
protocol UnsignedIntegerArithmetic: IntegerArithmetic {}

func + <T: SignedIntegerArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> Int { return lhs.toSigned + rhs.toSigned }
func + <T: UnsignedIntegerArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> UInt { return lhs.toUnsigned + rhs.toUnsigned }
func + <T: UnsignedIntegerArithmetic, U: SignedIntegerArithmetic> (lhs: T, rhs: U) -> Int { return lhs.toSigned + rhs.toSigned }

func - <T: SignedIntegerArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> Int { return lhs.toSigned - rhs.toSigned }
func - <T: UnsignedIntegerArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> UInt { return lhs.toUnsigned - rhs.toUnsigned }
func - <T: UnsignedIntegerArithmetic, U: SignedIntegerArithmetic> (lhs: T, rhs: U) -> Int { return lhs.toSigned - rhs.toSigned }

func * <T: SignedIntegerArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> Int { return lhs.toSigned * rhs.toSigned }
func * <T: UnsignedIntegerArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> UInt { return lhs.toUnsigned * rhs.toUnsigned }
func * <T: UnsignedIntegerArithmetic, U: SignedIntegerArithmetic> (lhs: T, rhs: U) -> Int { return lhs.toSigned * rhs.toSigned }

func / <T: SignedIntegerArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> Int { return lhs.toSigned / rhs.toSigned }
func / <T: UnsignedIntegerArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> UInt { return lhs.toUnsigned / rhs.toUnsigned }
func / <T: UnsignedIntegerArithmetic, U: SignedIntegerArithmetic> (lhs: T, rhs: U) -> Int { return lhs.toSigned / rhs.toSigned }

func + <T: FloatingPointArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> Float { return lhs.toFloat + rhs.toFloat }
func + <T: FloatingPointArithmetic, U: SignedIntegerArithmetic> (lhs: T, rhs: U) -> Float { return lhs.toFloat + rhs.toFloat }

func - <T: FloatingPointArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> Float { return lhs.toFloat - rhs.toFloat }
func - <T: FloatingPointArithmetic, U: SignedIntegerArithmetic> (lhs: T, rhs: U) -> Float { return lhs.toFloat - rhs.toFloat }

func * <T: FloatingPointArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> Float { return lhs.toFloat * rhs.toFloat }
func * <T: FloatingPointArithmetic, U: SignedIntegerArithmetic> (lhs: T, rhs: U) -> Float { return lhs.toFloat * rhs.toFloat }

func / <T: FloatingPointArithmetic, U: UnsignedIntegerArithmetic> (lhs: T, rhs: U) -> Float { return lhs.toFloat / rhs.toFloat }
func / <T: FloatingPointArithmetic, U: SignedIntegerArithmetic> (lhs: T, rhs: U) -> Float { return lhs.toFloat / rhs.toFloat }


// MARK: Supported Types

extension Float: FloatingPointArithmetic {
    var toFloat: Float { return self }
}

extension UInt: FloatingPointArithmetic, UnsignedIntegerArithmetic {
    var toSigned: Int { return Int(self) }
    var toUnsigned: UInt { return self }
    var toFloat: Float { return Float(self) }
}

extension UInt8: FloatingPointArithmetic, UnsignedIntegerArithmetic {
    var toSigned: Int { return Int(self) }
    var toUnsigned: UInt { return UInt(self) }
    var toFloat: Float { return Float(self) }
}

extension Int: FloatingPointArithmetic, SignedIntegerArithmetic {
    var toSigned: Int { return self }
    var toUnsigned: UInt { return UInt(self) }
    var toFloat: Float { return Float(self) }
}