我有一个带有1个可选字段和1个非可选字段的类,它们都具有Type AnotherClass 类型,并且还符合
CustomProtocol
:
protocol CustomProtocol {}
class CustomClass: CustomProtocol {
var nonoptionalField: AnotherClass = AnotherClass()
var optionalField: AnotherClass?
}
class AnotherClass: CustomProtocol {
}
现场 nonoptionalField 的类型 AnotherClass 和符合 CustomProtocol 。
另一方面, optionalField 实际上是 Optional
CustomProtocol
:
for field in Mirror(reflecting: CustomClass()).children {
let fieldMirror = Mirror(reflecting: field.value)
if fieldMirror.subjectType is CustomProtocol.Type {
print("\(field.label!) is \(fieldMirror.subjectType) and conforms CustomProtocol")
} else {
print("\(field.label!) is \(fieldMirror.subjectType) and DOES NOT conform CustomProtocol")
}
}
// nonoptionalField is AnotherClass and conforms CustomProtocol
// optionalField is Optional<AnotherClass> and DOES NOT conform CustomProtocol
如何解开 optionalField 属性的Type(而不是值),以便可以将其与其协议 CustomProtocol 关联?
换句话说,如何从 Optional
AnotherClass ? __
局限性:
我真的必须通过镜像使用Swift反射,不幸的是, 到目前为止,.subjectType 属性不允许解开 Optional
我不认为有一种简单的方法来执行此操作,因为我们目前无法在没有占位符的情况下就泛型类型进行交谈-因此我们不能简单地转换为Optional.Type
。
我们Optional<Any>.Type
也不能转换为,因为编译器无法为其提供实例的元类型值提供相同类型的自动转换(例如An
Optional<Int>
可以转换为an Optional<Any>
,而an Optional<Int>.Type
不能转换为a
Optional<Any>.Type
)。
然而,一种解决方案(尽管有些棘手)将是定义一个“虚拟协议”以表示“任何Optional
实例”,而与Wrapped
类型无关。然后,我们可以让该协议定义一个wrappedType
要求,以便获得Wrapped
给定Optional
类型的元类型值。
例如:
protocol OptionalProtocol {
// the metatype value for the wrapped type.
static var wrappedType: Any.Type { get }
}
extension Optional : OptionalProtocol {
static var wrappedType: Any.Type { return Wrapped.self }
}
现在,如果fieldMirror.subjectType
是Optional<Wrapped>.Type
,我们可以将其转换为OptionalProtocol.Type
,然后从中获取元wrappedType
类型值。然后,这使我们可以检查CustomProtocol
一致性。
for field in Mirror(reflecting: CustomClass()).children {
let fieldMirror = Mirror(reflecting: field.value)
// if fieldMirror.subjectType returns an optional metatype value
// (i.e an Optional<Wrapped>.Type), we can cast to OptionalProtocol.Type,
// and then get the Wrapped type, otherwise default to fieldMirror.subjectType
let wrappedType = (fieldMirror.subjectType as? OptionalProtocol.Type)?.wrappedType
?? fieldMirror.subjectType
// check for CustomProtocol conformance.
if wrappedType is CustomProtocol.Type {
print("\(field.label!) is \(fieldMirror.subjectType) and conforms CustomProtocol")
} else {
print("\(field.label!) is \(fieldMirror.subjectType) and DOES NOT conform CustomProtocol")
}
}
// nonoptionalField is AnotherClass and conforms CustomProtocol
// optionalField is Optional<AnotherClass> and conforms CustomProtocol
这仅处理单个级别的可选嵌套,但可以通过简单地反复尝试将结果元类型值强制转换为OptionalProtocol.Type
并获取wrappedType
,然后检查CustomProtocol
一致性来轻松地应用于任意可选嵌套级别。
class CustomClass : CustomProtocol {
var nonoptionalField: AnotherClass = AnotherClass()
var optionalField: AnotherClass??
var str: String = ""
}
/// If `type` is an `Optional<T>` metatype, returns the metatype for `T`
/// (repeating the unwrapping if `T` is an `Optional`), along with the number of
/// times an unwrap was performed. Otherwise just `type` will be returned.
func seeThroughOptionalType(
_ type: Any.Type
) -> (wrappedType: Any.Type, layerCount: Int) {
var type = type
var layerCount = 0
while let optionalType = type as? OptionalProtocol.Type {
type = optionalType.wrappedType
layerCount += 1
}
return (type, layerCount)
}
for field in Mirror(reflecting: CustomClass()).children {
let fieldMirror = Mirror(reflecting: field.value)
let (wrappedType, _) = seeThroughOptionalType(fieldMirror.subjectType)
if wrappedType is CustomProtocol.Type {
print("\(field.label!) is \(fieldMirror.subjectType) and conforms CustomProtocol")
} else {
print("\(field.label!) is \(fieldMirror.subjectType) and DOES NOT conform CustomProtocol")
}
}
// nonoptionalField is AnotherClass and conforms CustomProtocol
// optionalField is Optional<Optional<AnotherClass>> and conforms CustomProtocol
// str is String and DOES NOT conform CustomProtocol
问题内容: 编译错误如下: 类型“ AnyObject”不符合协议“ SequenceType” 这种压力是什么? 谁能帮我很多忙! 问题答案: 苹果在Swift编程语言中指出: for-in循环针对范围,序列,集合或进度中的每个项目执行一组语句。 目前,它仅符合protocol ,因此您无法在其上使用for循环。如果要这样做,则必须执行类似以下操作:
问题内容: Beta 3一切正常,现在出现一个奇怪的错误,而且我不知道如何解决它。尝试了所有类似问题的解决方案。 这是我的代码: 两条标记线都给了我相同的错误: 类型“ String.Index”不符合协议“ IntegerLiteralConvertible” 有人能帮我吗?还是Beta 4有漏洞?谢谢! 问题答案: 在Beta 4中,Swift的String.Index处理再次发生了变化- 现
问题内容: 尝试按照Apple文档(和教程化的)创建Launch Helper时,我似乎遇到了麻烦,原因是将Objective- C代码移植到Swift中…在此方面,谁的编译器再也不过分了案件。 该错误似乎始终是: 我尝试过在多个位置进行转换,以防万一我只是在处理一个多余的,古老的原语(由Obj- C或Core Foundation引入)而无济于事。 为了以防万一,我尝试投射响应: 产生错误: …
最后一点:如果这似乎与SO上的其他问题重复,我道歉。如前所述,我已经看了他们,但无法得到我想要的理解。
问题内容: 作为学习的练习,我将在Swift中重写我的验证库。 我有一个协议定义了各个规则的外观: 关联的类型定义要验证的输入的类型(例如,字符串)。它可以是显式的或通用的。 这是两个规则: 在其他地方,我有一个函数,用于验证带有s 集合的输入: 我以为这行得通,但是编译器不同意。 在下面的例子中,即使输入是一个字符串,的是一个字符串,并且Ş 是一个String … …我收到了非常有用的错误消息:
问题内容: 我有一个符合多种协议的Objective-C变量。 我将如何在Swift中代表这种类型? 问题答案: 这应该工作: 注意,必须快速使用NSObjectProtocol而不是NSObject。 以下是一些其他示例: 符合多种协议的对象数组: 具有符合多种协议的参数的功能: 对于3.1之前的Swift版本,请使用: