Skip to content
This repository was archived by the owner on May 26, 2020. It is now read-only.

Commit 560b4e3

Browse files
dmcrodriguesandersio
authored andcommitted
Add a producer to emit the current content followed by subsequent changes
1 parent b2832a6 commit 560b4e3

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed

Sources/ReactiveArray.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
22
import ReactiveSwift
3-
import enum Result.NoError
3+
import Result
44

55
// MARK: - Changeset
66

@@ -44,6 +44,21 @@ public final class ReactiveArray<Element> {
4444

4545
public let signal: Signal<Changeset<Element>, NoError>
4646

47+
public var producer: SignalProducer<Changeset<Element>, NoError> {
48+
return SignalProducer.attempt { [weak self] () -> Result<Changeset<Element>, NSError> in
49+
guard let `self` = self else { return .failure(NSError()) }
50+
51+
return .success(
52+
Changeset(insertions:
53+
self.changes(inserting: self[self.indices], at: Range(self.indices))
54+
)
55+
)
56+
57+
}
58+
.flatMapError { _ in .empty }
59+
.concat(SignalProducer(signal: signal))
60+
}
61+
4762
public var capacity: Int {
4863
return elements.capacity
4964
}

Tests/ReactiveArrayTests.swift

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,98 @@ class ReactiveArrayTests: XCTestCase {
506506
])
507507
)
508508
}
509+
510+
// MARK: - Producer tests
511+
512+
func test_producer() {
513+
514+
var changesets: [Changeset<Int>] = []
515+
516+
let array = ReactiveArray([1, 2, 3])
517+
518+
array.producer.startWithValues { changesets.append($0) }
519+
520+
array.append(4)
521+
522+
array.removeAll()
523+
524+
let expectedChangesets = [
525+
Changeset(
526+
insertions: [
527+
Insert(element: 1, at: 0),
528+
Insert(element: 2, at: 1),
529+
Insert(element: 3, at: 2)
530+
]),
531+
Changeset(
532+
insertions: [
533+
Insert(element: 4, at: 3)
534+
]),
535+
Changeset(
536+
deletions: [
537+
Remove(element: 1, at: 0),
538+
Remove(element: 2, at: 1),
539+
Remove(element: 3, at: 2),
540+
Remove(element: 4, at: 3)
541+
])
542+
]
543+
544+
zip(changesets, expectedChangesets).forEach { XCTAssertEqual($0, $1) }
545+
}
546+
547+
func test_producer_with_up_to_date_changes() {
548+
549+
var changesets: [Changeset<Int>] = []
550+
551+
let array = ReactiveArray([1, 2, 3])
552+
553+
let producer = array.producer
554+
555+
array.append(4)
556+
557+
producer.startWithValues { changesets.append($0) }
558+
559+
array.removeAll()
560+
561+
let expectedChangesets = [
562+
Changeset(
563+
insertions: [
564+
Insert(element: 1, at: 0),
565+
Insert(element: 2, at: 1),
566+
Insert(element: 3, at: 2),
567+
Insert(element: 4, at: 3)
568+
]),
569+
Changeset(
570+
deletions: [
571+
Remove(element: 1, at: 0),
572+
Remove(element: 2, at: 1),
573+
Remove(element: 3, at: 2),
574+
Remove(element: 4, at: 3)
575+
])
576+
]
577+
578+
zip(changesets, expectedChangesets).forEach { XCTAssertEqual($0, $1) }
579+
}
580+
581+
func test_producer_not_retaining_array() {
582+
583+
let completedExpectation = expectation(description: "Completed expectation")
584+
585+
var array = ReactiveArray([1, 2, 3]) as Optional
586+
587+
let producer = array!.producer
588+
589+
array = nil
590+
591+
producer
592+
.on(completed: {
593+
completedExpectation.fulfill()
594+
}, value: { _ in
595+
XCTAssertFalse(false, "Producer should not send any values") }
596+
)
597+
.start()
598+
599+
waitForExpectations(timeout: 1.0, handler: nil)
600+
}
509601
}
510602

511603
// MARK: - Helpers

0 commit comments

Comments
 (0)