到目前为止,我只能使用全局函数来实现这一点。我不确定这是否可能,但我希望编写一个通用类的扩展,希望能实现同样的目标。
下面是它使用 ReactiveCocoa 中的 SignalProducer 类的工作全局函数,但对于任何泛型类,其原理应该是相同的。
func ignoreNilValues <Value,Error> (producer: SignalProducer<Value?,Error>) -> SignalProducer<Value, Error> {
return producer.filter { return $0 != nil }.map { $0! }
}
更新:
我已经取得了进展,但仍然没有找到完整的解决方案
给定具有某些通用属性的任何类
class GenericClass<SomeType> {
var someProperty: [SomeType] = []
}
如何编写一个扩展来过滤任何可选值并使用 Wrapped 类型返回该值?
以下内容将过滤任何 nil 值,但仍将其作为可选类型返回。
protocol AnOptional {
var isNil: Bool {get}
}
extension Optional : AnOptional {
var isNil: Bool {
get {
guard let hasValue = self.map({ (value: Wrapped) -> Bool in
return true
}) else {
return true
}
return !hasValue
}
}
}
extension GenericClass where SomeType : AnOptional {
func filterNilValuesOfSomeProperty() -> [SomeType] {
return someProperty.filter({ (anOptional: AnOptional) -> Bool in
return !anOptional.isNil
})
}
}
可以看出
let aClass = GenericClass<Int?>()
aClass.someProperty = [3,5,6,nil,4,3,6, nil]
let x = aClass.someProperty
//x = [Some(3),Some(5),Some(6),nil,Some(4),Some(3),Some(6), nil]
let y = aClass.filterNilValuesOfSomeProperty()
//y = [Some(3),Some(5),Some(6),Some(4),Some(3),Some(6)]
是否可以编写一个返回包装类型的类扩展?在上面的示例中,它将是 [Int]
而不是 [Int?]
。
我重写了这个例子的全局函数解决方案。
func ignoreNilValues <Value> (aClass: GenericClass<Value?>) -> GenericClass<Value> {
let aNewClass = GenericClass<Value>()
aNewClass.someProperty = aClass.someProperty.filter({ (v: Value?) -> Bool in
v != nil
}).map { (oldValue: Value?) -> Value in
return oldValue!
}
return aNewClass
}
let z = ignoreNilValues(aClass).someProperty
//z = [3, 5, 6, 4, 3, 6]
最佳答案
“技巧”是定义一个所有选项都遵循的协议(protocol) (这是来自Creating an extension to filter nils from an Array in Swift 稍作简化;这个想法可以追溯到 this Apple Forum Thread ):
protocol OptionalType {
typealias Wrapped
func intoOptional() -> Wrapped?
}
extension Optional : OptionalType {
func intoOptional() -> Wrapped? {
return self
}
}
您可以在您的情况下将其用作:
class GenericClass<SomeType> {
var someProperty: [SomeType] = []
}
extension GenericClass where SomeType : OptionalType {
func filterNilValuesOfSomeProperty() -> [SomeType.Wrapped] {
return someProperty.flatMap { $0.intoOptional() }
}
}
它使用 SequenceType
中的 flatMap()
方法:
extension SequenceType {
/// Return an `Array` containing the non-nil results of mapping
/// `transform` over `self`.
///
/// - Complexity: O(*M* + *N*), where *M* is the length of `self`
/// and *N* is the length of the result.
@warn_unused_result
public func flatMap<T>(@noescape transform: (Self.Generator.Element) throws -> T?) rethrows -> [T]
}
示例:
let aClass = GenericClass<Int?>()
aClass.someProperty = [3,5,6,nil,4,3,6, nil]
let x = aClass.someProperty
print(x) // [Optional(3), Optional(5), Optional(6), nil, Optional(4), Optional(3), Optional(6), nil]
let y = aClass.filterNilValuesOfSomeProperty()
print(y) // [3, 5, 6, 4, 3, 6]
在 Swift 3 及更高版本中,协议(protocol)必须定义为
protocol OptionalType {
associatedtype Wrapped
func intoOptional() -> Wrapped?
}
关于swift - 我怎样才能编写一个函数,假设它是一个可选类型,那么它会在 swift 中解开通用属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34563161/