Swift 通用完成处理程序
Swift generic completion handler
我正在尝试弄清楚如何创建通用完成处理程序。下面是一个示例,说明了一个示例 "internal" 通用完成处理程序和相同的通用完成处理程序,如果我可以以 "external" 形式创建它,我希望能够创建它。问题是我不知道如何在完成处理程序中编写 internalCompletion<T: MyEnum>...
的等价物。我在 externalCompletion
函数中写下了我想象中的样子:类似于 func externalCompletion(_ completer<T: MyEnum>: ((T) -> Void) where T: Hashable))
的内容,但这显然是不正确的。我正在尝试做的事情可能吗?我的直觉是 swift 不会让完成处理程序保持通用性,总是需要在函数级别进行类型转换,这会破坏我的示例的目的(即 func externalCompletetion<T: MyEnum>(_ completer: ((T) -> Void)) where T: Hashable
,问题在于我将不得不在 EnumA、EnumB 和 EnumC 之间做出选择,无法 运行 在这三个方面都完成。)
typealias MyEnumKeyedData<T: MyEnum> = [T: String] where T: Hashable
// MARK : - MyEnum Protocol
protocol MyEnum {
static func all<T: MyEnum>(_:T.Type) -> [T] where T: Hashable
static var all: [MyEnum] { get }
}
extension MyEnum {
static func all<T: MyEnum>(_:T.Type) -> [T] where T: Hashable { return Self.all as! [T] }
}
// MARK : - My enums
enum EnumA: MyEnum {
case first
static var all: [MyEnum] { return [EnumA.first]}
}
enum EnumB: MyEnum {
case first
static var all: [MyEnum] { return [EnumB.first]}
}
enum EnumC: MyEnum {
case first
static var all: [MyEnum] { return [EnumC.first]}
}
// MARK : - MyEnum Data Iterator
class MyDataEnumIterator {
var dataA: MyEnumKeyedData<EnumA> = [:]
var dataB: MyEnumKeyedData<EnumB> = [:]
var dataC: MyEnumKeyedData<EnumC> = [:]
func updateData<T: MyEnum>(_ key: T, _ value: String) where T: Hashable {
switch T.self {
case is EnumA.Type: dataA[key as! EnumA] = value
case is EnumB.Type: dataB[key as! EnumB] = value
case is EnumC.Type: dataC[key as! EnumC] = value
default: fatalError("Enum does not exist")
}
}
// Internal (This works)
func internalEnumIterator() {
for key in EnumA.all(EnumA.self) { internalCompletion(key) }
for key in EnumB.all(EnumB.self) { internalCompletion(key) }
for key in EnumC.all(EnumC.self) { internalCompletion(key) }
}
func internalCompletion<T: MyEnum>(_ key: T) where T: Hashable {
let value = "\(key)"
updateData(key, value)
}
// External (This obviously doesn't, just sketching the idea)
func externalEnumIterator(_ completer<T: MyEnum>: ((T) -> Void) where T: Hashable) {
for key in EnumA.all(EnumA.self) { completer(key) }
for key in EnumB.all(EnumB.self) { completer(key) }
for key in EnumC.all(EnumC.self) { completer(key) }
}
}
// MARK : - Test cases (internal works, external does not, just sketching example)
let iterator = MyDataEnumIterator()
iterator.externalEnumIterator({ <T: MyEnum> (T) where T: Hashable in
let value = "\(key)"
iterator.updateData(key, value)
})
iterator.internalEnumIterator()
这是代码的工作版本,只需进行最少的必要更改即可运行
typealias MyEnumKeyedData<T: MyEnum> = [T: String] where T: Hashable
// MARK : - MyEnum Protocol
protocol MyEnum {
static func all<T: MyEnum>(_:T.Type) -> [T] where T: Hashable
static var all: [MyEnum] { get }
}
extension MyEnum {
static func all<T: MyEnum>(_:T.Type) -> [T] where T: Hashable { return Self.all as! [T] }
}
// MARK : - My enums
enum EnumA: MyEnum {
case first
static var all: [MyEnum] { return [EnumA.first]}
}
enum EnumB: MyEnum {
case first
static var all: [MyEnum] { return [EnumB.first]}
}
enum EnumC: MyEnum {
case first
static var all: [MyEnum] { return [EnumC.first]}
}
// MARK : - MyEnum Data Iterator
class MyDataEnumIterator {
var dataA: MyEnumKeyedData<EnumA> = [:]
var dataB: MyEnumKeyedData<EnumB> = [:]
var dataC: MyEnumKeyedData<EnumC> = [:]
func updateData(_ key: MyEnum, _ value: String) {
switch key {
case let key as EnumA: dataA[key] = value
case let key as EnumB: dataB[key] = value
case let key as EnumC: dataC[key] = value
default: fatalError("Enum does not exist")
}
}
// Internal (This works)
func internalEnumIterator() {
for key in EnumA.all(EnumA.self) { internalCompletion(key) }
for key in EnumB.all(EnumB.self) { internalCompletion(key) }
for key in EnumC.all(EnumC.self) { internalCompletion(key) }
}
func internalCompletion<T: MyEnum>(_ key: T) where T: Hashable {
let value = "\(key)"
updateData(key, value)
}
func EnumIterator(_ compeltitionHandler: (MyEnum) -> Void) {
for key in EnumA.all(EnumA.self) { compeltitionHandler(key as MyEnum) }
for key in EnumB.all(EnumB.self) { compeltitionHandler(key as MyEnum) }
for key in EnumC.all(EnumC.self) { compeltitionHandler(key as MyEnum) }
}
}
let iterator = MyDataEnumIterator()
iterator.EnumIterator{ key in
let value = "\(key)"
iterator.updateData(key, value)
}
iterator.internalEnumIterator()
这是删除所有废话并添加下标语法的合理版本的代码:
// MARK : - MyEnum Protocol
protocol MyEnum {
static func all() -> [MyEnum]
}
// MARK : - My enums
enum EnumA: MyEnum {
case first
static func all() -> [MyEnum] { return [EnumA.first] }
}
enum EnumB: MyEnum {
case first
static func all() -> [MyEnum] { return [EnumB.first] }
}
enum EnumC: MyEnum {
case first
static func all() -> [MyEnum] { return [EnumC.first] }
}
// MARK : - MyEnum Data Iterator
class MyDataEnumIterator {
var dataA = [EnumA: String]()
var dataB = [EnumB: String]()
var dataC = [EnumC: String]()
subscript(key: MyEnum) -> String? {
get {
switch key {
case let key as EnumA: return dataA[key]
case let key as EnumB: return dataB[key]
case let key as EnumC: return dataC[key]
default: fatalError("Enum does not exist")
}
}
set {
switch key {
case let key as EnumA: dataA[key] = newValue
case let key as EnumB: dataB[key] = newValue
case let key as EnumC: dataC[key] = newValue
default: fatalError("Enum does not exist")
}
}
}
func EnumIterator(_ body: (MyEnum) -> Void) {
EnumA.all().forEach(body);
EnumB.all().forEach(body);
EnumC.all().forEach(body);
}
}
let iterator = MyDataEnumIterator()
iterator.EnumIterator{
iterator[[=11=]] = "\([=11=])"
}
我正在尝试弄清楚如何创建通用完成处理程序。下面是一个示例,说明了一个示例 "internal" 通用完成处理程序和相同的通用完成处理程序,如果我可以以 "external" 形式创建它,我希望能够创建它。问题是我不知道如何在完成处理程序中编写 internalCompletion<T: MyEnum>...
的等价物。我在 externalCompletion
函数中写下了我想象中的样子:类似于 func externalCompletion(_ completer<T: MyEnum>: ((T) -> Void) where T: Hashable))
的内容,但这显然是不正确的。我正在尝试做的事情可能吗?我的直觉是 swift 不会让完成处理程序保持通用性,总是需要在函数级别进行类型转换,这会破坏我的示例的目的(即 func externalCompletetion<T: MyEnum>(_ completer: ((T) -> Void)) where T: Hashable
,问题在于我将不得不在 EnumA、EnumB 和 EnumC 之间做出选择,无法 运行 在这三个方面都完成。)
typealias MyEnumKeyedData<T: MyEnum> = [T: String] where T: Hashable
// MARK : - MyEnum Protocol
protocol MyEnum {
static func all<T: MyEnum>(_:T.Type) -> [T] where T: Hashable
static var all: [MyEnum] { get }
}
extension MyEnum {
static func all<T: MyEnum>(_:T.Type) -> [T] where T: Hashable { return Self.all as! [T] }
}
// MARK : - My enums
enum EnumA: MyEnum {
case first
static var all: [MyEnum] { return [EnumA.first]}
}
enum EnumB: MyEnum {
case first
static var all: [MyEnum] { return [EnumB.first]}
}
enum EnumC: MyEnum {
case first
static var all: [MyEnum] { return [EnumC.first]}
}
// MARK : - MyEnum Data Iterator
class MyDataEnumIterator {
var dataA: MyEnumKeyedData<EnumA> = [:]
var dataB: MyEnumKeyedData<EnumB> = [:]
var dataC: MyEnumKeyedData<EnumC> = [:]
func updateData<T: MyEnum>(_ key: T, _ value: String) where T: Hashable {
switch T.self {
case is EnumA.Type: dataA[key as! EnumA] = value
case is EnumB.Type: dataB[key as! EnumB] = value
case is EnumC.Type: dataC[key as! EnumC] = value
default: fatalError("Enum does not exist")
}
}
// Internal (This works)
func internalEnumIterator() {
for key in EnumA.all(EnumA.self) { internalCompletion(key) }
for key in EnumB.all(EnumB.self) { internalCompletion(key) }
for key in EnumC.all(EnumC.self) { internalCompletion(key) }
}
func internalCompletion<T: MyEnum>(_ key: T) where T: Hashable {
let value = "\(key)"
updateData(key, value)
}
// External (This obviously doesn't, just sketching the idea)
func externalEnumIterator(_ completer<T: MyEnum>: ((T) -> Void) where T: Hashable) {
for key in EnumA.all(EnumA.self) { completer(key) }
for key in EnumB.all(EnumB.self) { completer(key) }
for key in EnumC.all(EnumC.self) { completer(key) }
}
}
// MARK : - Test cases (internal works, external does not, just sketching example)
let iterator = MyDataEnumIterator()
iterator.externalEnumIterator({ <T: MyEnum> (T) where T: Hashable in
let value = "\(key)"
iterator.updateData(key, value)
})
iterator.internalEnumIterator()
这是代码的工作版本,只需进行最少的必要更改即可运行
typealias MyEnumKeyedData<T: MyEnum> = [T: String] where T: Hashable
// MARK : - MyEnum Protocol
protocol MyEnum {
static func all<T: MyEnum>(_:T.Type) -> [T] where T: Hashable
static var all: [MyEnum] { get }
}
extension MyEnum {
static func all<T: MyEnum>(_:T.Type) -> [T] where T: Hashable { return Self.all as! [T] }
}
// MARK : - My enums
enum EnumA: MyEnum {
case first
static var all: [MyEnum] { return [EnumA.first]}
}
enum EnumB: MyEnum {
case first
static var all: [MyEnum] { return [EnumB.first]}
}
enum EnumC: MyEnum {
case first
static var all: [MyEnum] { return [EnumC.first]}
}
// MARK : - MyEnum Data Iterator
class MyDataEnumIterator {
var dataA: MyEnumKeyedData<EnumA> = [:]
var dataB: MyEnumKeyedData<EnumB> = [:]
var dataC: MyEnumKeyedData<EnumC> = [:]
func updateData(_ key: MyEnum, _ value: String) {
switch key {
case let key as EnumA: dataA[key] = value
case let key as EnumB: dataB[key] = value
case let key as EnumC: dataC[key] = value
default: fatalError("Enum does not exist")
}
}
// Internal (This works)
func internalEnumIterator() {
for key in EnumA.all(EnumA.self) { internalCompletion(key) }
for key in EnumB.all(EnumB.self) { internalCompletion(key) }
for key in EnumC.all(EnumC.self) { internalCompletion(key) }
}
func internalCompletion<T: MyEnum>(_ key: T) where T: Hashable {
let value = "\(key)"
updateData(key, value)
}
func EnumIterator(_ compeltitionHandler: (MyEnum) -> Void) {
for key in EnumA.all(EnumA.self) { compeltitionHandler(key as MyEnum) }
for key in EnumB.all(EnumB.self) { compeltitionHandler(key as MyEnum) }
for key in EnumC.all(EnumC.self) { compeltitionHandler(key as MyEnum) }
}
}
let iterator = MyDataEnumIterator()
iterator.EnumIterator{ key in
let value = "\(key)"
iterator.updateData(key, value)
}
iterator.internalEnumIterator()
这是删除所有废话并添加下标语法的合理版本的代码:
// MARK : - MyEnum Protocol
protocol MyEnum {
static func all() -> [MyEnum]
}
// MARK : - My enums
enum EnumA: MyEnum {
case first
static func all() -> [MyEnum] { return [EnumA.first] }
}
enum EnumB: MyEnum {
case first
static func all() -> [MyEnum] { return [EnumB.first] }
}
enum EnumC: MyEnum {
case first
static func all() -> [MyEnum] { return [EnumC.first] }
}
// MARK : - MyEnum Data Iterator
class MyDataEnumIterator {
var dataA = [EnumA: String]()
var dataB = [EnumB: String]()
var dataC = [EnumC: String]()
subscript(key: MyEnum) -> String? {
get {
switch key {
case let key as EnumA: return dataA[key]
case let key as EnumB: return dataB[key]
case let key as EnumC: return dataC[key]
default: fatalError("Enum does not exist")
}
}
set {
switch key {
case let key as EnumA: dataA[key] = newValue
case let key as EnumB: dataB[key] = newValue
case let key as EnumC: dataC[key] = newValue
default: fatalError("Enum does not exist")
}
}
}
func EnumIterator(_ body: (MyEnum) -> Void) {
EnumA.all().forEach(body);
EnumB.all().forEach(body);
EnumC.all().forEach(body);
}
}
let iterator = MyDataEnumIterator()
iterator.EnumIterator{
iterator[[=11=]] = "\([=11=])"
}