我试图在Swift 3中扩展Foundation的MSVCR120.DLL
类,添加了一个便利初始化器。但它对基金会提供的初始化程序的调用永远不会返回。
这个问题在以下简单的演示中说明,该演示可以作为Playground运行。
Timer
控制台输出:
Next statement never returns
进一步研究,
•我编写了类似的代码扩展import Foundation
extension Timer {
convenience init(target: Any) {
print("Next statement never returns")
self.init(timeInterval: 1.0,
target: target,
selector: #selector(Target.fire),
userInfo: nil,
repeats: true)
print("This never executes")
}
}
class Target {
@objc func fire(_ timer: Timer) {
}
}
let target = Target()
let timer = Timer(target: target)
(使用实例初始化程序的其他基础类之一)。结果:没问题。
•为了消除Objective-C的原因,我将包装的初始化程序更改为URLProtocol
方法并提供了Swift闭包。结果:同样的问题。
答案 0 :(得分:4)
我实际上并不知道答案,但我在实际应用程序中运行此操作时看到调试器存在无限递归(因此挂起)。我怀疑这是因为你实际上并没有调用Timer的指定初始化器。这个事实并不明显,但是如果你尝试子类化Timer并调用super.init(timeInterval...)
编译器会抱怨,并且标题中super.init(timeInterval...)
上还有一个奇怪的“未继承”标记。
我可以通过调用self.init(fireAt:...)
来解决此问题:
extension Timer {
convenience init(target: Any) {
print("Next statement never returns") // but it does
self.init(fireAt: Date(), interval: 1, target: target,
selector: #selector(Target.fire), userInfo: nil, repeats: true)
print("This never executes") // but it does
}
}
准备好你会...
答案 1 :(得分:2)
我看到与无限递归的matt所描述的相同的问题。 -[NSCFTimer release]
在同一个对象上反复调用。通过从实例初始化程序中调用类初始化程序,可以在纯Objective-C中重现此行为。
@implementation NSTimer (Foo)
- (instancetype)initWithTarget:(id)t {
return [NSTimer timerWithTimeInterval:1 target:t selector:@selector(description) userInfo:nil repeats:NO];
}
@end
编译器抱怨指定的初始化程序没有被调用,这似乎与修复问题有关,但没有解释递归调用。
warning: convenience initializer missing a 'self' call to another initializer
答案 2 :(得分:0)
@matt的答案有效。
是的,我在我的应用程序中也看到了无限递归 - CFReleases。 Swift书很清楚便利初始化器必须调用指定的初始化器。但是,并没有说出惩罚是什么。无限递归虽然令人惊讶,但似乎是合理的。
但是,请查看这两个声明,您可以通过选择单击或命令单击Xcode中的其中一个方法来查看这些声明:
init(timeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void)
convenience init(fire date: Date, interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void)
我觉得那里有些不对劲。 @matt建议的函数,附加的(" fire")参数解决了我的问题,标记为 convenience 。我使用的功能,不标记便利,我认为(作为一个Swift新手)是指定的。但它只有一个参数。咦?
我想我会提交一个错误,指出 Apple在错误的功能上以某种方式获得便利关键字。这可能是因为Swift真的没有头文件,对吗?所以我想知道当我们选择点击基础功能时我们会看到什么。可能他们的工作流程中有一个步骤容易出现人为错误?