Skip to content

Commit

Permalink
Some cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
srdanrasic committed Oct 22, 2016
1 parent 7098a62 commit 8e47ad6
Show file tree
Hide file tree
Showing 14 changed files with 100 additions and 68 deletions.
2 changes: 1 addition & 1 deletion Playground.playground/Contents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import PlaygroundSupport
var p: Property! = Property(1)
weak var wp: Property<Int>? = p

Signal1<Double>.interval(1, queue: .main).map { $0 }.debug().bind(to: p)
Signal1<Double>.interval(1, queue: .main).map { $0 }.debug("test signal").bind(to: p)

DispatchQueue.main.after(when: 3.3) {
p = nil
Expand Down
4 changes: 4 additions & 0 deletions ReactiveKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
16F2F56D1D6D924B00B85896 /* SignalProtocol+Arities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16F2F56B1D6D924B00B85896 /* SignalProtocol+Arities.swift */; };
16F2F56E1D6D924B00B85896 /* SignalProtocol+Arities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16F2F56B1D6D924B00B85896 /* SignalProtocol+Arities.swift */; };
16F2F56F1D6D924B00B85896 /* SignalProtocol+Arities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16F2F56B1D6D924B00B85896 /* SignalProtocol+Arities.swift */; };
EC06A8711DBBF8C7006AEA81 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC06A86F1DBBF8A6006AEA81 /* ResultTests.swift */; };
EC6C0FC71DB4A78E00C3880B /* PropertyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC6C0FC51DB4A76A00C3880B /* PropertyTests.swift */; };
EC7A6F891D3CCF5B00F9EF4A /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7A6F881D3CCF5B00F9EF4A /* NoError.swift */; };
EC7A6F8A1D3CCF5B00F9EF4A /* NoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC7A6F881D3CCF5B00F9EF4A /* NoError.swift */; };
Expand Down Expand Up @@ -102,6 +103,7 @@
16C33B241BEFBA0100A0DBE0 /* ReactiveKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
16F2F5661D6D8A4500B85896 /* Lock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Lock.swift; path = Sources/Lock.swift; sourceTree = SOURCE_ROOT; };
16F2F56B1D6D924B00B85896 /* SignalProtocol+Arities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "SignalProtocol+Arities.swift"; path = "Sources/SignalProtocol+Arities.swift"; sourceTree = SOURCE_ROOT; };
EC06A86F1DBBF8A6006AEA81 /* ResultTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = "<group>"; };
EC6C0FC51DB4A76A00C3880B /* PropertyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyTests.swift; sourceTree = "<group>"; };
EC7A6F881D3CCF5B00F9EF4A /* NoError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NoError.swift; path = Sources/NoError.swift; sourceTree = SOURCE_ROOT; };
EC8A99DC1CABD9B50042A6AD /* Disposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Disposable.swift; path = Sources/Disposable.swift; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -224,6 +226,7 @@
ECD102FD1D89B2530086B6A1 /* Helpers.swift */,
ECD102FE1D89B2530086B6A1 /* SignalTests.swift */,
EC6C0FC51DB4A76A00C3880B /* PropertyTests.swift */,
EC06A86F1DBBF8A6006AEA81 /* ResultTests.swift */,
);
path = ReactiveKitTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -542,6 +545,7 @@
files = (
ECD102FF1D89B2530086B6A1 /* Helpers.swift in Sources */,
ECD103001D89B2530086B6A1 /* SignalTests.swift in Sources */,
EC06A8711DBBF8C7006AEA81 /* ResultTests.swift in Sources */,
EC6C0FC71DB4A78E00C3880B /* PropertyTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
4 changes: 2 additions & 2 deletions Sources/Bindable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ extension SignalProtocol where Error == NoError {
/// and return a disposable that can cancel binding.
@discardableResult
public func bind<B: BindableProtocol>(to bindable: B, context: @escaping ExecutionContext = createNonRecursiveContext()) -> Disposable where B.Element == Element {
return bindable.bind(signal: observeIn(context: context))
return bindable.bind(signal: observeIn(context))
}

/// Establish a one-way binding between the source and the bindable
/// and return a disposable that can cancel binding.
@discardableResult
public func bind<B: BindableProtocol>(to bindable: B, context: @escaping ExecutionContext = createNonRecursiveContext()) -> Disposable where B.Element: OptionalProtocol, B.Element.Wrapped == Element {
return map { B.Element($0) }.observeIn(context: context).bind(to: bindable)
return map { B.Element($0) }.observeIn(context).bind(to: bindable)
}
}

Expand Down
4 changes: 0 additions & 4 deletions Sources/Connectable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,13 @@
// THE SOFTWARE.
//

// MARK: - ConnectableSignalType

/// Represents a signal that is started by calling `connect` on it.
public protocol ConnectableSignalProtocol: SignalProtocol {

/// Start the signal.
func connect() -> Disposable
}

// MARK: - RawConnectableSignal

/// Makes a signal connectable through the given subject.
public final class ConnectableSignal<O: SignalProtocol>: ConnectableSignalProtocol {

Expand Down
6 changes: 3 additions & 3 deletions Sources/Disposable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public final class BlockDisposable: Disposable {
}

private var handler: (() -> ())?
private let lock = NSRecursiveLock(name: "ReactiveKit.BlockDisposable")
private let lock = NSRecursiveLock(name: "com.reactivekit.blockdisposable")

public init(_ handler: @escaping () -> ()) {
self.handler = handler
Expand Down Expand Up @@ -109,7 +109,7 @@ public final class CompositeDisposable: Disposable {

public private(set) var isDisposed: Bool = false
private var disposables: [Disposable] = []
private let lock = NSRecursiveLock(name: "ReactiveKit.CompositeDisposable")
private let lock = NSRecursiveLock(name: "com.reactivekit.compositedisposable")

public convenience init() {
self.init([])
Expand Down Expand Up @@ -188,7 +188,7 @@ public extension Disposable {
public final class SerialDisposable: Disposable {

public private(set) var isDisposed: Bool = false
private let lock = NSRecursiveLock(name: "ReactiveKit.SerialDisposable")
private let lock = NSRecursiveLock(name: "com.reactivekit.serialdisposable")

/// Will dispose other disposable immediately if self is already disposed.
public var otherDisposable: Disposable? {
Expand Down
4 changes: 3 additions & 1 deletion Sources/Observer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,18 @@ public protocol ObserverProtocol {
/// Type of elements being received.
associatedtype Element

/// Type of error that can be received.
associatedtype Error: Swift.Error

/// Sends given event to the observer.
/// Send the event to the observer.
func on(_ event: Event<Element, Error>)
}

/// Represents a type that receives events. Observer is just a convenience
/// wrapper around a closure that accepts an event.
public struct Observer<Element, Error: Swift.Error>: ObserverProtocol {

/// Underlying observer closure.
public let observer: (Event<Element, Error>) -> Void

/// Creates an observer that wraps given closure.
Expand Down
2 changes: 1 addition & 1 deletion Sources/Property.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class Property<Value>: PropertyProtocol, SubjectProtocol, BindableProtoco

private var _value: Value
private let subject = PublishSubject<Value, NoError>()
private let lock = NSRecursiveLock(name: "ReactiveKit.Property")
private let lock = NSRecursiveLock(name: "com.reactivekit.property")

public var disposeBag: DisposeBag {
return subject.disposeBag
Expand Down
8 changes: 4 additions & 4 deletions Sources/Result.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,21 @@ public enum Result<T, E: Swift.Error>: CustomStringConvertible {
case failure(E)

/// Constructs a result with a success value.
public init(value: T) {
public init(_ value: T) {
self = .success(value)
}

/// Constructs a result with an error.
public init(error: E) {
public init(_ error: E) {
self = .failure(error)
}

public var description: String {
switch self {
case let .success(value):
return ".Success(\(value))"
return ".success(\(value))"
case let .failure(error):
return ".Failure(\(error))"
return ".failure(\(error))"
}
}
}
Expand Down
12 changes: 5 additions & 7 deletions Sources/Signal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,21 @@

import Foundation

// MARK: - Signal

/// A Signal represents a stream of elements.
public struct Signal<Element, Error: Swift.Error>: SignalProtocol {

private let producer: (Observer<Element, Error>) -> Disposable
public typealias Producer = (Observer<Element, Error>) -> Disposable
private let producer: Producer

/// Create new signal given a producer closure.
public init(producer: @escaping (Observer<Element, Error>) -> Disposable) {
public init(producer: @escaping Producer) {
self.producer = producer
}

/// Register an observer that will receive events from the signal.
/// Register the observer that will receive events from the signal.
public func observe(with observer: @escaping (Event<Element, Error>) -> Void) -> Disposable {
let serialDisposable = SerialDisposable(otherDisposable: nil)
let lock = NSRecursiveLock(name: "com.ReactiveKit.Signal.observe")
let lock = NSRecursiveLock(name: "com.reactivekit.signal.observe")
var terminated = false
let observer = Observer<Element, Error> { event in
lock.atomic {
Expand All @@ -64,4 +63,3 @@ public struct Signal<Element, Error: Swift.Error>: SignalProtocol {

/// A convenience alias for non-failable signals.
public typealias Signal1<Element> = Signal<Element, NoError>

10 changes: 5 additions & 5 deletions Sources/SignalProtocol+Arities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@

// MARK: - Tuple functions

fileprivate func tuple<A, B>(a: A, b: B) -> (A, B) { return (a, b) }
fileprivate func tuple<A, B, C>(a: A, b: B, c: C) -> (A, B, C) { return (a, b, c) }
fileprivate func tuple<A, B, C, D>(a: A, b: B, c: C, d: D) -> (A, B, C, D) { return (a, b, c, d) }
fileprivate func tuple<A, B, C, D, E>(a: A, b: B, c: C, d: D, e: E) -> (A, B, C, D, E) { return (a, b, c, d, e) }
fileprivate func tuple<A, B, C, D, E, F>(a: A, b: B, c: C, d: D, e: E, f: F) -> (A, B, C, D, E, F) { return (a, b, c, d, e, f) }
private func tuple<A, B>(a: A, b: B) -> (A, B) { return (a, b) }
private func tuple<A, B, C>(a: A, b: B, c: C) -> (A, B, C) { return (a, b, c) }
private func tuple<A, B, C, D>(a: A, b: B, c: C, d: D) -> (A, B, C, D) { return (a, b, c, d) }
private func tuple<A, B, C, D, E>(a: A, b: B, c: C, d: D, e: E) -> (A, B, C, D, E) { return (a, b, c, d, e) }
private func tuple<A, B, C, D, E, F>(a: A, b: B, c: C, d: D, e: E, f: F) -> (A, B, C, D, E, F) { return (a, b, c, d, e, f) }

// MARK: Combine Latest

Expand Down
61 changes: 24 additions & 37 deletions Sources/SignalProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ public extension SignalProtocol {
case .failed(let error):
observer.completed()
if logging {
print("Operation at \(file):\(line) encountered an error: \(error)")
print("Signal at \(file):\(line) encountered an error: \(error)")
}
case .completed:
observer.completed()
Expand Down Expand Up @@ -699,27 +699,6 @@ extension SignalProtocol {
return serialDisposable
}
}

/// Filters (ignores) `.next` events that are generated recursively from an observer.
/// Applicable only with subjects.
public func filterRecursiveEvents() -> Signal<Element, Error> {
return Signal { observer in
var sending = false
return self.observe { event in
switch event {
case .next(let element):
guard !sending else { return }
sending = true
observer.next(element)
sending = false
case .failed(let error):
observer.failed(error)
case .completed:
observer.completed()
}
}
}
}

/// Delay signal events for `interval` time.
public func delay(interval: Double, on queue: DispatchQueue) -> Signal<Element, Error> {
Expand Down Expand Up @@ -758,23 +737,31 @@ extension SignalProtocol {
}
}

/// Use `doOn` to log various events.
public func debug(id: String = "Untitled Signal") -> Signal<Element, Error> {
/// Log various signal events. If title is not provided, source file and function names are printed instead.
public func debug(_ title: String? = nil, file: String = #file, function: String = #function, line: Int = #line) -> Signal<Element, Error> {
let prefix: String
if let title = title {
prefix = "[\(title)]"
} else {
let filename = file.components(separatedBy: "/").last ?? file
prefix = "[\(filename):\(function):\(line)]"
}

return doOn(next: { element in
print("\(id): Next(\(element))")
print("\(prefix) next(\(element))")
}, start: {
print("\(id): Start")
print("\(prefix) started")
}, failed: { error in
print("\(id): \(error)")
print("\(prefix) failed: \(error)")
}, completed: {
print("\(id): Completed")
print("\(prefix) completed")
}, disposed: {
print("\(id): Disposed")
print("\(prefix) disposed")
})
}

/// Set the execution context used to dispatch events (i.e. to run the observers).
public func observeIn(context: @escaping ExecutionContext) -> Signal<Element, Error> {
public func observeIn(_ context: @escaping ExecutionContext) -> Signal<Element, Error> {
return Signal { observer in
return self.observe { event in
context {
Expand All @@ -785,8 +772,8 @@ extension SignalProtocol {
}

/// Set the dispatch queue used to dispatch events (i.e. to run the observers).
public func observeOn(queue: DispatchQueue) -> Signal<Element, Error> {
return observeIn(context: queue.context)
public func observeOn(_ queue: DispatchQueue) -> Signal<Element, Error> {
return observeIn(queue.context)
}

/// Supress events while last event generated on other signal is `false`.
Expand Down Expand Up @@ -977,7 +964,7 @@ public extension SignalProtocol where Element: SignalProtocol, Element.Error ==
/// Flatten the signal by observing all inner signals and propagate events from each one as they come.
public func merge() -> Signal<InnerElement, Error> {
return Signal { observer in
let lock = NSRecursiveLock(name: "merge")
let lock = NSRecursiveLock(name: "com.reactivekit.merge")
let compositeDisposable = CompositeDisposable()
var numberOfOperations = 1 // 1 for outer signal

Expand Down Expand Up @@ -1023,7 +1010,7 @@ public extension SignalProtocol where Element: SignalProtocol, Element.Error ==
let serialDisposable = SerialDisposable(otherDisposable: nil)
let compositeDisposable = CompositeDisposable([serialDisposable])
var completions = (outer: false, inner: false)
let lock = NSRecursiveLock(name: "switchToLatest")
let lock = NSRecursiveLock(name: "com.reactivekit.switchtolatest")

compositeDisposable += self.observe { outerEvent in
switch outerEvent {
Expand Down Expand Up @@ -1067,7 +1054,7 @@ public extension SignalProtocol where Element: SignalProtocol, Element.Error ==
/// arrive, starting next observation only after previous one completes.
public func concat() -> Signal<InnerElement, Error> {
return Signal { observer in
let lock = NSRecursiveLock(name: "concat")
let lock = NSRecursiveLock(name: "com.reactivekit.concat")
let serialDisposable = SerialDisposable(otherDisposable: nil)
let compositeDisposable = CompositeDisposable([serialDisposable])
var completions = (outer: false, inner: true)
Expand Down Expand Up @@ -1134,7 +1121,7 @@ extension SignalProtocol {

fileprivate func _amb<O: SignalProtocol>(with other: O) -> Signal<Element, Error> where O.Element == Element, O.Error == Error {
return Signal { observer in
let lock = NSRecursiveLock(name: "amb")
let lock = NSRecursiveLock(name: "com.reactivekit.amb")
let disposable = (my: SerialDisposable(otherDisposable: nil), other: SerialDisposable(otherDisposable: nil))
var dispatching = (me: false, other: false)

Expand Down Expand Up @@ -1171,7 +1158,7 @@ extension SignalProtocol {

fileprivate func _combineLatest<O: SignalProtocol, U>(with other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
return Signal { observer in
let lock = NSRecursiveLock(name: "combineLatestWith")
let lock = NSRecursiveLock(name: "com.reactivekit.combinelatestwith")

var elements: (my: Element?, other: O.Element?)
var completions: (me: Bool, other: Bool) = (false, false)
Expand Down
6 changes: 3 additions & 3 deletions Sources/Subjects.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public protocol SubjectProtocol: SignalProtocol, ObserverProtocol {
/// A type that is both a signal and an observer.
public final class PublishSubject<Element, Error: Swift.Error>: ObserverRegister<(Event<Element, Error>) -> Void>, SubjectProtocol {

private let lock = NSRecursiveLock(name: "PublishSubject")
private let lock = NSRecursiveLock(name: "com.reactivekit.publishsubject")
private var terminated = false

public let disposeBag = DisposeBag()
Expand Down Expand Up @@ -69,7 +69,7 @@ public typealias PublishSubject1<Element> = PublishSubject<Element, NoError>
public final class ReplaySubject<Element, Error: Swift.Error>: ObserverRegister<(Event<Element, Error>) -> Void>, SubjectProtocol {

private var buffer: ArraySlice<Event<Element, Error>> = []
private let lock = NSRecursiveLock(name: "ReactiveKit.ReplaySubject")
private let lock = NSRecursiveLock(name: "com.reactivekit.replaysubject")

public let bufferSize: Int
public let disposeBag = DisposeBag()
Expand Down Expand Up @@ -111,7 +111,7 @@ internal class _ReplayOneSubject<Element, Error: Swift.Error>: ObserverRegister<

private var lastEvent: Event<Element, Error>? = nil
private var terminalEvent: Event<Element, Error>? = nil
private let lock = NSRecursiveLock(name: "ReplayOneSubject")
private let lock = NSRecursiveLock(name: "com.reactivekit.replayonesubject")

public override init() {
}
Expand Down
27 changes: 27 additions & 0 deletions Tests/ReactiveKitTests/ResultTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// ResultTests.swift
// ReactiveKit
//
// Created by Srdan Rasic on 22/10/2016.
// Copyright © 2016 Srdan Rasic. All rights reserved.
//

import XCTest
@testable import ReactiveKit

class ResultTests: XCTestCase {

func testSuccess() {
let result = Result<Int, TestError>(5)

XCTAssert(result.error == nil)
XCTAssert(result.value != nil && result.value! == 5)
}

func testFailured() {
let result = Result<Int, TestError>(.Error)

XCTAssert(result.error != nil && result.error! == .Error)
XCTAssert(result.value == nil)
}
}
Loading

0 comments on commit 8e47ad6

Please sign in to comment.