到目前为止,我只能使用全局函数实现这一目标.我不确定是否可能,但我希望写一个泛型类的扩展,希望能实现同样的目的.
下面是使用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值,但仍将其作为Optional类型返回.
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,nil] let x = aClass.someProperty //x = [Some(3),Some(5),Some(6),Some(4),Some(3),nil] let y = aClass.filterNilValuesOfSomeProperty() //y = [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,6]
“技巧”是定义所有选项符合的协议
(这是从 Creating an extension to filter nils from an Array in Swift开始
略微简化;这个想法可以追溯到 this Apple Forum Thread):
(这是从 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,nil] let x = aClass.someProperty print(x) // [Optional(3),Optional(5),Optional(6),Optional(4),Optional(3),nil] let y = aClass.filterNilValuesOfSomeProperty() print(y) // [3,6]
在Swift 3及更高版本中,协议必须定义为
protocol OptionalType { associatedtype Wrapped func intoOptional() -> Wrapped? }