├── .gitignore
├── .swiftlint.yml
├── App
├── .swiftlint.yml
├── CombineOperators.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── CombineOperators
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── icon1024.png
│ │ │ ├── icon_120-1.png
│ │ │ ├── icon_120.png
│ │ │ ├── icon_152.png
│ │ │ ├── icon_167.png
│ │ │ ├── icon_180.png
│ │ │ ├── icon_20.png
│ │ │ ├── icon_29.png
│ │ │ ├── icon_40-1.png
│ │ │ ├── icon_40-2.png
│ │ │ ├── icon_40.png
│ │ │ ├── icon_58-1.png
│ │ │ ├── icon_58.png
│ │ │ ├── icon_60.png
│ │ │ ├── icon_76.png
│ │ │ ├── icon_80-1.png
│ │ │ ├── icon_80.png
│ │ │ └── icon_87.png
│ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Combine Ops.entitlements
│ ├── Info.plist
│ └── SceneDelegate.swift
├── CombineOperatorsTests
│ ├── CombineOperatorsTests.swift
│ └── Info.plist
└── CombineOperatorsUITests
│ ├── CombineOperatorsUITests.swift
│ └── Info.plist
├── Docs
├── interactivecombine.gif
└── promo.png
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── CombineOperatorsCore
│ ├── CombineOperatorsCore.swift
│ ├── Models
│ ├── Operator.swift
│ ├── OperatorVariant.swift
│ └── Subject.swift
│ ├── OperatorScene
│ ├── Nodes
│ │ ├── BandNode.swift
│ │ ├── OldValueNode.swift
│ │ ├── OperatorNode.swift
│ │ ├── PublisherNode.swift
│ │ ├── SubjectNode.swift
│ │ ├── TimerNode.swift
│ │ └── ValueNode.swift
│ ├── OperatorScene.swift
│ └── TimeUpdatingScene.swift
│ ├── Resources
│ ├── Media.xcassets
│ │ ├── Color
│ │ │ ├── Contents.json
│ │ │ ├── countdownFill.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── countdownTrack.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── errorButton.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── errorButtonHighlighted.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── finishButton.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── finishButtonHighlighted.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── inputButton.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── inputButtonHighlighted.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── macNavBarTintColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── operatorFinished.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── operatorFinishedError.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── operatorOldValue.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── operatorValue.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── subjectOldValue.colorset
│ │ │ │ └── Contents.json
│ │ │ └── subjectValue.colorset
│ │ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ └── Shared
│ │ │ ├── Contents.json
│ │ │ ├── band_operator.imageset
│ │ │ ├── Contents.json
│ │ │ ├── band_operator.png
│ │ │ ├── band_operator@2x.png
│ │ │ └── band_operator@3x.png
│ │ │ ├── band_subject.imageset
│ │ │ ├── Contents.json
│ │ │ ├── band_subject.png
│ │ │ ├── band_subject@2x.png
│ │ │ └── band_subject@3x.png
│ │ │ ├── number_of_subscriptions.imageset
│ │ │ ├── Contents.json
│ │ │ └── number_of_subscriptions.pdf
│ │ │ ├── operator.imageset
│ │ │ ├── Contents.json
│ │ │ ├── operator.png
│ │ │ ├── operator@2x.png
│ │ │ └── operator@3x.png
│ │ │ ├── pipe_left.imageset
│ │ │ ├── Contents.json
│ │ │ ├── pipe_left.png
│ │ │ ├── pipe_left@2x.png
│ │ │ └── pipe_left@3x.png
│ │ │ ├── pipe_right.imageset
│ │ │ ├── Contents.json
│ │ │ ├── pipe_right.png
│ │ │ ├── pipe_right@2x.png
│ │ │ └── pipe_right@3x.png
│ │ │ ├── subject.imageset
│ │ │ ├── Contents.json
│ │ │ ├── subject.png
│ │ │ ├── subject@2x.png
│ │ │ └── subject@3x.png
│ │ │ ├── value_operator.imageset
│ │ │ ├── Contents.json
│ │ │ ├── value_operator.png
│ │ │ ├── value_operator@2x.png
│ │ │ └── value_operator@3x.png
│ │ │ ├── value_operator_old.imageset
│ │ │ ├── Contents.json
│ │ │ ├── value_operator_old.png
│ │ │ ├── value_operator_old@2x.png
│ │ │ └── value_operator_old@3x.png
│ │ │ ├── value_subject.imageset
│ │ │ ├── Contents.json
│ │ │ ├── value_subject.png
│ │ │ ├── value_subject@2x.png
│ │ │ └── value_subject@3x.png
│ │ │ └── value_subject_old.imageset
│ │ │ ├── Contents.json
│ │ │ ├── value_subject_old.png
│ │ │ ├── value_subject_old@2x.png
│ │ │ └── value_subject_old@3x.png
│ └── SwiftGen
│ │ └── Assets.swift
│ ├── ViewControllers
│ ├── BaseOperatorViewController.swift
│ ├── OperatorInfoViewController.swift
│ ├── OperatorViewControllers
│ │ ├── Collecting
│ │ │ ├── OperatorAllSatisfyViewController.swift
│ │ │ ├── OperatorContainsViewController.swift
│ │ │ ├── OperatorCountViewController.swift
│ │ │ ├── OperatorMaxViewController.swift
│ │ │ ├── OperatorMinViewController.swift
│ │ │ ├── OperatorOutputAtViewController.swift
│ │ │ └── OperatorReduceViewController.swift
│ │ ├── Combining
│ │ │ ├── OperatorAppendViewController.swift
│ │ │ ├── OperatorCombineLatestViewController.swift
│ │ │ ├── OperatorDropUntilOutputFromViewController.swift
│ │ │ ├── OperatorFlatMapViewController.swift
│ │ │ ├── OperatorMapAndSwitchToLatestViewController.swift
│ │ │ ├── OperatorMergeViewController.swift
│ │ │ ├── OperatorPrefixUntilOutputFromViewController.swift
│ │ │ ├── OperatorPrependViewController.swift
│ │ │ └── OperatorZipViewController.swift
│ │ ├── Error handling
│ │ │ ├── OperatorCatchErrorViewController.swift
│ │ │ ├── OperatorMapErrorViewController.swift
│ │ │ └── OperatorReplaceErrorViewController.swift
│ │ ├── Filtering
│ │ │ ├── OperatorCompactMapViewController.swift
│ │ │ ├── OperatorDropFirstViewController.swift
│ │ │ ├── OperatorDropWhileViewController.swift
│ │ │ ├── OperatorFilterViewController.swift
│ │ │ ├── OperatorFirstViewController.swift
│ │ │ ├── OperatorIgnoreOutputViewController.swift
│ │ │ ├── OperatorLastViewController.swift
│ │ │ ├── OperatorPrefixViewController.swift
│ │ │ └── OperatorRemoveDuplicatesViewController.swift
│ │ ├── Timing
│ │ │ ├── OperatorCollectByTimeViewController.swift
│ │ │ ├── OperatorDebounceViewController.swift
│ │ │ ├── OperatorDelayViewController.swift
│ │ │ ├── OperatorMeasureIntervalViewController.swift
│ │ │ ├── OperatorThrottleViewController.swift
│ │ │ └── OperatorTimeoutViewController.swift
│ │ └── Transforming
│ │ │ ├── OperatorCollectViewController.swift
│ │ │ ├── OperatorMapViewController.swift
│ │ │ ├── OperatorReplaceEmptyViewController.swift
│ │ │ ├── OperatorReplaceNilViewController.swift
│ │ │ └── OperatorScanViewController.swift
│ ├── OperatorsTableViewController.swift
│ └── SymbolsTableViewController.swift
│ └── Views
│ ├── InputButton.swift
│ └── SubjectView.swift
├── Tests
├── CombineOperatorsCoreTests
│ ├── CombineOperatorsCoreTests.swift
│ └── XCTestManifests.swift
└── LinuxMain.swift
└── swiftgen.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | # .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | disabled_rules:
2 | - trailing_whitespace
3 | - unused_setter_value
4 | - nesting
5 | - opening_brace
6 |
7 | opt_in_rules:
8 | - force_unwrapping
9 | - unavailable_function
10 |
11 | line_length: 200
12 |
13 | function_parameter_count: 8
14 |
15 | file_length: 500
16 |
17 | identifier_name:
18 | min_length: 1
19 | max_length: 50
20 |
21 | type_name:
22 | max_length:
23 | warning: 80
24 | error: 100
25 |
26 | type_body_length:
27 | warning: 400
28 | error: 600
29 |
--------------------------------------------------------------------------------
/App/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | disabled_rules:
2 | - trailing_whitespace
3 | - unused_setter_value
4 | - nesting
5 | - opening_brace
6 |
7 | opt_in_rules:
8 | - force_unwrapping
9 | - unavailable_function
10 |
11 | line_length: 200
12 |
13 | function_parameter_count: 8
14 |
15 | file_length: 500
16 |
17 | identifier_name:
18 | min_length: 1
19 | max_length: 50
20 |
21 | type_name:
22 | max_length:
23 | warning: 80
24 | error: 100
25 |
26 | type_body_length:
27 | warning: 400
28 | error: 600
29 |
--------------------------------------------------------------------------------
/App/CombineOperators.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/App/CombineOperators.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/App/CombineOperators/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // CombineOperators
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 |
28 | @UIApplicationMain
29 | class AppDelegate: UIResponder, UIApplicationDelegate {
30 |
31 | func application(
32 | _ application: UIApplication,
33 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
34 | ) -> Bool {
35 | // Override point for customization after application launch.
36 | return true
37 | }
38 |
39 | // MARK: UISceneSession Lifecycle
40 |
41 | func application(
42 | _ application: UIApplication,
43 | configurationForConnecting connectingSceneSession: UISceneSession,
44 | options: UIScene.ConnectionOptions
45 | ) -> UISceneConfiguration {
46 | // Called when a new scene session is being created.
47 | // Use this method to select a configuration to create the new scene with.
48 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "icon_40.png",
5 | "idiom" : "iphone",
6 | "scale" : "2x",
7 | "size" : "20x20"
8 | },
9 | {
10 | "filename" : "icon_60.png",
11 | "idiom" : "iphone",
12 | "scale" : "3x",
13 | "size" : "20x20"
14 | },
15 | {
16 | "filename" : "icon_58.png",
17 | "idiom" : "iphone",
18 | "scale" : "2x",
19 | "size" : "29x29"
20 | },
21 | {
22 | "filename" : "icon_87.png",
23 | "idiom" : "iphone",
24 | "scale" : "3x",
25 | "size" : "29x29"
26 | },
27 | {
28 | "filename" : "icon_80.png",
29 | "idiom" : "iphone",
30 | "scale" : "2x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "filename" : "icon_120.png",
35 | "idiom" : "iphone",
36 | "scale" : "3x",
37 | "size" : "40x40"
38 | },
39 | {
40 | "filename" : "icon_120-1.png",
41 | "idiom" : "iphone",
42 | "scale" : "2x",
43 | "size" : "60x60"
44 | },
45 | {
46 | "filename" : "icon_180.png",
47 | "idiom" : "iphone",
48 | "scale" : "3x",
49 | "size" : "60x60"
50 | },
51 | {
52 | "filename" : "icon_20.png",
53 | "idiom" : "ipad",
54 | "scale" : "1x",
55 | "size" : "20x20"
56 | },
57 | {
58 | "filename" : "icon_40-1.png",
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "20x20"
62 | },
63 | {
64 | "filename" : "icon_29.png",
65 | "idiom" : "ipad",
66 | "scale" : "1x",
67 | "size" : "29x29"
68 | },
69 | {
70 | "filename" : "icon_58-1.png",
71 | "idiom" : "ipad",
72 | "scale" : "2x",
73 | "size" : "29x29"
74 | },
75 | {
76 | "filename" : "icon_40-2.png",
77 | "idiom" : "ipad",
78 | "scale" : "1x",
79 | "size" : "40x40"
80 | },
81 | {
82 | "filename" : "icon_80-1.png",
83 | "idiom" : "ipad",
84 | "scale" : "2x",
85 | "size" : "40x40"
86 | },
87 | {
88 | "filename" : "icon_76.png",
89 | "idiom" : "ipad",
90 | "scale" : "1x",
91 | "size" : "76x76"
92 | },
93 | {
94 | "filename" : "icon_152.png",
95 | "idiom" : "ipad",
96 | "scale" : "2x",
97 | "size" : "76x76"
98 | },
99 | {
100 | "filename" : "icon_167.png",
101 | "idiom" : "ipad",
102 | "scale" : "2x",
103 | "size" : "83.5x83.5"
104 | },
105 | {
106 | "filename" : "icon1024.png",
107 | "idiom" : "ios-marketing",
108 | "scale" : "1x",
109 | "size" : "1024x1024"
110 | }
111 | ],
112 | "info" : {
113 | "author" : "xcode",
114 | "version" : 1
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon1024.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_120-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_120-1.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_120.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_152.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_167.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_180.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_20.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_29.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_40-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_40-1.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_40-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_40-2.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_40.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_58-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_58-1.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_58.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_60.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_76.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_80-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_80-1.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_80.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/App/CombineOperators/Assets.xcassets/AppIcon.appiconset/icon_87.png
--------------------------------------------------------------------------------
/App/CombineOperators/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/App/CombineOperators/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/App/CombineOperators/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/App/CombineOperators/Combine Ops.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.network.client
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/App/CombineOperators/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | 1
21 | LSApplicationCategoryType
22 | public.app-category.developer-tools
23 | LSRequiresIPhoneOS
24 |
25 | UIApplicationSceneManifest
26 |
27 | UIApplicationSupportsMultipleScenes
28 |
29 | UISceneConfigurations
30 |
31 | UIWindowSceneSessionRoleApplication
32 |
33 |
34 | UISceneConfigurationName
35 | Default Configuration
36 | UISceneDelegateClassName
37 | $(PRODUCT_MODULE_NAME).SceneDelegate
38 | UISceneStoryboardFile
39 | Main
40 |
41 |
42 |
43 |
44 | UILaunchStoryboardName
45 | LaunchScreen
46 | UIMainStoryboardFile
47 | Main
48 | UIRequiredDeviceCapabilities
49 |
50 | armv7
51 |
52 | UISupportedInterfaceOrientations
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationLandscapeLeft
56 | UIInterfaceOrientationLandscapeRight
57 |
58 | UISupportedInterfaceOrientations~ipad
59 |
60 | UIInterfaceOrientationPortrait
61 | UIInterfaceOrientationPortraitUpsideDown
62 | UIInterfaceOrientationLandscapeLeft
63 | UIInterfaceOrientationLandscapeRight
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/App/CombineOperators/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // CombineOperators
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import CombineOperatorsCore
28 |
29 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
30 |
31 | var window: UIWindow?
32 |
33 | func scene(
34 | _ scene: UIScene,
35 | willConnectTo session: UISceneSession,
36 | options connectionOptions: UIScene.ConnectionOptions
37 | ) {
38 |
39 | #if targetEnvironment(macCatalyst)
40 |
41 | guard let windowScene = (scene as? UIWindowScene) else { return }
42 |
43 | UINavigationBar.appearance().tintColor = Assets.macNavBarTintColor.color
44 |
45 | windowScene.title = "Combine Operators"
46 |
47 | let splitViewController = UISplitViewController()
48 | splitViewController.preferredDisplayMode = .allVisible
49 | splitViewController.presentsWithGesture = false
50 | splitViewController.primaryBackgroundStyle = .sidebar
51 |
52 | let navigationController = UINavigationController(rootViewController: OperatorsTableViewController(isCompact: false))
53 |
54 | splitViewController.viewControllers = [navigationController]
55 |
56 | window?.rootViewController = splitViewController
57 |
58 | #else
59 |
60 | let splitViewController = UISplitViewController(style: .doubleColumn)
61 | splitViewController.preferredDisplayMode = .twoDisplaceSecondary
62 | splitViewController.presentsWithGesture = false
63 | splitViewController.preferredSplitBehavior = .tile
64 |
65 | let operatorsTableViewController = OperatorsTableViewController(isCompact: false)
66 |
67 | splitViewController.setViewController(operatorsTableViewController, for: .primary)
68 |
69 | let compactOperatorsTableViewController = OperatorsTableViewController(isCompact: true)
70 | let navigationController = UINavigationController(rootViewController: compactOperatorsTableViewController)
71 | splitViewController.setViewController(navigationController, for: .compact)
72 |
73 | window?.rootViewController = splitViewController
74 |
75 | #endif
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/App/CombineOperatorsTests/CombineOperatorsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CombineOperatorsTests.swift
3 | // CombineOperatorsTests
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import XCTest
27 | @testable import CombineOperators
28 |
29 | class CombineOperatorsTests: XCTestCase {
30 |
31 | override func setUpWithError() throws {
32 | // Put setup code here. This method is called before the invocation of each test method in the class.
33 | }
34 |
35 | override func tearDownWithError() throws {
36 | // Put teardown code here. This method is called after the invocation of each test method in the class.
37 | }
38 |
39 | func testExample() throws {
40 | // This is an example of a functional test case.
41 | // Use XCTAssert and related functions to verify your tests produce the correct results.
42 | }
43 |
44 | func testPerformanceExample() throws {
45 | // This is an example of a performance test case.
46 | self.measure {
47 | // Put the code you want to measure the time of here.
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/App/CombineOperatorsTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/App/CombineOperatorsUITests/CombineOperatorsUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CombineOperatorsUITests.swift
3 | // CombineOperatorsUITests
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import XCTest
27 |
28 | class CombineOperatorsUITests: XCTestCase {
29 |
30 | override func setUpWithError() throws {
31 | // Put setup code here. This method is called before the invocation of each test method in the class.
32 |
33 | // In UI tests it is usually best to stop immediately when a failure occurs.
34 | continueAfterFailure = false
35 | }
36 |
37 | override func tearDownWithError() throws {
38 | // Put teardown code here. This method is called after the invocation of each test method in the class.
39 | }
40 |
41 | func testExample() throws {
42 | // UI tests must launch the application that they test.
43 | let app = XCUIApplication()
44 | app.launch()
45 |
46 | // Use recording to get started writing UI tests.
47 | // Use XCTAssert and related functions to verify your tests produce the correct results.
48 | }
49 |
50 | func testLaunchPerformance() throws {
51 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) {
52 | // This measures how long it takes to launch your application.
53 | measure(metrics: [XCTOSSignpostMetric.applicationLaunch]) {
54 | XCUIApplication().launch()
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/App/CombineOperatorsUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Docs/interactivecombine.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Docs/interactivecombine.gif
--------------------------------------------------------------------------------
/Docs/promo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Docs/promo.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 cocoatoucher
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "CombineOperatorsCore",
8 | platforms: [
9 | .iOS(.v14)
10 | ],
11 | products: [
12 | .library(name: "CombineOperatorsCore", targets: ["CombineOperatorsCore"])
13 | ],
14 | dependencies: [],
15 | targets: [
16 | .target(name: "CombineOperatorsCore"),
17 | .testTarget(name: "CombineOperatorsCoreTests", dependencies: ["CombineOperatorsCore"])
18 | ],
19 | swiftLanguageVersions: [.v5]
20 | )
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | # Combine Operators
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Combine Operators is an interactive tutorial/cheat sheet app that you can download on the iOS App Store. It lets you play with Combine framework publishers and can help you grasp basic concepts if you are a beginner or refresh your memory during your further journey with the framework.
19 |
20 | With Combine Operators you can
21 | - Interact directly with underlying publisher instances through an intuitive UI.
22 | - Observe how subjects and operators behave with different input sequences through helpful animations.
23 |
24 | There are plans to make Combine Operators support more advanced input values and subject/operator combinations. Stay tuned and contribute! 🙌
25 |
26 | *The app is not implemented using SwiftUI, but that is a future plan as well.
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/CombineOperatorsCore.swift:
--------------------------------------------------------------------------------
1 | struct CombineOperatorsCore {
2 | var text = "Hello, World!"
3 | }
4 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Models/Operator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Operator.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import Foundation
27 |
28 | struct Operator {
29 | let name: String
30 | let description: String?
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Models/Subject.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Subject.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import Foundation
27 | import Combine
28 |
29 | enum PublisherUpdate {
30 | case subscription
31 | case output(value: String?)
32 | case completion(isError: Bool)
33 | case cancel
34 | case request
35 | case subscriptionCount(Int)
36 | }
37 |
38 | class Subject {
39 | let title: String
40 | let publisher: PassthroughSubject
41 | let inputValues: [String?]
42 |
43 | var trackedPublisher: AnyPublisher?
44 |
45 | var isFinished: Bool = false
46 |
47 | var handleUpdate: ((PublisherUpdate) -> Void)?
48 |
49 | var numberOfSubcriptions: Int = 0 {
50 | didSet {
51 | handleUpdate?(.subscriptionCount(numberOfSubcriptions))
52 | }
53 | }
54 |
55 | internal init(
56 | title: String,
57 | inputValues: [String?]) {
58 | self.title = title
59 | let publisher = PassthroughSubject()
60 | self.publisher = publisher
61 | self.inputValues = inputValues
62 |
63 | self.trackedPublisher = publisher.handleEvents(
64 | receiveSubscription: { [weak self] _ in
65 | guard let self = self else { return }
66 | self.numberOfSubcriptions += 1
67 | self.handleUpdate?(.subscription)
68 | }, receiveOutput: { [weak self] value in
69 | guard let self = self else { return }
70 | self.handleUpdate?(.output(value: value))
71 | }, receiveCompletion: { [weak self] completion in
72 | guard let self = self else { return }
73 | self.numberOfSubcriptions = 0
74 | switch completion {
75 | case .failure:
76 | self.handleUpdate?(.completion(isError: true))
77 | case .finished:
78 | self.handleUpdate?(.completion(isError: false))
79 | }
80 | }, receiveCancel: { [weak self] in
81 | guard let self = self else { return }
82 | self.numberOfSubcriptions = 0
83 | self.handleUpdate?(.cancel)
84 | }, receiveRequest: { [weak self] _ in
85 | guard let self = self else { return }
86 | self.handleUpdate?(.request)
87 | }
88 | )
89 | .eraseToAnyPublisher()
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/OperatorScene/Nodes/BandNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BandNode.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import SpriteKit
27 |
28 | class BandNode: SKSpriteNode {
29 |
30 | init(isOperator: Bool = false) {
31 | super.init(texture: nil, color: .gray, size: CGSize(width: 32, height: 200))
32 |
33 | name = "band"
34 |
35 | if isOperator {
36 | texture = SKTexture(image: Assets.bandOperator.image)
37 | } else {
38 | texture = SKTexture(image: Assets.bandSubject.image)
39 | }
40 | }
41 |
42 | @available(*, unavailable)
43 | required init?(coder aDecoder: NSCoder) {
44 | fatalError("init(coder:) has not been implemented")
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/OperatorScene/Nodes/OldValueNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OldValueNode.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import SpriteKit
27 |
28 | class OldValueNode: SKSpriteNode {
29 |
30 | let value: String?
31 |
32 | init(value: String?, isOperator: Bool = false) {
33 | self.value = value
34 | let color = isOperator ? Assets.operatorOldValue.color : Assets.subjectOldValue.color
35 | super.init(texture: nil, color: color, size: CGSize(width: 32, height: 24))
36 |
37 | name = "oldValue"
38 |
39 | setupNodes()
40 | }
41 |
42 | @available(*, unavailable)
43 | required init?(coder aDecoder: NSCoder) {
44 | fatalError("init(coder:) has not been implemented")
45 | }
46 |
47 | // MARK: - Private
48 |
49 | private lazy var labelNode: SKLabelNode = {
50 | let node = SKLabelNode()
51 | if value?.hasPrefix("finished-err") == true {
52 | if value?.hasSuffix("x") == true {
53 | node.text = "☠️ error"
54 | } else {
55 | node.text = "error"
56 | }
57 | } else {
58 | node.text = value
59 | }
60 | node.fontSize = 12.0
61 | node.fontName = UIFont.boldSystemFont(ofSize: 12.0).familyName
62 | node.fontColor = UIColor.white
63 | node.horizontalAlignmentMode = .center
64 | node.verticalAlignmentMode = .center
65 | return node
66 | }()
67 |
68 | private func setupNodes() {
69 | if value?.hasPrefix("finished") == true {
70 | if value?.hasSuffix("err") == true || value?.hasSuffix("err-x") == true {
71 | color = Assets.operatorFinishedError.color
72 | } else {
73 | color = Assets.operatorFinished.color
74 | }
75 | }
76 |
77 | addChild(labelNode)
78 |
79 | let labelWidth = labelNode.calculateAccumulatedFrame().size.width
80 | let width = max(labelWidth + 10, 32)
81 | size.width = width
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/OperatorScene/Nodes/ValueNode.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ValueNode.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import SpriteKit
27 |
28 | class ValueNode: SKSpriteNode {
29 |
30 | let value: String
31 | var isRemoved: Bool = false
32 |
33 | init(value: String, isOperator: Bool = false) {
34 | self.value = value
35 | let color = isOperator ? Assets.operatorValue.color : Assets.subjectValue.color
36 | super.init(texture: nil, color: color, size: CGSize(width: 50, height: 50))
37 |
38 | name = "value"
39 |
40 | setupNodes()
41 | }
42 |
43 | @available(*, unavailable)
44 | required init?(coder aDecoder: NSCoder) {
45 | fatalError("init(coder:) has not been implemented")
46 | }
47 |
48 | // MARK: - Private
49 |
50 | private lazy var labelNode: SKLabelNode = {
51 | let node = SKLabelNode()
52 | node.fontSize = 16.0
53 | node.fontName = UIFont.boldSystemFont(ofSize: 16.0).familyName
54 | node.fontColor = UIColor.white
55 | node.horizontalAlignmentMode = .center
56 | node.verticalAlignmentMode = .center
57 | return node
58 | }()
59 |
60 | private func setupNodes() {
61 | if value.hasPrefix("finished") == true {
62 | if value.hasSuffix("err") || value.hasSuffix("err-x") {
63 | color = Assets.operatorFinishedError.color
64 | } else {
65 | color = Assets.operatorFinished.color
66 | }
67 | }
68 |
69 | addChild(labelNode)
70 |
71 | if value.hasPrefix("finished-err") == true {
72 | if value.hasSuffix("x") == true {
73 | labelNode.text = "☠️ error"
74 | } else {
75 | labelNode.text = "error"
76 | }
77 | } else {
78 | labelNode.text = value
79 | }
80 |
81 | let labelWidth = labelNode.calculateAccumulatedFrame().size.width
82 | let width = max(labelWidth + 10, 50)
83 | size.width = width
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/OperatorScene/TimeUpdatingScene.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TimeUpdatingScene.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import SpriteKit
27 |
28 | class TimeUpdatingScene: SKScene {
29 |
30 | private(set) var currentTime: TimeInterval = 0
31 | private(set) var lastUpdateTime: TimeInterval = 0
32 | private(set) var lastDelta: TimeInterval = 0
33 |
34 | override func update(_ currentTime: TimeInterval) {
35 | self.currentTime = currentTime
36 | if lastUpdateTime == 0 {
37 | lastUpdateTime = currentTime
38 | }
39 | lastDelta = currentTime - lastUpdateTime
40 | }
41 |
42 | override func didFinishUpdate() {
43 | lastUpdateTime = currentTime
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/countdownFill.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.894",
9 | "green" : "0.475",
10 | "red" : "0.027"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/countdownTrack.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.776",
9 | "green" : "0.953",
10 | "red" : "0.937"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/errorButton.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x33",
9 | "green" : "0x56",
10 | "red" : "0xFF"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/errorButtonHighlighted.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.000",
9 | "green" : "0.184",
10 | "red" : "1.000"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/finishButton.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x8A",
9 | "green" : "0xC9",
10 | "red" : "0x24"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/finishButtonHighlighted.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x6B",
9 | "green" : "0x9C",
10 | "red" : "0x1C"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/inputButton.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.894",
9 | "green" : "0.659",
10 | "red" : "0.937"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/inputButtonHighlighted.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.925",
9 | "green" : "0.502",
10 | "red" : "1.000"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/macNavBarTintColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "display-p3",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.449",
9 | "green" : "0.449",
10 | "red" : "0.449"
11 | }
12 | },
13 | "idiom" : "universal"
14 | },
15 | {
16 | "appearances" : [
17 | {
18 | "appearance" : "luminosity",
19 | "value" : "dark"
20 | }
21 | ],
22 | "color" : {
23 | "color-space" : "srgb",
24 | "components" : {
25 | "alpha" : "1.000",
26 | "blue" : "1.000",
27 | "green" : "1.000",
28 | "red" : "1.000"
29 | }
30 | },
31 | "idiom" : "universal"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/operatorFinished.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x8A",
9 | "green" : "0xC9",
10 | "red" : "0x24"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/operatorFinishedError.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0x33",
9 | "green" : "0x56",
10 | "red" : "0xFF"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/operatorOldValue.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.188",
9 | "green" : "0.145",
10 | "red" : "0.173"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/operatorValue.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.392",
9 | "green" : "0.220",
10 | "red" : "0.329"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/subjectOldValue.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.588",
9 | "green" : "0.486",
10 | "red" : "0.373"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Color/subjectValue.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "color" : {
5 | "color-space" : "srgb",
6 | "components" : {
7 | "alpha" : "1.000",
8 | "blue" : "0.894",
9 | "green" : "0.475",
10 | "red" : "0.027"
11 | }
12 | },
13 | "idiom" : "universal"
14 | }
15 | ],
16 | "info" : {
17 | "author" : "xcode",
18 | "version" : 1
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_operator.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "band_operator.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "band_operator@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "band_operator@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_operator.imageset/band_operator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_operator.imageset/band_operator.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_operator.imageset/band_operator@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_operator.imageset/band_operator@2x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_operator.imageset/band_operator@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_operator.imageset/band_operator@3x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_subject.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "band_subject.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "band_subject@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "band_subject@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_subject.imageset/band_subject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_subject.imageset/band_subject.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_subject.imageset/band_subject@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_subject.imageset/band_subject@2x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_subject.imageset/band_subject@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/band_subject.imageset/band_subject@3x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/number_of_subscriptions.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "number_of_subscriptions.pdf",
5 | "idiom" : "universal"
6 | }
7 | ],
8 | "info" : {
9 | "author" : "xcode",
10 | "version" : 1
11 | },
12 | "properties" : {
13 | "preserves-vector-representation" : true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/number_of_subscriptions.imageset/number_of_subscriptions.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/number_of_subscriptions.imageset/number_of_subscriptions.pdf
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/operator.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "operator.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "operator@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "operator@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/operator.imageset/operator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/operator.imageset/operator.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/operator.imageset/operator@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/operator.imageset/operator@2x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/operator.imageset/operator@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/operator.imageset/operator@3x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_left.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "pipe_left.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "pipe_left@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "pipe_left@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_left.imageset/pipe_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_left.imageset/pipe_left.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_left.imageset/pipe_left@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_left.imageset/pipe_left@2x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_left.imageset/pipe_left@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_left.imageset/pipe_left@3x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_right.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "pipe_right.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "pipe_right@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "pipe_right@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_right.imageset/pipe_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_right.imageset/pipe_right.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_right.imageset/pipe_right@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_right.imageset/pipe_right@2x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_right.imageset/pipe_right@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/pipe_right.imageset/pipe_right@3x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/subject.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "subject.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "subject@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "subject@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/subject.imageset/subject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/subject.imageset/subject.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/subject.imageset/subject@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/subject.imageset/subject@2x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/subject.imageset/subject@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/subject.imageset/subject@3x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "value_operator.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "value_operator@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "value_operator@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator.imageset/value_operator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator.imageset/value_operator.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator.imageset/value_operator@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator.imageset/value_operator@2x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator.imageset/value_operator@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator.imageset/value_operator@3x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator_old.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "value_operator_old.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "value_operator_old@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "value_operator_old@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator_old.imageset/value_operator_old.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator_old.imageset/value_operator_old.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator_old.imageset/value_operator_old@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator_old.imageset/value_operator_old@2x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator_old.imageset/value_operator_old@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_operator_old.imageset/value_operator_old@3x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "value_subject.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "value_subject@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "value_subject@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject.imageset/value_subject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject.imageset/value_subject.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject.imageset/value_subject@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject.imageset/value_subject@2x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject.imageset/value_subject@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject.imageset/value_subject@3x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject_old.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "value_subject_old.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "value_subject_old@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "value_subject_old@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject_old.imageset/value_subject_old.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject_old.imageset/value_subject_old.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject_old.imageset/value_subject_old@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject_old.imageset/value_subject_old@2x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject_old.imageset/value_subject_old@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocoatoucher/CombineOperators/68b1f4d96a264472e0c3a3dfa40134e1dfb68d69/Sources/CombineOperatorsCore/Resources/Media.xcassets/Shared/value_subject_old.imageset/value_subject_old@3x.png
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Collecting/OperatorAllSatisfyViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorAllSatisfyViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorAllSatisfyViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "allSatisfy", description: "value % 2 = 0")]
33 |
34 | operatorInfo = "Publishes a single Boolean value that indicates whether all received elements pass a given predicate."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let allSatisfy = subject
40 | .allSatisfy { value -> Bool in
41 | return Int(value) % 2 == 0
42 | }
43 |
44 | allSatisfy
45 | .sink(
46 | receiveValue: { value in
47 | display("\\(value)"))
48 | }
49 | )
50 | """
51 | }
52 |
53 | override func setupBindings() {
54 | let subject1 = Subject(
55 | title: "Subject",
56 | inputValues: ["2", "3", nil]
57 | )
58 |
59 | subjects = [subject1]
60 |
61 | let last = subject1.trackedPublisher!
62 | .allSatisfy { value -> Bool in
63 | guard
64 | let value = value,
65 | let valueInt = Int(value)
66 | else {
67 | return false
68 | }
69 | return valueInt % 2 == 0
70 | }
71 |
72 | subscription = last
73 | .handleEvents(
74 | receiveSubscription: { [weak self] _ in
75 | guard let self = self else { return }
76 | self.updateOperator(.subscription)
77 | }, receiveCancel: { [weak self] in
78 | guard let self = self else { return }
79 | self.updateOperator(.cancel)
80 | }, receiveRequest: { [weak self] _ in
81 | guard let self = self else { return }
82 | self.updateOperator(.request)
83 | }
84 | )
85 | .sink(
86 | receiveCompletion: { [weak self] completion in
87 | guard let self = self else { return }
88 | self.setCompletionFromOperator(completion: completion)
89 | }, receiveValue: { [weak self] value in
90 | guard let self = self else { return }
91 | self.setValueFromOperator(value: "\(value)")
92 | }
93 | )
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Collecting/OperatorContainsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorContainsViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorContainsViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "contains", description: "🌟")]
33 |
34 | operatorInfo = "Publishes a Boolean value upon receiving an element equal to the argument."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let contains = subject
40 | .contains("🌟")
41 |
42 | contains
43 | .sink(
44 | receiveValue: { value in
45 | display("\\(value)"))
46 | }
47 | )
48 | """
49 | }
50 |
51 | override func setupBindings() {
52 | let subject1 = Subject(
53 | title: "Subject",
54 | inputValues: ["🌟", "✅", nil]
55 | )
56 |
57 | subjects = [subject1]
58 |
59 | let last = subject1.trackedPublisher!.contains("🌟")
60 |
61 | subscription = last
62 | .handleEvents(
63 | receiveSubscription: { [weak self] _ in
64 | guard let self = self else { return }
65 | self.updateOperator(.subscription)
66 | }, receiveCancel: { [weak self] in
67 | guard let self = self else { return }
68 | self.updateOperator(.cancel)
69 | }, receiveRequest: { [weak self] _ in
70 | guard let self = self else { return }
71 | self.updateOperator(.request)
72 | }
73 | )
74 | .sink(
75 | receiveCompletion: { [weak self] completion in
76 | guard let self = self else { return }
77 | self.setCompletionFromOperator(completion: completion)
78 | }, receiveValue: { [weak self] value in
79 | guard let self = self else { return }
80 | self.setValueFromOperator(value: "\(value)")
81 | }
82 | )
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Collecting/OperatorCountViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorCountViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorCountViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "count", description: nil)]
33 |
34 | operatorInfo = "Publishes the number of elements received from the upstream publisher."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let count = subject.count()
40 |
41 | count
42 | .sink(
43 | receiveValue: { value in
44 | display("\\(value)"))
45 | }
46 | )
47 | """
48 | }
49 |
50 | override func setupBindings() {
51 | let subject1 = Subject(
52 | title: "Subject",
53 | inputValues: ["🌟", "✅", nil]
54 | )
55 |
56 | subjects = [subject1]
57 |
58 | let count = subject1.trackedPublisher!.count()
59 |
60 | subscription = count
61 | .handleEvents(
62 | receiveSubscription: { [weak self] _ in
63 | guard let self = self else { return }
64 | self.updateOperator(.subscription)
65 | }, receiveCancel: { [weak self] in
66 | guard let self = self else { return }
67 | self.updateOperator(.cancel)
68 | }, receiveRequest: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.request)
71 | }
72 | )
73 | .sink(
74 | receiveCompletion: { [weak self] completion in
75 | guard let self = self else { return }
76 | self.setCompletionFromOperator(completion: completion)
77 | }, receiveValue: { [weak self] value in
78 | guard let self = self else { return }
79 | self.setValueFromOperator(value: "\(value)")
80 | }
81 | )
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Collecting/OperatorMinViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorMinViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorMinViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "min", description: nil)]
33 |
34 | operatorInfo = "Publishes the minimum value received from the upstream publisher, after it finishes."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let min = subject
40 | .min { left, right -> Bool in
41 | return Int(left) < Int(right)
42 | }
43 |
44 | min
45 | .sink(
46 | receiveValue: { value in
47 | display(value)
48 | }
49 | )
50 | """
51 | }
52 |
53 | override func setupBindings() {
54 | let subject1 = Subject(
55 | title: "Subject",
56 | inputValues: ["3", "5", nil]
57 | )
58 |
59 | subjects = [subject1]
60 |
61 | let last = subject1.trackedPublisher!.min { left, right -> Bool in
62 | guard let left = left, let leftInt = Int(left) else {
63 | return false
64 | }
65 | guard let right = right, let rightInt = Int(right) else {
66 | return false
67 | }
68 | return Int(leftInt) < Int(rightInt)
69 | }
70 |
71 | subscription = last
72 | .handleEvents(
73 | receiveSubscription: { [weak self] _ in
74 | guard let self = self else { return }
75 | self.updateOperator(.subscription)
76 | }, receiveCancel: { [weak self] in
77 | guard let self = self else { return }
78 | self.updateOperator(.cancel)
79 | }, receiveRequest: { [weak self] _ in
80 | guard let self = self else { return }
81 | self.updateOperator(.request)
82 | }
83 | )
84 | .sink(
85 | receiveCompletion: { [weak self] completion in
86 | guard let self = self else { return }
87 | self.setCompletionFromOperator(completion: completion)
88 | }, receiveValue: { [weak self] value in
89 | guard let self = self else { return }
90 | self.setValueFromOperator(value: value)
91 | }
92 | )
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Collecting/OperatorOutputAtViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorOutputAtViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorOutputAtViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "outputAt", description: "index 1")]
33 |
34 | operatorInfo = "Publishes a specific element, indicated by its index in the sequence of published elements."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let outputAt = subject
40 | .output(at: 1)
41 |
42 | outputAt
43 | .sink(
44 | receiveValue: { value in
45 | display(value ?? "none")
46 | }
47 | )
48 | """
49 | }
50 |
51 | override func setupBindings() {
52 | let subject1 = Subject(
53 | title: "Subject",
54 | inputValues: ["🌟", "✅", nil]
55 | )
56 |
57 | subjects = [subject1]
58 |
59 | let outputAt = subject1.trackedPublisher!.output(at: 1)
60 |
61 | subscription = outputAt
62 | .handleEvents(
63 | receiveSubscription: { [weak self] _ in
64 | guard let self = self else { return }
65 | self.updateOperator(.subscription)
66 | }, receiveCancel: { [weak self] in
67 | guard let self = self else { return }
68 | self.updateOperator(.cancel)
69 | }, receiveRequest: { [weak self] _ in
70 | guard let self = self else { return }
71 | self.updateOperator(.request)
72 | }
73 | )
74 | .sink(
75 | receiveCompletion: { [weak self] completion in
76 | guard let self = self else { return }
77 | self.setCompletionFromOperator(completion: completion)
78 | }, receiveValue: { [weak self] value in
79 | guard let self = self else { return }
80 | self.setValueFromOperator(value: value ?? "none")
81 | }
82 | )
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Collecting/OperatorReduceViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorReduceViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorReduceViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "reduce", description: "➡️ + values")]
33 |
34 | operatorInfo = "Applies a closure that collects each element of a stream and publishes a final result upon completion."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let reduce = subject
40 | .reduce("➡️") { reduced, value -> String? in
41 | return (reduced ?? "") + (value ?? "nil")
42 | }
43 |
44 | reduce
45 | .sink(
46 | receiveValue: { value in
47 | display(value)
48 | }
49 | )
50 | """
51 | }
52 |
53 | override func setupBindings() {
54 |
55 | let subject1 = Subject(
56 | title: "Subject",
57 | inputValues: ["🌟", "✅", nil]
58 | )
59 |
60 | subjects = [subject1]
61 |
62 | let reduce = subject1.trackedPublisher!
63 | .reduce("➡️") { reduced, value -> String? in
64 | return (reduced ?? "") + (value ?? "nil")
65 | }
66 |
67 | subscription = reduce
68 | .handleEvents(
69 | receiveSubscription: { [weak self] _ in
70 | guard let self = self else { return }
71 | self.updateOperator(.subscription)
72 | }, receiveCancel: { [weak self] in
73 | guard let self = self else { return }
74 | self.updateOperator(.cancel)
75 | }, receiveRequest: { [weak self] _ in
76 | guard let self = self else { return }
77 | self.updateOperator(.request)
78 | }
79 | )
80 | .sink(
81 | receiveCompletion: { [weak self] completion in
82 | guard let self = self else { return }
83 | self.setCompletionFromOperator(completion: completion)
84 | }, receiveValue: { [weak self] value in
85 | guard let self = self else { return }
86 | self.setValueFromOperator(value: value)
87 | }
88 | )
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Combining/OperatorAppendViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorAppendViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorAppendViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "append", description: "S2 -> S1")]
33 |
34 | operatorInfo = "Appends a publisher’s output with the elements emitted by the given publisher."
35 |
36 | operatorCode = """
37 | let subject1 = PassthroughSubject()
38 | let subject2 = PassthroughSubject()
39 |
40 | let append = subject1
41 | .append(subject2)
42 |
43 | append
44 | .sink(
45 | receiveValue: { value in
46 | display(value)
47 | }
48 | )
49 | """
50 | }
51 |
52 | override func setupBindings() {
53 | let subject1 = Subject(
54 | title: "Subject 1",
55 | inputValues: ["🌟", "✅", nil]
56 | )
57 |
58 | let subject2 = Subject(
59 | title: "Subject 2",
60 | inputValues: ["😎", "😱", nil]
61 | )
62 |
63 | subjects = [subject1, subject2]
64 |
65 | let append = subject1.trackedPublisher!
66 | .append(subject2.trackedPublisher!)
67 |
68 | subscription = append
69 | .handleEvents(
70 | receiveSubscription: { [weak self] _ in
71 | guard let self = self else { return }
72 | self.updateOperator(.subscription)
73 | }, receiveCancel: { [weak self] in
74 | guard let self = self else { return }
75 | self.updateOperator(.cancel)
76 | }, receiveRequest: { [weak self] _ in
77 | guard let self = self else { return }
78 | self.updateOperator(.request)
79 | }
80 | )
81 | .sink(
82 | receiveCompletion: { [weak self] completion in
83 | guard let self = self else { return }
84 | self.setCompletionFromOperator(completion: completion)
85 | }, receiveValue: { [weak self] value in
86 | guard let self = self else { return }
87 | self.setValueFromOperator(value: value)
88 | }
89 | )
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Combining/OperatorCombineLatestViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorCombineLatestViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorCombineLatestViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "combineLatest", description: nil)]
33 |
34 | operatorInfo = "Subscribes to an additional publisher and publishes a tuple upon receiving output from either publisher."
35 |
36 | operatorCode = """
37 | let subject1 = PassthroughSubject()
38 | let subject2 = PassthroughSubject()
39 |
40 | let combineLatest = subject1
41 | .combineLatest(subject2)
42 |
43 | combineLatest
44 | .sink(
45 | receiveValue: { first, second in
46 | display("\\(first ?? "nil") \\(second ?? "nil")")
47 | }
48 | )
49 | """
50 | }
51 |
52 | override func setupBindings() {
53 | let subject1 = Subject(
54 | title: "Subject 1",
55 | inputValues: ["🌟", "✅", nil]
56 | )
57 | let subject2 = Subject(
58 | title: "Subject 2",
59 | inputValues: ["😎", "😱", nil]
60 | )
61 |
62 | subjects = [subject1, subject2]
63 |
64 | let combined = subject1.trackedPublisher!
65 | .combineLatest(subject2.trackedPublisher!)
66 |
67 | subscription = combined
68 | .handleEvents(
69 | receiveSubscription: { [weak self] _ in
70 | guard let self = self else { return }
71 | self.updateOperator(.subscription)
72 | }, receiveCancel: { [weak self] in
73 | guard let self = self else { return }
74 | self.updateOperator(.cancel)
75 | }, receiveRequest: { [weak self] _ in
76 | guard let self = self else { return }
77 | self.updateOperator(.request)
78 | }
79 | )
80 | .sink(
81 | receiveCompletion: { [weak self] completion in
82 | guard let self = self else { return }
83 | self.setCompletionFromOperator(completion: completion)
84 | },
85 | receiveValue: { [weak self] firstValue, secondValue in
86 | guard let self = self else { return }
87 | self.setValueFromOperator(value: "\(firstValue ?? "nil") \(secondValue ?? "nil")")
88 | }
89 | )
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Combining/OperatorDropUntilOutputFromViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorDropUntilOutputFromViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorDropUntilOutputFromViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "dropUntilOutput", description: "Upstream: S1")]
33 |
34 | operatorInfo = "Ignores elements from the upstream publisher until it receives an element from a second publisher."
35 |
36 | operatorCode = """
37 | let subject1 = PassthroughSubject()
38 | let subject2 = PassthroughSubject()
39 |
40 | let dropUntilOutputFrom = subject1
41 | .drop(untilOutputFrom: subject2)
42 |
43 | dropUntilOutputFrom
44 | .sink(
45 | receiveValue: { value in
46 | display(value)
47 | }
48 | )
49 | """
50 | }
51 |
52 | override func setupBindings() {
53 | let subject1 = Subject(
54 | title: "Subject 1",
55 | inputValues: ["🌟", "✅", nil]
56 | )
57 |
58 | let subject2 = Subject(
59 | title: "Subject 2",
60 | inputValues: ["😎", "😱", nil]
61 | )
62 |
63 | subjects = [subject1, subject2]
64 |
65 | let dropUntil = subject1.trackedPublisher!
66 | .drop(untilOutputFrom: subject2.trackedPublisher!)
67 |
68 | subscription = dropUntil
69 | .handleEvents(
70 | receiveSubscription: { [weak self] _ in
71 | guard let self = self else { return }
72 | self.updateOperator(.subscription)
73 | }, receiveCancel: { [weak self] in
74 | guard let self = self else { return }
75 | self.updateOperator(.cancel)
76 | }, receiveRequest: { [weak self] _ in
77 | guard let self = self else { return }
78 | self.updateOperator(.request)
79 | }
80 | )
81 | .sink(
82 | receiveCompletion: { [weak self] completion in
83 | guard let self = self else { return }
84 | self.setCompletionFromOperator(completion: completion)
85 | }, receiveValue: { [weak self] value in
86 | guard let self = self else { return }
87 | self.setValueFromOperator(value: value)
88 | }
89 | )
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Combining/OperatorFlatMapViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorFlatMapViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorFlatMapViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "flatMap", description: "S1 -> S2")]
33 |
34 | operatorInfo = "Transforms all elements from an upstream publisher into a new or existing publisher."
35 |
36 | operatorCode = """
37 | let subject1 = PassthroughSubject()
38 | let subject2 = PassthroughSubject()
39 |
40 | let flatMap = subject1
41 | .flatMap { _ in
42 | return subject2
43 | }
44 |
45 | flatMap
46 | .sink(
47 | receiveValue: { value in
48 | display(value)
49 | }
50 | )
51 | """
52 | }
53 |
54 | override func setupBindings() {
55 | let subject1 = Subject(
56 | title: "Subject 1",
57 | inputValues: ["🌟", "✅", nil]
58 | )
59 |
60 | let subject2 = Subject(
61 | title: "Subject 2",
62 | inputValues: ["😎", "😱", nil]
63 | )
64 |
65 | subjects = [subject1, subject2]
66 |
67 | let flatMap = subject1.trackedPublisher!
68 | .flatMap { _ -> AnyPublisher in
69 | return subject2.trackedPublisher!
70 | }
71 |
72 | subscription = flatMap
73 | .handleEvents(
74 | receiveSubscription: { [weak self] _ in
75 | guard let self = self else { return }
76 | self.updateOperator(.subscription)
77 | }, receiveCancel: { [weak self] in
78 | guard let self = self else { return }
79 | self.updateOperator(.cancel)
80 | }, receiveRequest: { [weak self] _ in
81 | guard let self = self else { return }
82 | self.updateOperator(.request)
83 | }
84 | )
85 | .sink(
86 | receiveCompletion: { [weak self] completion in
87 | guard let self = self else { return }
88 | self.setCompletionFromOperator(completion: completion)
89 | }, receiveValue: { [weak self] value in
90 | guard let self = self else { return }
91 | self.setValueFromOperator(value: value)
92 | }
93 | )
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Combining/OperatorMergeViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorMergeViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorMergeViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "merge", description: nil)]
33 |
34 | operatorInfo = "Combines elements from a publisher with those from another publisher of the same type, delivering an interleaved sequence of elements."
35 |
36 | operatorCode = """
37 | let subject1 = PassthroughSubject()
38 | let subject2 = PassthroughSubject()
39 |
40 | let merge = subject1
41 | .merge(with: subject2)
42 |
43 | merge
44 | .sink(
45 | receiveValue: { value in
46 | display(value)
47 | }
48 | )
49 | """
50 | }
51 |
52 | override func setupBindings() {
53 | let subject1 = Subject(
54 | title: "Subject 1",
55 | inputValues: ["🌟", "✅", nil]
56 | )
57 |
58 | let subject2 = Subject(
59 | title: "Subject 2",
60 | inputValues: ["😎", "😱", nil]
61 | )
62 |
63 | subjects = [subject1, subject2]
64 |
65 | let merge = subject1.trackedPublisher!
66 | .merge(with: subject2.trackedPublisher!)
67 |
68 | subscription = merge
69 | .handleEvents(
70 | receiveSubscription: { [weak self] _ in
71 | guard let self = self else { return }
72 | self.updateOperator(.subscription)
73 | }, receiveCancel: { [weak self] in
74 | guard let self = self else { return }
75 | self.updateOperator(.cancel)
76 | }, receiveRequest: { [weak self] _ in
77 | guard let self = self else { return }
78 | self.updateOperator(.request)
79 | }
80 | )
81 | .sink(
82 | receiveCompletion: { [weak self] completion in
83 | guard let self = self else { return }
84 | self.setCompletionFromOperator(completion: completion)
85 | }, receiveValue: { [weak self] value in
86 | guard let self = self else { return }
87 | self.setValueFromOperator(value: value)
88 | }
89 | )
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Combining/OperatorPrefixUntilOutputFromViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorPrefixUntilOutputFromViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorPrefixUntilOutputFromViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "prefixUntilOutput", description: "from S2")]
33 |
34 | operatorInfo = "Republishes elements until another publisher emits an element."
35 |
36 | operatorCode = """
37 | let subject1 = PassthroughSubject()
38 | let subject2 = PassthroughSubject()
39 |
40 | let prefixUntilOutputFrom = subject1
41 | .prefix(untilOutputFrom: subject2)
42 |
43 | prefixUntilOutputFrom
44 | .sink(
45 | receiveValue: { value in
46 | display(value)
47 | }
48 | )
49 | """
50 | }
51 |
52 | override func setupBindings() {
53 | let subject1 = Subject(
54 | title: "Subject 1",
55 | inputValues: ["🌟", "✅", nil]
56 | )
57 |
58 | let subject2 = Subject(
59 | title: "Subject 2",
60 | inputValues: ["😎", "😱", nil]
61 | )
62 |
63 | subjects = [subject1, subject2]
64 |
65 | let prefixUntil = subject1.trackedPublisher!
66 | .prefix(untilOutputFrom: subject2.trackedPublisher!)
67 |
68 | subscription = prefixUntil
69 | .handleEvents(
70 | receiveSubscription: { [weak self] _ in
71 | guard let self = self else { return }
72 | self.updateOperator(.subscription)
73 | }, receiveCancel: { [weak self] in
74 | guard let self = self else { return }
75 | self.updateOperator(.cancel)
76 | }, receiveRequest: { [weak self] _ in
77 | guard let self = self else { return }
78 | self.updateOperator(.request)
79 | }
80 | )
81 | .sink(
82 | receiveCompletion: { [weak self] completion in
83 | guard let self = self else { return }
84 | self.setCompletionFromOperator(completion: completion)
85 | }, receiveValue: { [weak self] value in
86 | guard let self = self else { return }
87 | self.setValueFromOperator(value: value)
88 | }
89 | )
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Combining/OperatorPrependViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorPrependViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorPrependViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "prepend", description: "S2 -> S1")]
33 |
34 | operatorInfo = "Prefixes a publisher’s output with the elements emitted by the given publisher."
35 |
36 | operatorCode = """
37 | let subject1 = PassthroughSubject()
38 | let subject2 = PassthroughSubject()
39 |
40 | let prepend = subject1
41 | .prepend(subject2)
42 |
43 | prepend
44 | .sink(
45 | receiveValue: { value in
46 | display(value)
47 | }
48 | )
49 | """
50 | }
51 |
52 | override func setupBindings() {
53 | let subject1 = Subject(
54 | title: "Subject 1",
55 | inputValues: ["🌟", "✅", nil]
56 | )
57 |
58 | let subject2 = Subject(
59 | title: "Subject 2",
60 | inputValues: ["😎", "😱", nil]
61 | )
62 |
63 | subjects = [subject1, subject2]
64 |
65 | let prepend = subject1.trackedPublisher!
66 | .prepend(subject2.trackedPublisher!)
67 |
68 | subscription = prepend
69 | .handleEvents(
70 | receiveSubscription: { [weak self] _ in
71 | guard let self = self else { return }
72 | self.updateOperator(.subscription)
73 | }, receiveCancel: { [weak self] in
74 | guard let self = self else { return }
75 | self.updateOperator(.cancel)
76 | }, receiveRequest: { [weak self] _ in
77 | guard let self = self else { return }
78 | self.updateOperator(.request)
79 | }
80 | )
81 | .sink(
82 | receiveCompletion: { [weak self] completion in
83 | guard let self = self else { return }
84 | self.setCompletionFromOperator(completion: completion)
85 | }, receiveValue: { [weak self] value in
86 | guard let self = self else { return }
87 | self.setValueFromOperator(value: value)
88 | }
89 | )
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Combining/OperatorZipViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorZipViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorZipViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "zip", description: nil)]
33 |
34 | operatorInfo = "Combines elements from another publisher and deliver pairs of elements as tuples."
35 |
36 | operatorCode = """
37 | let subject1 = PassthroughSubject()
38 | let subject2 = PassthroughSubject()
39 |
40 | let zip = subject1
41 | .zip(subject2)
42 |
43 | zip
44 | .sink(
45 | receiveValue: { values in
46 | let result = "\\(values.0 ?? "nil") \\(values.1 ?? "nil")"
47 | display(result)
48 | }
49 | )
50 | """
51 | }
52 |
53 | override func setupBindings() {
54 |
55 | let subject1 = Subject(
56 | title: "Subject 1",
57 | inputValues: ["🌟", "✅", nil]
58 | )
59 |
60 | let subject2 = Subject(
61 | title: "Subject 2",
62 | inputValues: ["😎", "😱", nil]
63 | )
64 |
65 | subjects = [subject1, subject2]
66 |
67 | let zip = subject1.trackedPublisher!
68 | .zip(subject2.trackedPublisher!)
69 |
70 | subscription = zip
71 | .handleEvents(
72 | receiveSubscription: { [weak self] _ in
73 | guard let self = self else { return }
74 | self.updateOperator(.subscription)
75 | }, receiveCancel: { [weak self] in
76 | guard let self = self else { return }
77 | self.updateOperator(.cancel)
78 | }, receiveRequest: { [weak self] _ in
79 | guard let self = self else { return }
80 | self.updateOperator(.request)
81 | }
82 | )
83 | .sink(
84 | receiveCompletion: { [weak self] completion in
85 | guard let self = self else { return }
86 | self.setCompletionFromOperator(completion: completion)
87 | }, receiveValue: { [weak self] values in
88 | guard let self = self else { return }
89 | let result = "\(values.0 ?? "nil") \(values.1 ?? "nil")"
90 | self.setValueFromOperator(value: "\(result)")
91 | }
92 | )
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Error handling/OperatorCatchErrorViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorCatchErrorViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorCatchErrorViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "catch", description: "to 👀")]
33 |
34 | operatorInfo = "Handles errors from an upstream publisher by replacing it with another publisher."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let catchError = subject
40 | .catch { error in
41 | Just("👀")
42 | }
43 |
44 | catchError
45 | .sink(
46 | receiveValue: { value in
47 | display(value)
48 | }
49 | )
50 | """
51 | }
52 |
53 | override func setupBindings() {
54 | let subject = Subject(
55 | title: "Subject",
56 | inputValues: ["🌟", "✅", nil]
57 | )
58 |
59 | subjects = [subject]
60 |
61 | let catchError = subject.trackedPublisher!
62 | .catch { error in
63 | Just("👀")
64 | }
65 |
66 | subscription = catchError
67 | .handleEvents(
68 | receiveSubscription: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.subscription)
71 | }, receiveCancel: { [weak self] in
72 | guard let self = self else { return }
73 | self.updateOperator(.cancel)
74 | }, receiveRequest: { [weak self] _ in
75 | guard let self = self else { return }
76 | self.updateOperator(.request)
77 | }
78 | )
79 | .sink(
80 | receiveCompletion: { [weak self] completion in
81 | guard let self = self else { return }
82 | self.setCompletionFromOperator(completion: completion)
83 | }, receiveValue: { [weak self] value in
84 | guard let self = self else { return }
85 | self.setValueFromOperator(value: value)
86 | }
87 | )
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Error handling/OperatorMapErrorViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorMapErrorViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorMapErrorViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "mapError", description: "to ☠️ error")]
33 |
34 | operatorInfo = "Converts any failure from the upstream publisher into a new error."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let mapError = subject
40 | .mapError { error -> Error in
41 | return TestError.mapped
42 | }
43 |
44 | mapError
45 | .sink(
46 | receiveValue: { value in
47 | display(value)
48 | }
49 | )
50 | """
51 | }
52 |
53 | override func setupBindings() {
54 | let subject = Subject(
55 | title: "Subject",
56 | inputValues: ["🌟", "✅", nil]
57 | )
58 |
59 | subjects = [subject]
60 |
61 | let mapError = subject.trackedPublisher!
62 | .mapError { error -> Error in
63 | return TestError.mapped
64 | }
65 |
66 | subscription = mapError
67 | .handleEvents(
68 | receiveSubscription: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.subscription)
71 | }, receiveCancel: { [weak self] in
72 | guard let self = self else { return }
73 | self.updateOperator(.cancel)
74 | }, receiveRequest: { [weak self] _ in
75 | guard let self = self else { return }
76 | self.updateOperator(.request)
77 | }
78 | )
79 | .sink(
80 | receiveCompletion: { [weak self] completion in
81 | guard let self = self else { return }
82 | self.setCompletionFromOperator(completion: completion)
83 | }, receiveValue: { [weak self] value in
84 | guard let self = self else { return }
85 | self.setValueFromOperator(value: value)
86 | }
87 | )
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Error handling/OperatorReplaceErrorViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorReplaceErrorViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorReplaceErrorViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "replaceError", description: "with 👻")]
33 |
34 | operatorInfo = "Replaces any errors in the stream with the provided element."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let replaceError = subject
40 | .replaceError(with: "👻")
41 |
42 | replaceError
43 | .sink(
44 | receiveValue: { value in
45 | display(value)
46 | }
47 | )
48 | """
49 | }
50 |
51 | override func setupBindings() {
52 | let subject = Subject(
53 | title: "Subject",
54 | inputValues: ["🌟", "✅", nil]
55 | )
56 |
57 | subjects = [subject]
58 |
59 | let replaceError = subject.trackedPublisher!
60 | .replaceError(with: "👻")
61 |
62 | subscription = replaceError
63 | .handleEvents(
64 | receiveSubscription: { [weak self] _ in
65 | guard let self = self else { return }
66 | self.updateOperator(.subscription)
67 | }, receiveCancel: { [weak self] in
68 | guard let self = self else { return }
69 | self.updateOperator(.cancel)
70 | }, receiveRequest: { [weak self] _ in
71 | guard let self = self else { return }
72 | self.updateOperator(.request)
73 | }
74 | )
75 | .sink(
76 | receiveCompletion: { [weak self] completion in
77 | guard let self = self else { return }
78 | self.setCompletionFromOperator(completion: completion)
79 | }, receiveValue: { [weak self] value in
80 | guard let self = self else { return }
81 | self.setValueFromOperator(value: value)
82 | }
83 | )
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Filtering/OperatorCompactMapViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorCompactMapViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorCompactMapViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "compactMap", description: "value + 💃")]
33 |
34 | operatorInfo = "Calls a closure with each received element and publishes any returned optional that has a value."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let compactMap = subject
40 | .compactMap { value -> String? in
41 | if let value = value {
42 | return "\\(value) 💃"
43 | }
44 | return nil
45 | }
46 |
47 | compactMap
48 | .sink(
49 | receiveValue: { value in
50 | display(value)
51 | }
52 | )
53 | """
54 | }
55 |
56 | override func setupBindings() {
57 | let subject1 = Subject(
58 | title: "Subject",
59 | inputValues: ["🌟", "✅", nil]
60 | )
61 |
62 | subjects = [subject1]
63 |
64 | let compactMap = subject1.trackedPublisher!
65 | .compactMap { value -> String? in
66 | if let value = value {
67 | return "\(value) 💃"
68 | }
69 | return nil
70 | }
71 |
72 | subscription = compactMap
73 | .handleEvents(
74 | receiveSubscription: { [weak self] _ in
75 | guard let self = self else { return }
76 | self.updateOperator(.subscription)
77 | }, receiveCancel: { [weak self] in
78 | guard let self = self else { return }
79 | self.updateOperator(.cancel)
80 | }, receiveRequest: { [weak self] _ in
81 | guard let self = self else { return }
82 | self.updateOperator(.request)
83 | }
84 | )
85 | .sink(
86 | receiveCompletion: { [weak self] completion in
87 | guard let self = self else { return }
88 | self.setCompletionFromOperator(completion: completion)
89 | }, receiveValue: { [weak self] value in
90 | guard let self = self else { return }
91 | self.setValueFromOperator(value: value)
92 | }
93 | )
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Filtering/OperatorDropFirstViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorDropFirstViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorDropFirstViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "dropFirst", description: "first 2")]
33 |
34 | operatorInfo = "Omits the specified number of elements before republishing subsequent elements."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let dropFirst = subject
40 | .dropFirst(2)
41 |
42 | dropFirst
43 | .sink(
44 | receiveValue: { value in
45 | display(value)
46 | }
47 | )
48 | """
49 | }
50 |
51 | override func setupBindings() {
52 | let subject1 = Subject(
53 | title: "Subject",
54 | inputValues: ["🌟", "✅", nil]
55 | )
56 |
57 | subjects = [subject1]
58 |
59 | let dropFirst = subject1.trackedPublisher!
60 | .dropFirst(2)
61 |
62 | subscription = dropFirst
63 | .handleEvents(
64 | receiveSubscription: { [weak self] _ in
65 | guard let self = self else { return }
66 | self.updateOperator(.subscription)
67 | }, receiveCancel: { [weak self] in
68 | guard let self = self else { return }
69 | self.updateOperator(.cancel)
70 | }, receiveRequest: { [weak self] _ in
71 | guard let self = self else { return }
72 | self.updateOperator(.request)
73 | }
74 | )
75 | .sink(
76 | receiveCompletion: { [weak self] completion in
77 | guard let self = self else { return }
78 | self.setCompletionFromOperator(completion: completion)
79 | }, receiveValue: { [weak self] value in
80 | guard let self = self else { return }
81 | self.setValueFromOperator(value: value)
82 | }
83 | )
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Filtering/OperatorDropWhileViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorDropWhileViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorDropWhileViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "dropWhile", description: "value == 🌟")]
33 |
34 | operatorInfo = "Omits elements from the upstream publisher until a given closure returns false, before republishing all remaining elements."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let dropWhile = subject
40 | .drop(while: {
41 | $0 == "🌟"
42 | })
43 |
44 | dropWhile
45 | .sink(
46 | receiveValue: { value in
47 | display(value)
48 | }
49 | )
50 | """
51 | }
52 |
53 | override func setupBindings() {
54 | let subject1 = Subject(
55 | title: "Subject",
56 | inputValues: ["🌟", "✅", nil]
57 | )
58 |
59 | subjects = [subject1]
60 |
61 | let dropWhile = subject1.trackedPublisher!
62 | .drop(while: {
63 | $0 == "🌟"
64 | })
65 |
66 | subscription = dropWhile
67 | .handleEvents(
68 | receiveSubscription: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.subscription)
71 | }, receiveCancel: { [weak self] in
72 | guard let self = self else { return }
73 | self.updateOperator(.cancel)
74 | }, receiveRequest: { [weak self] _ in
75 | guard let self = self else { return }
76 | self.updateOperator(.request)
77 | }
78 | )
79 | .sink(
80 | receiveCompletion: { [weak self] completion in
81 | guard let self = self else { return }
82 | self.setCompletionFromOperator(completion: completion)
83 | }, receiveValue: { [weak self] value in
84 | guard let self = self else { return }
85 | self.setValueFromOperator(value: value)
86 | }
87 | )
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Filtering/OperatorFilterViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorFilterViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorFilterViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "filter", description: "value == ✅")]
33 |
34 | operatorInfo = "Republishes all elements that match a provided closure."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let filter = subject
40 | .filter { value -> Bool in
41 | return value == "✅"
42 | }
43 |
44 | filter
45 | .sink(
46 | receiveValue: { value in
47 | display(value)
48 | }
49 | )
50 | """
51 | }
52 |
53 | override func setupBindings() {
54 | let subject1 = Subject(
55 | title: "Subject",
56 | inputValues: ["🌟", "✅", nil]
57 | )
58 |
59 | subjects = [subject1]
60 |
61 | let filter = subject1.trackedPublisher!
62 | .filter { value -> Bool in
63 | return value == "✅"
64 | }
65 |
66 | subscription = filter
67 | .handleEvents(
68 | receiveSubscription: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.subscription)
71 | }, receiveCancel: { [weak self] in
72 | guard let self = self else { return }
73 | self.updateOperator(.cancel)
74 | }, receiveRequest: { [weak self] _ in
75 | guard let self = self else { return }
76 | self.updateOperator(.request)
77 | }
78 | )
79 | .sink(
80 | receiveCompletion: { [weak self] completion in
81 | guard let self = self else { return }
82 | self.setCompletionFromOperator(completion: completion)
83 | }, receiveValue: { [weak self] value in
84 | guard let self = self else { return }
85 | self.setValueFromOperator(value: value)
86 | }
87 | )
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Filtering/OperatorFirstViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorFirstViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorFirstViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "first", description: nil)]
33 |
34 | operatorInfo = "Publishes the first element of a stream, then finishes."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let first = subject.first()
40 |
41 | first
42 | .sink(
43 | receiveValue: { value in
44 | display(value)
45 | }
46 | )
47 | """
48 | }
49 |
50 | override func setupBindings() {
51 | let subject1 = Subject(
52 | title: "Subject",
53 | inputValues: ["🌟", "✅", nil]
54 | )
55 |
56 | subjects = [subject1]
57 |
58 | let first = subject1.trackedPublisher!
59 | .first()
60 |
61 | subscription = first
62 | .handleEvents(
63 | receiveSubscription: { [weak self] _ in
64 | guard let self = self else { return }
65 | self.updateOperator(.subscription)
66 | }, receiveCancel: { [weak self] in
67 | guard let self = self else { return }
68 | self.updateOperator(.cancel)
69 | }, receiveRequest: { [weak self] _ in
70 | guard let self = self else { return }
71 | self.updateOperator(.request)
72 | }
73 | )
74 | .sink(
75 | receiveCompletion: { [weak self] completion in
76 | guard let self = self else { return }
77 | self.setCompletionFromOperator(completion: completion)
78 | }, receiveValue: { [weak self] value in
79 | guard let self = self else { return }
80 | self.setValueFromOperator(value: value)
81 | }
82 | )
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Filtering/OperatorIgnoreOutputViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorIgnoreOutputViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorIgnoreOutputViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "ignoreOutput", description: nil)]
33 |
34 | operatorInfo = "Ignores all upstream elements, but passes along a completion state (finished or failed). Try sending some values and then tapping `Finish`"
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let ignoreOutput = subject.ignoreOutput()
40 |
41 | ignoreOutput
42 | .sink(
43 | receiveValue: { value in
44 | display(value)
45 | }
46 | )
47 | """
48 | }
49 |
50 | override func setupBindings() {
51 | let subject1 = Subject(
52 | title: "Subject",
53 | inputValues: ["🌟", "✅", nil]
54 | )
55 |
56 | subjects = [subject1]
57 |
58 | let ignored = subject1.trackedPublisher!.ignoreOutput()
59 |
60 | subscription = ignored
61 | .handleEvents(
62 | receiveSubscription: { [weak self] _ in
63 | guard let self = self else { return }
64 | self.updateOperator(.subscription)
65 | }, receiveCancel: { [weak self] in
66 | guard let self = self else { return }
67 | self.updateOperator(.cancel)
68 | }, receiveRequest: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.request)
71 | }
72 | )
73 | .sink(
74 | receiveCompletion: { [weak self] completion in
75 | guard let self = self else { return }
76 | self.setCompletionFromOperator(completion: completion)
77 | },
78 | receiveValue: { _ in }
79 | )
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Filtering/OperatorLastViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorLastViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorLastViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "last", description: nil)]
33 |
34 | operatorInfo = "Only publishes the last element of a stream, after the stream finishes."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let last = subject.last()
40 |
41 | last
42 | .sink(
43 | receiveValue: { value in
44 | display(value)
45 | }
46 | )
47 | """
48 | }
49 |
50 | override func setupBindings() {
51 | let subject1 = Subject(
52 | title: "Subject",
53 | inputValues: ["🌟", "✅", nil]
54 | )
55 |
56 | subjects = [subject1]
57 |
58 | let last = subject1.trackedPublisher!.last()
59 |
60 | subscription = last
61 | .handleEvents(
62 | receiveSubscription: { [weak self] _ in
63 | guard let self = self else { return }
64 | self.updateOperator(.subscription)
65 | }, receiveCancel: { [weak self] in
66 | guard let self = self else { return }
67 | self.updateOperator(.cancel)
68 | }, receiveRequest: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.request)
71 | }
72 | )
73 | .sink(
74 | receiveCompletion: { [weak self] completion in
75 | guard let self = self else { return }
76 | self.setCompletionFromOperator(completion: completion)
77 | }, receiveValue: { [weak self] value in
78 | guard let self = self else { return }
79 | self.setValueFromOperator(value: value)
80 | }
81 | )
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Filtering/OperatorPrefixViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorPrefixViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorPrefixViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "prefix", description: "length: 2")]
33 |
34 | operatorInfo = "Republishes elements up to the specified maximum count."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let prefix = subject.prefix(2)
40 |
41 | prefix
42 | .sink(
43 | receiveValue: { value in
44 | display(value)
45 | }
46 | )
47 | """
48 | }
49 |
50 | override func setupBindings() {
51 | let subject1 = Subject(
52 | title: "Subject",
53 | inputValues: ["🌟", "✅", nil]
54 | )
55 |
56 | subjects = [subject1]
57 |
58 | let last = subject1.trackedPublisher!.prefix(2)
59 |
60 | subscription = last
61 | .handleEvents(
62 | receiveSubscription: { [weak self] _ in
63 | guard let self = self else { return }
64 | self.updateOperator(.subscription)
65 | }, receiveCancel: { [weak self] in
66 | guard let self = self else { return }
67 | self.updateOperator(.cancel)
68 | }, receiveRequest: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.request)
71 | }
72 | )
73 | .sink(
74 | receiveCompletion: { [weak self] completion in
75 | guard let self = self else { return }
76 | self.setCompletionFromOperator(completion: completion)
77 | }, receiveValue: { [weak self] value in
78 | guard let self = self else { return }
79 | self.setValueFromOperator(value: value)
80 | }
81 | )
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Filtering/OperatorRemoveDuplicatesViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorRemoveDuplicatesViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorRemoveDuplicatesViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "remove\nDuplicates", description: nil)]
33 |
34 | operatorInfo = "Publishes only elements that don’t match the previous element."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let removeDuplicates = subject.removeDuplicates()
40 |
41 | removeDuplicates
42 | .sink(
43 | receiveValue: { value in
44 | display(value)
45 | }
46 | )
47 | """
48 | }
49 |
50 | override func setupBindings() {
51 | let subject1 = Subject(
52 | title: "Subject",
53 | inputValues: ["🌟", "✅", nil]
54 | )
55 |
56 | subjects = [subject1]
57 |
58 | let removeDuplicates = subject1.trackedPublisher!.removeDuplicates()
59 |
60 | subscription = removeDuplicates
61 | .handleEvents(
62 | receiveSubscription: { [weak self] _ in
63 | guard let self = self else { return }
64 | self.updateOperator(.subscription)
65 | }, receiveCancel: { [weak self] in
66 | guard let self = self else { return }
67 | self.updateOperator(.cancel)
68 | }, receiveRequest: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.request)
71 | }
72 | )
73 | .sink(
74 | receiveCompletion: { [weak self] completion in
75 | guard let self = self else { return }
76 | self.setCompletionFromOperator(completion: completion)
77 | }, receiveValue: { [weak self] value in
78 | guard let self = self else { return }
79 | self.setValueFromOperator(value: value)
80 | }
81 | )
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Timing/OperatorDebounceViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorDebounceViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorDebounceViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | subjectOutputCountdown = 3
33 |
34 | operators = [Operator(name: "debounce", description: "3 seconds")]
35 |
36 | operatorInfo = "Publishes elements only after a specified time interval elapses between events."
37 |
38 | operatorCode = """
39 | let subject = PassthroughSubject()
40 |
41 | let debounce = subject
42 | .debounce(for: 3, scheduler: DispatchQueue.main)
43 |
44 | debounce
45 | .sink(
46 | receiveValue: { value in
47 | display(value)
48 | }
49 | )
50 | """
51 | }
52 |
53 | override func setupBindings() {
54 | let subject1 = Subject(
55 | title: "Subject",
56 | inputValues: ["🌟", "✅", nil]
57 | )
58 |
59 | subjects = [subject1]
60 |
61 | let debounce = subject1.trackedPublisher!
62 | .debounce(for: 3, scheduler: DispatchQueue.main)
63 |
64 | subscription = debounce
65 | .handleEvents(
66 | receiveSubscription: { [weak self] _ in
67 | guard let self = self else { return }
68 | self.updateOperator(.subscription)
69 | }, receiveCancel: { [weak self] in
70 | guard let self = self else { return }
71 | self.updateOperator(.cancel)
72 | }, receiveRequest: { [weak self] _ in
73 | guard let self = self else { return }
74 | self.updateOperator(.request)
75 | }
76 | )
77 | .sink(
78 | receiveCompletion: { [weak self] completion in
79 | guard let self = self else { return }
80 | self.setCompletionFromOperator(completion: completion)
81 | }, receiveValue: { [weak self] value in
82 | guard let self = self else { return }
83 | self.setValueFromOperator(value: value)
84 | }
85 | )
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Timing/OperatorDelayViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorDelayViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorDelayViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | subjectOutputCountdown = 2
33 | subjectValueRestartsCountdown = true
34 | countdownFinishRestartsCountdown = false
35 |
36 | operators = [Operator(name: "delay", description: "2 seconds")]
37 |
38 | operatorInfo = "Delays delivery of all output to the downstream receiver by a specified amount of time on a particular scheduler."
39 |
40 | operatorCode = """
41 | let subject = PassthroughSubject()
42 |
43 | let delay = subject
44 | .delay(for: 2, scheduler: DispatchQueue.main)
45 |
46 | delay
47 | .sink(
48 | receiveValue: { value in
49 | display(value)
50 | }
51 | )
52 | """
53 | }
54 |
55 | override func setupBindings() {
56 | let subject1 = Subject(
57 | title: "Subject",
58 | inputValues: ["🌟", "✅", nil]
59 | )
60 |
61 | subjects = [subject1]
62 |
63 | let delay = subject1.trackedPublisher!
64 | .delay(for: 2, scheduler: DispatchQueue.main)
65 |
66 | subscription = delay
67 | .handleEvents(
68 | receiveSubscription: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.subscription)
71 | }, receiveCancel: { [weak self] in
72 | guard let self = self else { return }
73 | self.updateOperator(.cancel)
74 | }, receiveRequest: { [weak self] _ in
75 | guard let self = self else { return }
76 | self.updateOperator(.request)
77 | }
78 | )
79 | .sink(
80 | receiveCompletion: { [weak self] completion in
81 | guard let self = self else { return }
82 | self.setCompletionFromOperator(completion: completion)
83 | }, receiveValue: { [weak self] value in
84 | guard let self = self else { return }
85 | self.setValueFromOperator(value: value)
86 | }
87 | )
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Timing/OperatorMeasureIntervalViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorMeasureIntervalViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorMeasureIntervalViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "measureInterval", description: "in seconds")]
33 |
34 | operatorInfo = "Measures and emits the time interval between events received from an upstream publisher."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let measureInterval = subject
40 | .measureInterval(using: DispatchQueue.main)
41 |
42 | measureInterval
43 | .sink(
44 | receiveValue: { value in
45 | let seconds = String(format: "%.1f", Double(value.magnitude) / pow(10, 9))
46 | display(seconds)
47 | }
48 | )
49 | """
50 | }
51 |
52 | override func setupBindings() {
53 | let subject1 = Subject(
54 | title: "Subject",
55 | inputValues: ["🌟", "✅", nil]
56 | )
57 |
58 | subjects = [subject1]
59 |
60 | let measureInterval = subject1.trackedPublisher!
61 | .measureInterval(using: DispatchQueue.main)
62 |
63 | subscription = measureInterval
64 | .handleEvents(
65 | receiveSubscription: { [weak self] _ in
66 | guard let self = self else { return }
67 | self.updateOperator(.subscription)
68 | }, receiveCancel: { [weak self] in
69 | guard let self = self else { return }
70 | self.updateOperator(.cancel)
71 | }, receiveRequest: { [weak self] _ in
72 | guard let self = self else { return }
73 | self.updateOperator(.request)
74 | }
75 | )
76 | .sink(
77 | receiveCompletion: { [weak self] completion in
78 | guard let self = self else { return }
79 | self.setCompletionFromOperator(completion: completion)
80 | }, receiveValue: { [weak self] value in
81 | guard let self = self else { return }
82 |
83 | let seconds = String(format: "%.1f", Double(value.magnitude) / pow(10, 9))
84 | self.setValueFromOperator(value: "\(seconds)s")
85 |
86 | self.startCountdown()
87 | }
88 | )
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Timing/OperatorTimeoutViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorTimeoutViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorTimeoutViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | subjectOutputCountdown = 5
33 | countdownFinishKillsPublisher = true
34 |
35 | operators = [Operator(name: "timeout", description: "5 seconds")]
36 |
37 | operatorInfo = "Terminates publishing if the upstream publisher exceeds the specified time interval without producing an element."
38 |
39 | operatorCode = """
40 | let subject = PassthroughSubject()
41 |
42 | let timeout = subject
43 | .timeout(5, scheduler: DispatchQueue.main)
44 |
45 | timeout
46 | .sink(
47 | receiveValue: { value in
48 | display(value)
49 | }
50 | )
51 | """
52 | }
53 |
54 | override func setupBindings() {
55 | let subject1 = Subject(
56 | title: "Subject",
57 | inputValues: ["🌟", "✅", nil]
58 | )
59 |
60 | subjects = [subject1]
61 |
62 | let timeout = subject1.trackedPublisher!
63 | .timeout(5, scheduler: DispatchQueue.main)
64 |
65 | subscription = timeout
66 | .handleEvents(
67 | receiveSubscription: { [weak self] _ in
68 | guard let self = self else { return }
69 | self.updateOperator(.subscription)
70 | }, receiveCancel: { [weak self] in
71 | guard let self = self else { return }
72 | self.updateOperator(.cancel)
73 | }, receiveRequest: { [weak self] _ in
74 | guard let self = self else { return }
75 | self.updateOperator(.request)
76 | }
77 | )
78 | .sink(
79 | receiveCompletion: { [weak self] completion in
80 | guard let self = self else { return }
81 | self.setCompletionFromOperator(completion: completion)
82 | }, receiveValue: { [weak self] value in
83 | guard let self = self else { return }
84 | self.setValueFromOperator(value: value)
85 | }
86 | )
87 |
88 | startCountdown()
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Transforming/OperatorCollectViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorCollectViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | public class OperatorCollectViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "collect", description: "count: 3")]
33 |
34 | operatorInfo = "Collects up to the specified number of elements, and then emits a single array of the collection."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let collect = subject.collect(3)
40 |
41 | collect
42 | .sink(
43 | receiveValue: { values in
44 | let mappedValues = values.map { $0 ?? "nil" }
45 | display(mappedValues.joined(separator: " "))
46 | }
47 | )
48 | """
49 | }
50 |
51 | override func setupBindings() {
52 | let subject = Subject(
53 | title: "Subject",
54 | inputValues: ["🌟", "✅", nil]
55 | )
56 |
57 | subjects = [subject]
58 |
59 | let collect = subject.trackedPublisher!.collect(3)
60 |
61 | subscription = collect
62 | .handleEvents(
63 | receiveSubscription: { [weak self] _ in
64 | guard let self = self else { return }
65 | self.updateOperator(.subscription)
66 | }, receiveCancel: { [weak self] in
67 | guard let self = self else { return }
68 | self.updateOperator(.cancel)
69 | }, receiveRequest: { [weak self] _ in
70 | guard let self = self else { return }
71 | self.updateOperator(.request)
72 | }
73 | )
74 | .sink(
75 | receiveCompletion: { [weak self] completion in
76 | guard let self = self else { return }
77 | self.setCompletionFromOperator(completion: completion)
78 | }, receiveValue: { [weak self] values in
79 | guard let self = self else { return }
80 | let mappedValues = values.map { $0 ?? "nil" }
81 | self.setValueFromOperator(value: mappedValues.joined(separator: " "))
82 | }
83 | )
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Transforming/OperatorMapViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorMapViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorMapViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "map", description: "value + 🍏")]
33 |
34 | operatorInfo = "Transforms all elements from the upstream publisher with a provided closure."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let map = subject
40 | .map { value -> String? in
41 | return "\\(value ?? "nil") 🍏"
42 | }
43 |
44 | map
45 | .sink(
46 | receiveValue: { value in
47 | display(value)
48 | }
49 | )
50 | """
51 | }
52 |
53 | override func setupBindings() {
54 | let subject = Subject(
55 | title: "Subject",
56 | inputValues: ["🌟", "✅", nil]
57 | )
58 |
59 | subjects = [subject]
60 |
61 | let map = subject.trackedPublisher!
62 | .map { value -> String? in
63 | return "\(value ?? "nil") 🍏"
64 | }
65 |
66 | subscription = map
67 | .handleEvents(
68 | receiveSubscription: { [weak self] _ in
69 | guard let self = self else { return }
70 | self.updateOperator(.subscription)
71 | }, receiveCancel: { [weak self] in
72 | guard let self = self else { return }
73 | self.updateOperator(.cancel)
74 | }, receiveRequest: { [weak self] _ in
75 | guard let self = self else { return }
76 | self.updateOperator(.request)
77 | }
78 | )
79 | .sink(
80 | receiveCompletion: { [weak self] completion in
81 | guard let self = self else { return }
82 | self.setCompletionFromOperator(completion: completion)
83 | }, receiveValue: { [weak self] value in
84 | guard let self = self else { return }
85 | self.setValueFromOperator(value: value)
86 | }
87 | )
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Transforming/OperatorReplaceEmptyViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorReplaceEmptyViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorReplaceEmptyViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "replaceEmpty", description: "to 🙈")]
33 |
34 | operatorInfo = "Replaces an empty stream with the provided element. Try tapping `Finish` immediately without sending any values."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let replaceEmpty = subject
40 | .replaceEmpty(with: "🙈")
41 |
42 | replaceEmpty
43 | .sink(
44 | receiveValue: { value in
45 | display(value)
46 | }
47 | )
48 | """
49 | }
50 |
51 | override func setupBindings() {
52 | let subject = Subject(
53 | title: "Subject",
54 | inputValues: ["🌟", "✅", nil]
55 | )
56 |
57 | subjects = [subject]
58 |
59 | let replaceEmpty = subject.trackedPublisher!
60 | .replaceEmpty(with: "🙈")
61 |
62 | subscription = replaceEmpty
63 | .handleEvents(
64 | receiveSubscription: { [weak self] _ in
65 | guard let self = self else { return }
66 | self.updateOperator(.subscription)
67 | }, receiveCancel: { [weak self] in
68 | guard let self = self else { return }
69 | self.updateOperator(.cancel)
70 | }, receiveRequest: { [weak self] _ in
71 | guard let self = self else { return }
72 | self.updateOperator(.request)
73 | }
74 | )
75 | .sink(
76 | receiveCompletion: { [weak self] completion in
77 | guard let self = self else { return }
78 | self.setCompletionFromOperator(completion: completion)
79 | }, receiveValue: { [weak self] value in
80 | guard let self = self else { return }
81 | self.setValueFromOperator(value: value)
82 | }
83 | )
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/OperatorViewControllers/Transforming/OperatorReplaceNilViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OperatorReplaceNilViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 | import Combine
28 |
29 | class OperatorReplaceNilViewController: BaseOperatorViewController {
30 |
31 | override func setupOperator() {
32 | operators = [Operator(name: "replaceNil", description: "to 🐰")]
33 |
34 | operatorInfo = "Replaces nil elements in the stream with the provided element."
35 |
36 | operatorCode = """
37 | let subject = PassthroughSubject()
38 |
39 | let replaceNil = subject
40 | .replaceNil(with: "🐰")
41 |
42 | replaceNil
43 | .sink(
44 | receiveValue: { value in
45 | display(value)
46 | }
47 | )
48 | """
49 | }
50 |
51 | override func setupBindings() {
52 |
53 | let subject = Subject(
54 | title: "Subject",
55 | inputValues: ["🌟", "✅", nil]
56 | )
57 |
58 | subjects = [subject]
59 |
60 | let replaced = subject.trackedPublisher!
61 | .replaceNil(with: "🐰")
62 |
63 | subscription = replaced
64 | .handleEvents(
65 | receiveSubscription: { [weak self] _ in
66 | guard let self = self else { return }
67 | self.updateOperator(.subscription)
68 | }, receiveCancel: { [weak self] in
69 | guard let self = self else { return }
70 | self.updateOperator(.cancel)
71 | }, receiveRequest: { [weak self] _ in
72 | guard let self = self else { return }
73 | self.updateOperator(.request)
74 | }
75 | )
76 | .sink(
77 | receiveCompletion: { [weak self] completion in
78 | guard let self = self else { return }
79 | self.setCompletionFromOperator(completion: completion)
80 | }, receiveValue: { [weak self] value in
81 | guard let self = self else { return }
82 | self.setValueFromOperator(value: value)
83 | }
84 | )
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/ViewControllers/SymbolsTableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SymbolsTableViewController.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 |
28 | open class SymbolsTableViewController: UITableViewController {
29 |
30 | let imageNames = ["link", "square.and.arrow.up", "xmark.circle", "exclamationmark.triangle", "checkmark"]
31 | let symbolTitles = ["Received subscription", "Received demand", "Cancelled", "Completed with error", "Completed"]
32 |
33 | open override func viewDidLoad() {
34 | super.viewDidLoad()
35 |
36 | title = "Publisher Symbol Guide"
37 | navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(performDismiss))
38 |
39 | tableView.register(UITableViewCell.self, forCellReuseIdentifier: "SymbolCell")
40 | tableView.allowsSelection = false
41 | }
42 |
43 | public override func numberOfSections(in tableView: UITableView) -> Int {
44 | return 1
45 | }
46 |
47 | public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
48 | return 6
49 | }
50 |
51 | public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
52 | let cell = tableView.dequeueReusableCell(withIdentifier: "SymbolCell", for: indexPath)
53 |
54 | if indexPath.row == 0 {
55 | cell.imageView?.image = Assets.numberOfSubscriptions.image
56 | cell.textLabel?.text = "Number of subscriptions"
57 | } else {
58 | cell.imageView?.image = UIImage(systemName: imageNames[indexPath.row - 1])
59 | cell.textLabel?.text = symbolTitles[indexPath.row - 1]
60 | }
61 |
62 | return cell
63 | }
64 |
65 | @objc private func performDismiss() {
66 | dismiss(animated: true, completion: nil)
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/Sources/CombineOperatorsCore/Views/InputButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InputButton.swift
3 | // CombineOperatorsCore
4 | //
5 | // Copyright (c) 2020 cocoatoucher user on github.com (https://github.com/cocoatoucher/)
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy
8 | // of this software and associated documentation files (the "Software"), to deal
9 | // in the Software without restriction, including without limitation the rights
10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | // copies of the Software, and to permit persons to whom the Software is
12 | // furnished to do so, subject to the following conditions:
13 |
14 | // The above copyright notice and this permission notice shall be included in all
15 | // copies or substantial portions of the Software.
16 |
17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | // SOFTWARE.
24 | //
25 |
26 | import UIKit
27 |
28 | class InputButton: UIButton {
29 |
30 | enum Mode {
31 | case value
32 | case error
33 | case finish
34 | }
35 |
36 | override var isEnabled: Bool {
37 | didSet {
38 | alpha = isEnabled ? 1.0 : 0.3
39 | }
40 | }
41 |
42 | override var isHighlighted: Bool {
43 | didSet {
44 | if isHighlighted {
45 | backgroundColor = UIColor(
46 | named: "\(colorNamePrefix)Highlighted",
47 | in: Bundle.module,
48 | compatibleWith: nil
49 | )
50 | } else {
51 | backgroundColor = UIColor(
52 | named: colorNamePrefix,
53 | in: Bundle.module,
54 | compatibleWith: nil
55 | )
56 | }
57 | }
58 | }
59 |
60 | let colorNamePrefix: String
61 |
62 | init(mode: Mode = .value) {
63 | switch mode {
64 | case .value:
65 | colorNamePrefix = "inputButton"
66 | case .error:
67 | colorNamePrefix = "errorButton"
68 | case .finish:
69 | colorNamePrefix = "finishButton"
70 | }
71 |
72 | super.init(frame: .zero)
73 |
74 | setTitleColor(.black, for: .normal)
75 | backgroundColor = UIColor(
76 | named: colorNamePrefix,
77 | in: Bundle.module,
78 | compatibleWith: nil
79 | )
80 | layer.cornerRadius = 4.0
81 | titleLabel?.font = UIFont.boldSystemFont(ofSize: 12.0)
82 | }
83 |
84 | @available(*, unavailable)
85 | required init?(coder: NSCoder) {
86 | fatalError("init(coder:) has not been implemented")
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/Tests/CombineOperatorsCoreTests/CombineOperatorsCoreTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import CombineOperatorsCore
3 |
4 | final class CombineOperatorsCoreTests: XCTestCase {
5 | func testExample() {
6 | // This is an example of a functional test case.
7 | // Use XCTAssert and related functions to verify your tests produce the correct
8 | // results.
9 | XCTAssertEqual(CombineOperatorsCore().text, "Hello, World!")
10 | }
11 |
12 | static var allTests = [
13 | ("testExample", testExample),
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/Tests/CombineOperatorsCoreTests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | #if !canImport(ObjectiveC)
4 | public func allTests() -> [XCTestCaseEntry] {
5 | return [
6 | testCase(CombineOperatorsCoreTests.allTests),
7 | ]
8 | }
9 | #endif
10 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 |
3 | import CombineOperatorsCoreTests
4 |
5 | var tests = [XCTestCaseEntry]()
6 | tests += CombineOperatorsCoreTests.allTests()
7 | XCTMain(tests)
8 |
--------------------------------------------------------------------------------
/swiftgen.yml:
--------------------------------------------------------------------------------
1 | xcassets:
2 | - inputs: Sources/CombineOperatorsCore/Resources/Media.xcassets
3 | outputs:
4 | templateName: swift4
5 | output: Sources/CombineOperatorsCore/Resources/SwiftGen/Assets.swift
6 | params:
7 | enumName: Assets
8 | publicAccess: true
9 |
--------------------------------------------------------------------------------