【发布时间】:2015-08-04 16:23:39
【问题描述】:
在回答问题之前,我将首先解释我正在尝试做什么以及我是如何陷入困境的。
作为我自己的学习练习,我使用了一些我已经在 Objective-C 中解决的问题,看看我如何使用 Swift 以不同的方式解决它们。我遇到的具体情况是一小块,它在它改变之前和之后捕获一个值,并在两者之间进行插值以创建动画的关键帧。
为此,我有一个对象Capture,其中包含对象属性、键路径和两个id 属性,用于之前和之后的值。后来,在对捕获的值进行插值时,我确保可以通过将它们中的每一个包装在 Value 类中进行插值,该类使用类簇返回适当的类,具体取决于它所包装的值的类型,或者 nil 用于不支持的类型。
这行得通,而且我可以让它在 Swift 中也能按照相同的模式运行,但感觉不像 Swift。
什么有效
我创建了一个Mixable 协议,而不是包装捕获的值作为启用插值的一种方式,当类型支持必要的基本算术时,我创建了一个类型可以遵循的协议并使用协议扩展:
protocol SimpleArithmeticType {
func +(lhs: Self, right: Self) -> Self
func *(lhs: Self, amount: Double) -> Self
}
protocol Mixable {
func mix(with other: Self, by amount: Double) -> Self
}
extension Mixable where Self: SimpleArithmeticType {
func mix(with other: Self, by amount: Double) -> Self {
return self * (1.0 - amount) + other * amount
}
}
这部分工作得非常好,并强制执行同质混合(一个类型只能与其自己的类型混合),这在 Objective-C 实现中没有强制执行。
我卡住的地方
下一个合乎逻辑的步骤,也是我卡住的地方,似乎是让每个 Capture 实例(现在是一个结构)保存两个相同可混合类型的变量,而不是两个 AnyObject。我还将初始化参数从一个对象和一个关键路径更改为一个返回对象()->T
struct Capture<T: Mixable> {
typealias Evaluation = () -> T
let eval: Evaluation
let before: T
var after: T {
return eval()
}
init(eval: Evaluation) {
self.eval = eval
self.before = eval()
}
}
这在可以推断类型时有效,例如:
let captureInt = Capture {
return 3.0
}
// > Capture<Double>
但不使用键值编码,返回 AnyObject:\
let captureAnyObject = Capture {
return myObject.valueForKeyPath("opacity")!
}
错误:无法使用类型为“(() -> _)”的参数列表调用类型“Capture”的初始化程序
AnyObject 不符合Mixable 协议,所以我可以理解为什么这不起作用。但是我可以检查对象的真正类型,并且由于我只介绍了少数可混合的类型,但我可以涵盖所有情况并返回正确的 Capture 类型。太看如果这甚至可以工作我做了一个更简单的例子
一个更简单的例子
struct Foo<T> {
let x: T
init(eval: ()->T) {
x = eval()
}
}
在保证类型推断时有效:
let fooInt = Foo {
return 3
}
// > Foo<Int>
let fooDouble = Foo {
return 3.0
}
// > Foo<Double>
但是当闭包可以返回不同的类型时就不行
let condition = true
let foo = Foo {
if condition {
return 3
} else {
return 3.0
}
}
错误:无法使用类型为 '(() -> _)' 的参数列表调用类型 'Foo' 的初始化程序
我什至无法自己定义这样的闭包。
let condition = true // as simple as it could be
let evaluation = {
if condition {
return 3
} else {
return 3.0
}
}
错误:无法在当前上下文中推断闭包类型
我的问题
这是完全可以做到的吗?可以使用条件来确定泛型的类型吗?或者是否有另一种方法来保存相同类型的两个变量,其中类型是根据条件决定的?
编辑
我真正想要的是:
- 捕获更改前后的值并保存对(旧 + 新)以供以后使用(同质对的异构集合)。
- 遍历所有收集到的值,去掉那些不能插值的(除非这个步骤可以和收集步骤整合)
- 单独插入每个同质对(混合旧的 + 新的)。
但在解决该问题时,这个方向似乎是一条死胡同。我将不得不后退几步并尝试不同的方法(如果我再次陷入困境,可能会问一个不同的问题)。
【问题讨论】:
-
我认为解决这个问题的唯一方法是从当前的实现中退后一步,重新考虑这个闭包,这样它就不会返回多种类型(毕竟这看起来也不是很快!)
-
编辑后,请考虑查看此 SO 帖子:stackoverflow.com/questions/29796654/…