到目前为止,我只能使用全局函数实现此目的。我不确定是否可能,但我希望写一个泛型类的扩展,希望能达到同样的目的。
下面是使用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,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]
答案 0 :(得分:3)
&#34;技巧&#34;是定义所有选项符合的协议 (这来自Creating an extension to filter nils from an Array in Swift 略微简化;这个想法可以追溯到this Apple Forum Thread):
<style name="FullScreenTheme" parent="Theme.AppCompat.NoActionBar">
<!-- ... -->
</style>
您可以在案例中使用它:
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() }
}
}
中的flatMap()
方法:
SequenceType
示例:
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]
}
在 Swift 3 之后,协议必须定义为
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]
答案 1 :(得分:0)
我在我的应用中使用了此解决方案,创建了协议,并为Optional添加了扩展名。
protocol OptionalUnwrap {
associatedtype Wrapped
func unwrap(default defaultValue: @autoclosure () -> Wrapped) -> Wrapped
}
extension Optional: OptionalUnwrap {
func unwrap(default defaultValue: @autoclosure () -> Wrapped) -> Wrapped {
if let value = self {
return value
}
return defaultValue()
}
}
您可以像这样使用它,您必须提供一个默认值,因此,如果可选为nil,它将返回默认值。它适用于所有类型。
struct StructName {
var name: String
var age: Int
}
var structName3: StructName?
let unwrapped = structName3.unwrap(default: StructName(name: "", age: 2345))
print(unwrapped.age)
var version: Int?
version.unwrap(default: 5)
var subject: String? = "iOS"
subject.unwrap(default: "")