Skip to content

Commit dee3e17

Browse files
authored
Merge pull request #7 from timsearle/ignoring-duplicates
Adding ignoringDuplicates Output transformer and the associated tests
2 parents 9f6f8bf + 806d827 commit dee3e17

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

Bind.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,7 @@
922922
isa = XCBuildConfiguration;
923923
buildSettings = {
924924
BUNDLE_LOADER = "$(TEST_HOST)";
925+
INFOPLIST_FILE = "";
925926
LD_RUNPATH_SEARCH_PATHS = (
926927
"$(inherited)",
927928
"@executable_path/Frameworks",
@@ -1078,6 +1079,7 @@
10781079
buildSettings = {
10791080
BUNDLE_LOADER = "$(TEST_HOST)";
10801081
ENABLE_BITCODE = YES;
1082+
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist";
10811083
LD_RUNPATH_SEARCH_PATHS = (
10821084
"$(inherited)",
10831085
"@executable_path/Frameworks",
@@ -1212,6 +1214,7 @@
12121214
isa = XCBuildConfiguration;
12131215
buildSettings = {
12141216
BUNDLE_LOADER = "$(TEST_HOST)";
1217+
INFOPLIST_FILE = "";
12151218
LD_RUNPATH_SEARCH_PATHS = (
12161219
"$(inherited)",
12171220
"@executable_path/Frameworks",
@@ -1288,6 +1291,7 @@
12881291
buildSettings = {
12891292
BUNDLE_LOADER = "$(TEST_HOST)";
12901293
ENABLE_BITCODE = YES;
1294+
INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist";
12911295
LD_RUNPATH_SEARCH_PATHS = (
12921296
"$(inherited)",
12931297
"@executable_path/Frameworks",

Sources/Bind/Output.swift

+27-1
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,11 @@ public class Output<Value>: Unbindable {
7171
/**
7272
`initial` allows the caller to specify an initial value to be populated into the Output through another mechanism
7373
other than the initialiser. If a value is already populated, this function just returns the receiver without doing
74-
anything
74+
anything.
7575
- Parameter value: The initial value
7676
- Returns: The same Output but with the initial value populated
77+
- Note: This is useful when needing to setup a functional chain with an initial value that does not
78+
trigger the chain to occur, e.g. setting the initial value at the end.
7779
*/
7880
public func initial(_ value: Value) -> Output<Value> {
7981
if self.value == nil {
@@ -241,3 +243,27 @@ public extension Output {
241243
return output
242244
}
243245
}
246+
247+
public extension Output where Value: Equatable {
248+
249+
/**
250+
Returns a new output that filters out any contiguous repeating `Value`.
251+
- Returns: A new `Output` which only emits a new value, when the new value is not equal to the previous value
252+
*/
253+
func ignoringDuplicates() -> Output<Value> {
254+
let output = Output<Value>()
255+
256+
var initial = self.value
257+
258+
let filtered = filter { value in
259+
value != initial
260+
}
261+
262+
filtered.bind { new in
263+
initial = self.value
264+
output.update(withValue: new)
265+
}
266+
267+
return filtered
268+
}
269+
}

Tests/BindTests/OutputTests.swift

+33
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,39 @@ final class OutputTests: XCTestCase {
333333
XCTAssertEqual(combined.latest, 10)
334334
}
335335

336+
func testIgnoringDuplicates() {
337+
let output = Output<Bool>()
338+
339+
var callCounter = 0
340+
var lastValue: Bool?
341+
342+
output
343+
.ignoringDuplicates()
344+
.bind { value in
345+
XCTAssertNotEqual(lastValue, value)
346+
lastValue = value
347+
callCounter += 1
348+
}
349+
350+
output.update(withValue: true)
351+
output.update(withValue: true)
352+
output.update(withValue: true)
353+
XCTAssertEqual(callCounter, 1)
354+
355+
output.update(withValue: false)
356+
XCTAssertEqual(callCounter, 2)
357+
358+
output.update(withValue: true)
359+
output.update(withValue: true)
360+
output.update(withValue: true)
361+
XCTAssertEqual(callCounter, 3)
362+
363+
output.update(withValue: false)
364+
output.update(withValue: false)
365+
output.update(withValue: false)
366+
XCTAssertEqual(callCounter, 4)
367+
}
368+
336369
func testDebug() {
337370
let printer = PrinterMock()
338371
let output1 = Output<Bool>(printer: printer)

0 commit comments

Comments
 (0)