Skip to content

Commit 4dec86f

Browse files
authored
Merge pull request #210 from DeclarativeHub/swift-5
ReactiveKit v3.10 (Swift 5)
2 parents a2ca6d8 + b86dae2 commit 4dec86f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3263
-2480
lines changed

.swift-version

Lines changed: 0 additions & 1 deletion
This file was deleted.

.travis.yml

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,26 @@
1-
language: objective-c
2-
osx_image: xcode9.3
1+
language: swift
2+
osx_image: xcode10.2
33

4-
# Travis is currently experiencing issues with Xcode builds: https://github.com/travis-ci/travis-ci/issues/6675#issuecomment-257964767
5-
# When this is resolved, remove the entire `before_install` block, as well as the `travis_retry` command below.
6-
before_install:
7-
- export IOS_SIMULATOR_UDID=`instruments -s devices | grep "iPhone 7 (11.3" | awk -F '[ ]' '{print $4}' | awk -F '[\[]' '{print $2}' | sed 's/.$//'`
8-
- echo $IOS_SIMULATOR_UDID
9-
- open -a "simulator" --args -CurrentDeviceUDID $IOS_SIMULATOR_UDID
4+
jobs:
5+
include:
6+
- stage: "Xcode"
7+
name: "Run tests on iOS"
8+
script: xcrun xcodebuild test -destination "platform=iOS Simulator,OS=12.2,name=iPhone X" -workspace "ReactiveKit.xcworkspace" -scheme "ReactiveKit-iOS"
9+
after_success: 'bash <(curl -s https://codecov.io/bash)'
10+
-
11+
name: "Build for macOS"
12+
script: xcrun xcodebuild build -destination "platform=macOS" -workspace "ReactiveKit.xcworkspace" -scheme "ReactiveKit-macOS"
13+
-
14+
name: "Build for tvOS"
15+
script: xcrun xcodebuild build -destination "platform=tvOS Simulator,OS=12.2,name=Apple TV 4K" -workspace "ReactiveKit.xcworkspace" -scheme "ReactiveKit-tvOS"
16+
-
17+
name: "Build for watchOS"
18+
script: xcrun xcodebuild build -destination "platform=watchOS Simulator,OS=5.2,name=Apple Watch Series 4 - 44mm" -workspace "ReactiveKit.xcworkspace" -scheme "ReactiveKit-watchOS"
1019

11-
install:
12-
- gem install xcpretty
20+
- stage: "Swift Package Manager"
21+
name: "Run Tests"
22+
script: swift test
1323

