From fa436b8c91a5f636e990f10253bb1c5a643de45f Mon Sep 17 00:00:00 2001 From: Markus Chmelar Date: Sun, 20 Nov 2016 14:08:09 +0100 Subject: [PATCH] Add property.filter --- CHANGELOG.md | 2 ++ Sources/Property.swift | 14 ++++++++ Tests/ReactiveSwiftTests/PropertySpec.swift | 37 +++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fac85c5a..a852a1299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # master *Please add new entries at the top.* +1. New property operator: `filter` (#586, kudos to @iv-mexx) + # 3.1.0-rc.1 1. Fixed a scenario of downstream interruptions being dropped. (#577, kudos to @andersio) diff --git a/Sources/Property.swift b/Sources/Property.swift index 5e63222a7..ab93b49eb 100644 --- a/Sources/Property.swift +++ b/Sources/Property.swift @@ -113,6 +113,20 @@ extension PropertyProtocol { return lift { $0.map(keyPath) } } + /// Passes only the values of the property that pass the given predicate + /// to a new property. + /// + /// - parameters: + /// - initial: A `Property` always needs a `value`. The initial `value` is necessary in case the + /// predicate excludes the first (or all) `value`s of this `Property` + /// - predicate: A closure that accepts value and returns `Bool` denoting + /// whether current `value` of this `Property` has passed the test. + /// + /// - returns: A property that holds only values from `self` passing the given predicate. + public func filter(initial: Value, _ predicate: @escaping (Value) -> Bool) -> Property { + return Property(initial: initial, then: self.producer.filter(predicate)) + } + /// Combines the current value and the subsequent values of two `Property`s in /// the manner described by `Signal.combineLatest(with:)`. /// diff --git a/Tests/ReactiveSwiftTests/PropertySpec.swift b/Tests/ReactiveSwiftTests/PropertySpec.swift index 15c25c273..8ebd79565 100644 --- a/Tests/ReactiveSwiftTests/PropertySpec.swift +++ b/Tests/ReactiveSwiftTests/PropertySpec.swift @@ -750,6 +750,43 @@ class PropertySpec: QuickSpec { } } + describe("filter") { + it("should only receive values that pass the predicate") { + let property = MutableProperty(1) + let filteredProperty = property + .filter(initial: 0) { $0 > 0 } + expect(filteredProperty.value) == 1 + + property.value = 0 + expect(filteredProperty.value) == 1 + + property.value = 2 + expect(filteredProperty.value) == 2 + + property.value = -5 + expect(filteredProperty.value) == 2 + + property.value = 3 + expect(filteredProperty.value) == 3 + } + + it("should behave correctly if the filter excludes the initial value") { + let property = MutableProperty(1) + let filteredProperty = property + .filter(initial: 0) { $0 < 0 } + expect(filteredProperty.value) == 0 + + property.value = 2 + expect(filteredProperty.value) == 0 + + property.value = -2 + expect(filteredProperty.value) == -2 + + property.value = 0 + expect(filteredProperty.value) == -2 + } + } + describe("combineLatest") { var property: MutableProperty! var otherProperty: MutableProperty!