再次完全重写这个问题,希望把重点放在我试图解决的问题上。
由于我们无法控制的外部框架,我们有以下课程要求我们实施"(?s:.*?)(?<!\\)"
,如此...
ObjCProtocolRequiringBla
如您所见,class FooBase : NSObject, ObjCProtocolRequiringBla {
class var possibleValues:[String] {
// Note: Use preconditionFailure, not fatalError for things like this.
// At runtime, they both halt execution, but precondition(Failure)
// only logs the message for debug builds. Additionally,
// in debug builds it pauses in a debuggable state rather than crash.
preconditionFailure("You must override possibleValues")
}
// This satisfies the objective-c protocol requirement
final func getBla() -> Bla {
let subclassSpecificValues = type(of:self).possibleValues
return Bla(withValues:subclassSpecificValues)
}
}
class FooA : FooBase
override class var possibleValues:[String] {
return [
"Value A1",
"Value A2",
"Value A3"
]
}
}
class FooB : FooBase
override class var possibleValues:[String] {
return [
"Value B1",
"Value B2",
"Value B3",
"Value B4"
]
}
}
用于实施possibleValues
。此外,它必须与该特定子类的所有实例相同,因此是一个类变量而不是实例变量。这是因为在代码中的另一个地方,我们必须检索所有子类中的所有可能值,例如......
getBla()
如果static func getAllPossibleValues:[String] {
return [
FooA.possibleValues,
FooB.possibleValues
].flatMap { $0 }
}
的子类未实现FooBase
,我试图弄清楚如何做是让编译器抱怨。
换句话说,我们如何才能使此报告成为编译时错误:
possibleValues
目前我所知道的唯一方法是上面的方法,在基类中用class FooC : FooBase
// Doesn't override class var possibleValues
}
或类似方法定义它,但这是运行时检查,而不是编译时间,所以它不是最好的解决方案。
答案 0 :(得分:0)
您可以通过使用扩展NSObjectProtocol的协议替换您的FooBase类来解决此问题。这将强制任何实现协议的类必须是NSObject的子类,并且还要实现所需的属性和方法。
protocol foo: NSObjectProtocol {
var someProp: String {get set}
func someFunc() -> Void
}
要从Objective-C使用协议,可以使用@objc注释,这至少适用于简单的场景,例如发送选择器#selector()作为参数。
@objc protocol foo: NSObjectProtocol {
var someProp: String {get set}
func someFunc() -> Void
}
以下代码正常运行
class fooClass: NSObject, foo {
var someProp: String
init(someProp: String) {
self.someProp = someProp
}
func someFunc() {
print("In someFunc with property: \(someProp)")
}
func timeIt() {
let timer = Timer.scheduledTimer(timeInterval: 0,
target: self, selector: #selector(someFunc), userInfo: nil, repeats: false)
print("timer created")
timer.fire()
}
}
func main() {
let f = fooClass(someProp: "test")
f.timeIt()
}
main()
答案 1 :(得分:0)
我试图弄清楚如何处理,如果FooBase的子类没有实现
possibleValues
,编译器就会抱怨。
你不能。您可以使possibleValues
类似于协议要求,并尝试采用该协议,但是如果FooBase本身实现possibleValues
,如果子类失败,则无法让编译器抱怨覆盖它。这不是一个愚蠢的想法,可能有计算机语言为你提供了一种方法,但Swift并不是一种语言。这就是为什么运行时解决方案是你能想到的最好的原因,而且这是标准模式,正如你看到UIPopoverBackgroundView这样的东西你可以看到。
答案 2 :(得分:0)
也许是这些方面的东西?我没有敲定每一个细节,但我认为这涵盖了很多你的编程问题。如果你想进一步讨论,让我们开一个聊天室,而不是继续在这里发表无休止的评论。
// Just to get it to compile
class Bla { init(withValues: [String]) {} }
protocol ObjCProtocolRequiringBla {}
class FooContainer : ObjCProtocolRequiringBla {
fileprivate var fooCore: FooProtocol
fileprivate init(_ fooCore: FooProtocol) { self.fooCore = fooCore }
// This satisfies the objective-c protocol requirement
final func getBla() -> Bla { return fooCore.getBla() }
}
protocol FooProtocol {
static var possibleValues:[String] { get }
func getBla() -> Bla
}
class FooA : NSObject, FooProtocol {
class var possibleValues:[String] {
return [
"Value A1",
"Value A2",
"Value A3"
]
}
func getBla() -> Bla {
return Bla(withValues: FooA.possibleValues)
}
}
class FooB : NSObject, FooProtocol {
class var possibleValues:[String] {
return [
"Value B1",
"Value B2",
"Value B3",
"Value B4"
]
}
func getBla() -> Bla {
return Bla(withValues: FooB.possibleValues)
}
}