14-
script:
15-
- set -o pipefail && travis_retry xcodebuild -project ReactiveKit.xcodeproj -scheme ReactiveKit-iOS -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 7,OS=11.3' test | xcpretty
16-
- swift test
17-
18-
after_success:
19-
- bash <(curl -s https://codecov.io/bash)
24+
- stage: "CocoaPods"
25+
name: "Lint Podspec"
26+
script: pod lib lint

Package.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
// swift-tools-version:4.1
1+
// swift-tools-version:5.0
22
import PackageDescription
33

44
let package = Package(
5-
name: "ReactiveKit",
6-
products: [
7-
.library(name: "ReactiveKit", targets: ["ReactiveKit"])
8-
],
9-
targets: [
10-
.target(name: "ReactiveKit", path: "Sources"),
11-
.testTarget(name: "ReactiveKitTests", dependencies: ["ReactiveKit"])
12-
]
5+
name: "ReactiveKit",
6+
products: [
7+
.library(name: "ReactiveKit", targets: ["ReactiveKit"])
8+
],
9+
targets: [
10+
.target(name: "ReactiveKit", path: "Sources"),
11+
.testTarget(name: "ReactiveKitTests", dependencies: ["ReactiveKit"])
12+
]
1313
)

Playground.playground/Contents.swift

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//: [Previous](@previous)
2+
3+
import Foundation
4+
import ReactiveKit
5+
import PlaygroundSupport
6+
7+
PlaygroundPage.current.needsIndefiniteExecution = true
8+
9+
//: # Creating Signals
10+
//: Uncomment the `observe { ... }` line to explore the behaviour!
11+
12+
SafeSignal(just: "Jim")
13+
//.observe { print($0) }
14+
15+
SafeSignal(just: "Jim after 1 second", after: 1)
16+
//.observe { print($0) }
17+
18+
SafeSignal(sequence: [1, 2, 3])
19+
//.observe { print($0) }
20+
21+
SafeSignal(sequence: [1, 2, 3], interval: 1)
22+
//.observe { print($0) }
23+
24+
SafeSignal(sequence: 1..., interval: 1)
25+
//.observe { print($0) }
26+
27+
SafeSignal(performing: {
28+
(0...1000).reduce(0, +)
29+
})
30+
//.observe { print($0) }
31+
32+
Signal<String, NSError>(evaluating: {
33+
if let file = try? String(contentsOf: URL(fileURLWithPath: "list.txt")) {
34+
return .success(file)
35+
} else {
36+
return .failure(NSError(domain: "No such file", code: 0, userInfo: nil))
37+
}
38+
})
39+
//.observe { print($0) }
40+
41+
Signal(catching: {
42+
try String(contentsOf: URL(string: "https://pokeapi.co/api/v2/pokemon/ditto/")!, encoding: .utf8)
43+
})
44+
//.observe { print($0) }
45+
46+
Signal<Int, NSError> { observer in
47+
observer.next(1)
48+
observer.next(2)
49+
observer.completed()
50+
return BlockDisposable {
51+
print("disposed")
52+
}
53+
}
54+
//.observe { print($0) }
55+
56+
//: [Next](@next)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//: Playground - noun: a place where people can play
2+
3+
import ReactiveKit
4+
import PlaygroundSupport
5+
6+
//: Explore ReactiveKit here
7+
8+
enum MyError: Error {
9+
case unknown
10+
}
11+
12+
let a = Signal<Int, Error>(sequence: 0...4, interval: 0.5)
13+
let b = SafeSignal(sequence: 0...2, interval: 2)
14+
15+
b.concat(with: b)
16+
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//: [Previous](@previous)
2+
3+
import Foundation
4+
import ReactiveKit
5+
import PlaygroundSupport
6+
7+
PlaygroundPage.current.needsIndefiniteExecution = true
8+
9+
//: # Observing Signals
10+
11+
// Let's make a signal that simulates doing some work like loading of a large file.
12+
13+
let loadedFile = SafeSignal<String> { observer in
14+
print("Now loading file...")
15+
sleep(1)
16+
observer.completed(with: "first line\nsecond line")
17+
print("File loaded.")
18+
return NonDisposable.instance
19+
}
20+
21+
// If you run the playground up to this line, nothing will happen.
22+
// You console log will be empty. Even if we access the signal
23+
24+
_ = loadedFile
25+
26+
// still nothing happens. We could transform it using any of the operators
27+
28+
let numberOfLines = loadedFile
29+
.map { $0.split(separator: "\n").count }
30+
.map { "The file has \($0) lines." }
31+
32+
// and if you run the playground up to this line, nothing again.
33+
34+
// While this might be a bit confusing, it's the most powerful feature of signals and
35+
// functional-reactive programming. Signals allow us to express the logic without doing side effects.
36+
37+
// In our example, we've defined how to load a file and how to count number of lines
38+
// in the file, but we have not actually loaded the file nor counted the lines.
39+
40+
// To make side effects, to do the work, one has to observe the signal. It's the act
41+
// of observing that starts everything! Let's try observing the signal.
42+
43+
numberOfLines.observe { event in
44+
print(event)
45+
}
46+
47+
// Run the playground up to this line and watch the console log.
48+
// It's only now that the file gets loaded, signal transformed and events printed.
49+
50+
// This is very useful in real world development, but be aware of a caveat: observing the
51+
// signal again will repeat the side efects. In our example, the file will be loaded again.
52+
53+
numberOfLines.observe { event in
54+
print(event)
55+
}
56+
57+
// Bummer? No. Once you get more into functional-reactive parading you will see that
58+
// being able to express the logic without doing side effects outweights this inconvenience.
59+
// In order to share the sequence, all we need to do is apply `shareReplay` operator.
60+
61+
let sharedLoadedFile = loadedFile.shareReplay()
62+
63+
// The first time we observe the shared signal, it will load the file:
64+
65+
sharedLoadedFile.observe { print($0) }
66+
67+
// However, any subsequent observation will just use the shared sequence cached in the memory:
68+
69+
sharedLoadedFile.observe { print($0) }
70+
sharedLoadedFile.observe { print($0) }
71+
72+
// There are few convience methods for observing signals. When you are only interested into elements
73+
// of the signal, as opposed to events that contain element, you could just observe next events:
74+
75+
sharedLoadedFile.observeNext { fileContent in
76+
print(fileContent)
77+
}
78+
79+
// If you are interested only when the signal completes, then observe just the completed event:
80+
81+
sharedLoadedFile.observeCompleted {
82+
print("Done")
83+
}
84+
85+
// Some signals can fail with an error. When you are interested only in the failure, observe the failed event:
86+
87+
sharedLoadedFile.observeFailed { error in
88+
print("Failed with error", error) // Will not happen because our signal doesn't fail.
89+
}
90+
91+
//: [Next](@next)

0 commit comments

Comments
 (0)