├── .gitignore ├── .travis.yml ├── Example ├── Podfile ├── Podfile.lock ├── RxSwiftNotifications.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── RxSwiftNotifications.xcworkspace │ └── contents.xcworkspacedata ├── RxSwiftNotifications │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ └── ViewController.swift └── Tests │ └── Info.plist ├── LICENSE ├── Package.swift ├── README.md ├── RxSwiftNotifications.podspec ├── RxSwiftNotifications ├── Assets │ └── .gitkeep ├── Classes │ ├── .gitkeep │ ├── Extras │ │ ├── GenNotification.swift │ │ ├── Notifiable + Listeners.swift │ │ ├── NotificationsListener.swift │ │ └── NotificationsProxy.swift │ ├── NoParamNotifiable.swift │ ├── Notifiable.swift │ └── NotificationObservable.swift └── Tests │ ├── GenNotificationTests.swift │ ├── NoParamNotifiableTests.swift │ ├── NotifiableTests.swift │ ├── NotificationsProxyTests.swift │ ├── Town.swift │ └── UIKitNotifications.swift └── _Pods.xcodeproj /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | xcshareddata/ 20 | 21 | ## Other 22 | *.moved-aside 23 | *.xccheckout 24 | *.xcscmblueprint 25 | *.xcuserstate 26 | 27 | ## Obj-C/Swift specific 28 | *.hmap 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 | .build/ 44 | 45 | # CocoaPods 46 | # 47 | # We recommend against adding the Pods directory to your .gitignore. However 48 | # you should judge for yourself, the pros and cons are mentioned at: 49 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 50 | # 51 | # Pods/ 52 | 53 | # Carthage 54 | Carthage/Checkouts 55 | Carthage/Build 56 | 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots 68 | fastlane/test_output 69 | fastlane/README.md 70 | 71 | # fastlane builds 72 | .screeenshots/ 73 | *.mobileoprovision 74 | *.cer 75 | *.certSigningRequest 76 | *.p12 77 | *.ipa 78 | *.mobileprovision 79 | Pods 80 | .DS_Store 81 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | xcode_project: Example/RxSwiftNotifications.xcodeproj 2 | xcode_scheme: RxSwiftNotifications-Example 3 | xcode_destination: platform=iOS Simulator,OS=13.4,name=iPhone X 4 | 5 | osx_image: xcode11.4 6 | language: objective-c 7 | xcode_sdk: iphonesimulator12.1 8 | 9 | # cache: cocoapods 10 | podfile: Example/Podfile 11 | before_install: 12 | - gem install cocoapods # Since Travis is not always on latest version 13 | - pod install --repo-update --project-directory=Example 14 | script: 15 | - xcodebuild -showsdks 16 | - xcodebuild test -workspace Example/RxSwiftNotifications.xcworkspace -list 17 | - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/RxSwiftNotifications.xcworkspace -scheme RxSwiftNotifications_Example -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 8,OS=12.0' ONLY_ACTIVE_ARCH=NO | xcpretty 18 | - pod lib lint 19 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'RxSwiftNotifications_Example' do 4 | pod 'RxSwiftNotifications', :path => '../' 5 | 6 | target 'RxSwiftNotifications_Tests' do 7 | inherit! :search_paths 8 | 9 | 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - RxCocoa (5.0.0): 3 | - RxRelay (~> 5) 4 | - RxSwift (~> 5) 5 | - RxRelay (5.0.0): 6 | - RxSwift (~> 5) 7 | - RxSwift (5.0.0) 8 | - RxSwiftNotifications (0.0.1): 9 | - RxCocoa (~> 5.0) 10 | - RxSwift (~> 5.0) 11 | 12 | DEPENDENCIES: 13 | - RxSwiftNotifications (from `../`) 14 | 15 | SPEC REPOS: 16 | https://github.com/cocoapods/specs.git: 17 | - RxCocoa 18 | - RxRelay 19 | - RxSwift 20 | 21 | EXTERNAL SOURCES: 22 | RxSwiftNotifications: 23 | :path: "../" 24 | 25 | SPEC CHECKSUMS: 26 | RxCocoa: fcf32050ac00d801f34a7f71d5e8e7f23026dcd8 27 | RxRelay: 4f7409406a51a55cd88483f21ed898c234d60f18 28 | RxSwift: 8b0671caa829a763bbce7271095859121cbd895f 29 | RxSwiftNotifications: 536f52c4d9be50d3d94aee39017dcca71a2e2315 30 | 31 | PODFILE CHECKSUM: 6ebd38529f854250d37441ba3252409fb9b7ac38 32 | 33 | COCOAPODS: 1.7.5 34 | -------------------------------------------------------------------------------- /Example/RxSwiftNotifications.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4F9F522F8C5344F2262BD11E /* Pods_RxSwiftNotifications_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB6CE53EF9D67D298127F11C /* Pods_RxSwiftNotifications_Tests.framework */; }; 11 | 50C2EF9970E5714C92E10909 /* Pods_RxSwiftNotifications_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7712B9E07F89DAB281EBE072 /* Pods_RxSwiftNotifications_Example.framework */; }; 12 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 13 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; }; 14 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 15 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 16 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 17 | 9C86DE1021E10BC800C76017 /* NoParamNotifiableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C86DE0A21E10BC800C76017 /* NoParamNotifiableTests.swift */; }; 18 | 9C86DE1121E10BC800C76017 /* GenNotificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C86DE0B21E10BC800C76017 /* GenNotificationTests.swift */; }; 19 | 9C86DE1221E10BC800C76017 /* NotifiableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C86DE0C21E10BC800C76017 /* NotifiableTests.swift */; }; 20 | 9C86DE1321E10BC800C76017 /* NotificationsProxyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C86DE0D21E10BC800C76017 /* NotificationsProxyTests.swift */; }; 21 | 9C86DE1421E10BC800C76017 /* Town.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C86DE0E21E10BC800C76017 /* Town.swift */; }; 22 | 9C86DE1521E10BC800C76017 /* UIKitNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C86DE0F21E10BC800C76017 /* UIKitNotifications.swift */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXContainerItemProxy section */ 26 | 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = 607FACCF1AFB9204008FA782; 31 | remoteInfo = RxSwiftNotifications; 32 | }; 33 | /* End PBXContainerItemProxy section */ 34 | 35 | /* Begin PBXFileReference section */ 36 | 2434BD0274318B8562433DDF /* Pods-RxSwiftNotifications_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxSwiftNotifications_Example.release.xcconfig"; path = "Target Support Files/Pods-RxSwiftNotifications_Example/Pods-RxSwiftNotifications_Example.release.xcconfig"; sourceTree = ""; }; 37 | 4E51EC63A4AA92181712BA5E /* Pods-RxSwiftNotifications_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxSwiftNotifications_Tests.release.xcconfig"; path = "Target Support Files/Pods-RxSwiftNotifications_Tests/Pods-RxSwiftNotifications_Tests.release.xcconfig"; sourceTree = ""; }; 38 | 558CCB90B3B39B6E2DB202C6 /* Pods-RxSwiftNotifications_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxSwiftNotifications_Example.debug.xcconfig"; path = "Target Support Files/Pods-RxSwiftNotifications_Example/Pods-RxSwiftNotifications_Example.debug.xcconfig"; sourceTree = ""; }; 39 | 607FACD01AFB9204008FA782 /* RxSwiftNotifications_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RxSwiftNotifications_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 41 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 42 | 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 43 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 44 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 45 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 46 | 607FACE51AFB9204008FA782 /* RxSwiftNotifications_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RxSwiftNotifications_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | 70CF3FA12991951B6183ACA3 /* RxSwiftNotifications.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = RxSwiftNotifications.podspec; path = ../RxSwiftNotifications.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 49 | 7712B9E07F89DAB281EBE072 /* Pods_RxSwiftNotifications_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RxSwiftNotifications_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 9C86DE0A21E10BC800C76017 /* NoParamNotifiableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoParamNotifiableTests.swift; sourceTree = ""; }; 51 | 9C86DE0B21E10BC800C76017 /* GenNotificationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GenNotificationTests.swift; sourceTree = ""; }; 52 | 9C86DE0C21E10BC800C76017 /* NotifiableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotifiableTests.swift; sourceTree = ""; }; 53 | 9C86DE0D21E10BC800C76017 /* NotificationsProxyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationsProxyTests.swift; sourceTree = ""; }; 54 | 9C86DE0E21E10BC800C76017 /* Town.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Town.swift; sourceTree = ""; }; 55 | 9C86DE0F21E10BC800C76017 /* UIKitNotifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIKitNotifications.swift; sourceTree = ""; }; 56 | A2BF3450ADED28B6F2B7BDD6 /* Pods-RxSwiftNotifications_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RxSwiftNotifications_Tests.debug.xcconfig"; path = "Target Support Files/Pods-RxSwiftNotifications_Tests/Pods-RxSwiftNotifications_Tests.debug.xcconfig"; sourceTree = ""; }; 57 | B716FCB3CA6383135ED035F5 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 58 | BB6CE53EF9D67D298127F11C /* Pods_RxSwiftNotifications_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RxSwiftNotifications_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | EC9BFB6428DC4C292523F960 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | 607FACCD1AFB9204008FA782 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | 50C2EF9970E5714C92E10909 /* Pods_RxSwiftNotifications_Example.framework in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | 607FACE21AFB9204008FA782 /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | 4F9F522F8C5344F2262BD11E /* Pods_RxSwiftNotifications_Tests.framework in Frameworks */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | /* End PBXFrameworksBuildPhase section */ 80 | 81 | /* Begin PBXGroup section */ 82 | 607FACC71AFB9204008FA782 = { 83 | isa = PBXGroup; 84 | children = ( 85 | 607FACF51AFB993E008FA782 /* Podspec Metadata */, 86 | 607FACD21AFB9204008FA782 /* Example for RxSwiftNotifications */, 87 | 607FACE81AFB9204008FA782 /* Tests */, 88 | 607FACD11AFB9204008FA782 /* Products */, 89 | 659FD94768603E3CAC3B1E67 /* Pods */, 90 | 82E2CF310A9E618352EA16FE /* Frameworks */, 91 | ); 92 | sourceTree = ""; 93 | }; 94 | 607FACD11AFB9204008FA782 /* Products */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 607FACD01AFB9204008FA782 /* RxSwiftNotifications_Example.app */, 98 | 607FACE51AFB9204008FA782 /* RxSwiftNotifications_Tests.xctest */, 99 | ); 100 | name = Products; 101 | sourceTree = ""; 102 | }; 103 | 607FACD21AFB9204008FA782 /* Example for RxSwiftNotifications */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */, 107 | 607FACD71AFB9204008FA782 /* ViewController.swift */, 108 | 607FACD91AFB9204008FA782 /* Main.storyboard */, 109 | 607FACDC1AFB9204008FA782 /* Images.xcassets */, 110 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 111 | 607FACD31AFB9204008FA782 /* Supporting Files */, 112 | ); 113 | name = "Example for RxSwiftNotifications"; 114 | path = RxSwiftNotifications; 115 | sourceTree = ""; 116 | }; 117 | 607FACD31AFB9204008FA782 /* Supporting Files */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 607FACD41AFB9204008FA782 /* Info.plist */, 121 | ); 122 | name = "Supporting Files"; 123 | sourceTree = ""; 124 | }; 125 | 607FACE81AFB9204008FA782 /* Tests */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 9C86DE0B21E10BC800C76017 /* GenNotificationTests.swift */, 129 | 9C86DE0A21E10BC800C76017 /* NoParamNotifiableTests.swift */, 130 | 9C86DE0C21E10BC800C76017 /* NotifiableTests.swift */, 131 | 9C86DE0D21E10BC800C76017 /* NotificationsProxyTests.swift */, 132 | 9C86DE0E21E10BC800C76017 /* Town.swift */, 133 | 9C86DE0F21E10BC800C76017 /* UIKitNotifications.swift */, 134 | 607FACE91AFB9204008FA782 /* Supporting Files */, 135 | ); 136 | name = Tests; 137 | path = ../RxSwiftNotifications/Tests; 138 | sourceTree = ""; 139 | }; 140 | 607FACE91AFB9204008FA782 /* Supporting Files */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 607FACEA1AFB9204008FA782 /* Info.plist */, 144 | ); 145 | name = "Supporting Files"; 146 | sourceTree = ""; 147 | }; 148 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 70CF3FA12991951B6183ACA3 /* RxSwiftNotifications.podspec */, 152 | B716FCB3CA6383135ED035F5 /* README.md */, 153 | EC9BFB6428DC4C292523F960 /* LICENSE */, 154 | ); 155 | name = "Podspec Metadata"; 156 | sourceTree = ""; 157 | }; 158 | 659FD94768603E3CAC3B1E67 /* Pods */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | 558CCB90B3B39B6E2DB202C6 /* Pods-RxSwiftNotifications_Example.debug.xcconfig */, 162 | 2434BD0274318B8562433DDF /* Pods-RxSwiftNotifications_Example.release.xcconfig */, 163 | A2BF3450ADED28B6F2B7BDD6 /* Pods-RxSwiftNotifications_Tests.debug.xcconfig */, 164 | 4E51EC63A4AA92181712BA5E /* Pods-RxSwiftNotifications_Tests.release.xcconfig */, 165 | ); 166 | path = Pods; 167 | sourceTree = ""; 168 | }; 169 | 82E2CF310A9E618352EA16FE /* Frameworks */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | 7712B9E07F89DAB281EBE072 /* Pods_RxSwiftNotifications_Example.framework */, 173 | BB6CE53EF9D67D298127F11C /* Pods_RxSwiftNotifications_Tests.framework */, 174 | ); 175 | name = Frameworks; 176 | sourceTree = ""; 177 | }; 178 | /* End PBXGroup section */ 179 | 180 | /* Begin PBXNativeTarget section */ 181 | 607FACCF1AFB9204008FA782 /* RxSwiftNotifications_Example */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "RxSwiftNotifications_Example" */; 184 | buildPhases = ( 185 | B2825DC588E18F3360AF0C0C /* [CP] Check Pods Manifest.lock */, 186 | 607FACCC1AFB9204008FA782 /* Sources */, 187 | 607FACCD1AFB9204008FA782 /* Frameworks */, 188 | 607FACCE1AFB9204008FA782 /* Resources */, 189 | 60A3D812532254A19CE87114 /* [CP] Embed Pods Frameworks */, 190 | ); 191 | buildRules = ( 192 | ); 193 | dependencies = ( 194 | ); 195 | name = RxSwiftNotifications_Example; 196 | productName = RxSwiftNotifications; 197 | productReference = 607FACD01AFB9204008FA782 /* RxSwiftNotifications_Example.app */; 198 | productType = "com.apple.product-type.application"; 199 | }; 200 | 607FACE41AFB9204008FA782 /* RxSwiftNotifications_Tests */ = { 201 | isa = PBXNativeTarget; 202 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "RxSwiftNotifications_Tests" */; 203 | buildPhases = ( 204 | 0A8448841D7AFD7EB5CAFAE4 /* [CP] Check Pods Manifest.lock */, 205 | 607FACE11AFB9204008FA782 /* Sources */, 206 | 607FACE21AFB9204008FA782 /* Frameworks */, 207 | 607FACE31AFB9204008FA782 /* Resources */, 208 | ); 209 | buildRules = ( 210 | ); 211 | dependencies = ( 212 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */, 213 | ); 214 | name = RxSwiftNotifications_Tests; 215 | productName = Tests; 216 | productReference = 607FACE51AFB9204008FA782 /* RxSwiftNotifications_Tests.xctest */; 217 | productType = "com.apple.product-type.bundle.unit-test"; 218 | }; 219 | /* End PBXNativeTarget section */ 220 | 221 | /* Begin PBXProject section */ 222 | 607FACC81AFB9204008FA782 /* Project object */ = { 223 | isa = PBXProject; 224 | attributes = { 225 | LastSwiftUpdateCheck = 0830; 226 | LastUpgradeCheck = 1030; 227 | ORGANIZATIONNAME = CocoaPods; 228 | TargetAttributes = { 229 | 607FACCF1AFB9204008FA782 = { 230 | CreatedOnToolsVersion = 6.3.1; 231 | LastSwiftMigration = 0900; 232 | }; 233 | 607FACE41AFB9204008FA782 = { 234 | CreatedOnToolsVersion = 6.3.1; 235 | LastSwiftMigration = 1010; 236 | TestTargetID = 607FACCF1AFB9204008FA782; 237 | }; 238 | }; 239 | }; 240 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "RxSwiftNotifications" */; 241 | compatibilityVersion = "Xcode 3.2"; 242 | developmentRegion = en; 243 | hasScannedForEncodings = 0; 244 | knownRegions = ( 245 | en, 246 | Base, 247 | ); 248 | mainGroup = 607FACC71AFB9204008FA782; 249 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */; 250 | projectDirPath = ""; 251 | projectRoot = ""; 252 | targets = ( 253 | 607FACCF1AFB9204008FA782 /* RxSwiftNotifications_Example */, 254 | 607FACE41AFB9204008FA782 /* RxSwiftNotifications_Tests */, 255 | ); 256 | }; 257 | /* End PBXProject section */ 258 | 259 | /* Begin PBXResourcesBuildPhase section */ 260 | 607FACCE1AFB9204008FA782 /* Resources */ = { 261 | isa = PBXResourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */, 265 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 266 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | }; 270 | 607FACE31AFB9204008FA782 /* Resources */ = { 271 | isa = PBXResourcesBuildPhase; 272 | buildActionMask = 2147483647; 273 | files = ( 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | }; 277 | /* End PBXResourcesBuildPhase section */ 278 | 279 | /* Begin PBXShellScriptBuildPhase section */ 280 | 0A8448841D7AFD7EB5CAFAE4 /* [CP] Check Pods Manifest.lock */ = { 281 | isa = PBXShellScriptBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | ); 285 | inputFileListPaths = ( 286 | ); 287 | inputPaths = ( 288 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 289 | "${PODS_ROOT}/Manifest.lock", 290 | ); 291 | name = "[CP] Check Pods Manifest.lock"; 292 | outputFileListPaths = ( 293 | ); 294 | outputPaths = ( 295 | "$(DERIVED_FILE_DIR)/Pods-RxSwiftNotifications_Tests-checkManifestLockResult.txt", 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | shellPath = /bin/sh; 299 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 300 | showEnvVarsInLog = 0; 301 | }; 302 | 60A3D812532254A19CE87114 /* [CP] Embed Pods Frameworks */ = { 303 | isa = PBXShellScriptBuildPhase; 304 | buildActionMask = 2147483647; 305 | files = ( 306 | ); 307 | inputPaths = ( 308 | "${PODS_ROOT}/Target Support Files/Pods-RxSwiftNotifications_Example/Pods-RxSwiftNotifications_Example-frameworks.sh", 309 | "${BUILT_PRODUCTS_DIR}/RxCocoa/RxCocoa.framework", 310 | "${BUILT_PRODUCTS_DIR}/RxRelay/RxRelay.framework", 311 | "${BUILT_PRODUCTS_DIR}/RxSwift/RxSwift.framework", 312 | "${BUILT_PRODUCTS_DIR}/RxSwiftNotifications/RxSwiftNotifications.framework", 313 | ); 314 | name = "[CP] Embed Pods Frameworks"; 315 | outputPaths = ( 316 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework", 317 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxRelay.framework", 318 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwift.framework", 319 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwiftNotifications.framework", 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | shellPath = /bin/sh; 323 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RxSwiftNotifications_Example/Pods-RxSwiftNotifications_Example-frameworks.sh\"\n"; 324 | showEnvVarsInLog = 0; 325 | }; 326 | B2825DC588E18F3360AF0C0C /* [CP] Check Pods Manifest.lock */ = { 327 | isa = PBXShellScriptBuildPhase; 328 | buildActionMask = 2147483647; 329 | files = ( 330 | ); 331 | inputFileListPaths = ( 332 | ); 333 | inputPaths = ( 334 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 335 | "${PODS_ROOT}/Manifest.lock", 336 | ); 337 | name = "[CP] Check Pods Manifest.lock"; 338 | outputFileListPaths = ( 339 | ); 340 | outputPaths = ( 341 | "$(DERIVED_FILE_DIR)/Pods-RxSwiftNotifications_Example-checkManifestLockResult.txt", 342 | ); 343 | runOnlyForDeploymentPostprocessing = 0; 344 | shellPath = /bin/sh; 345 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 346 | showEnvVarsInLog = 0; 347 | }; 348 | /* End PBXShellScriptBuildPhase section */ 349 | 350 | /* Begin PBXSourcesBuildPhase section */ 351 | 607FACCC1AFB9204008FA782 /* Sources */ = { 352 | isa = PBXSourcesBuildPhase; 353 | buildActionMask = 2147483647; 354 | files = ( 355 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, 356 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 357 | ); 358 | runOnlyForDeploymentPostprocessing = 0; 359 | }; 360 | 607FACE11AFB9204008FA782 /* Sources */ = { 361 | isa = PBXSourcesBuildPhase; 362 | buildActionMask = 2147483647; 363 | files = ( 364 | 9C86DE1021E10BC800C76017 /* NoParamNotifiableTests.swift in Sources */, 365 | 9C86DE1221E10BC800C76017 /* NotifiableTests.swift in Sources */, 366 | 9C86DE1121E10BC800C76017 /* GenNotificationTests.swift in Sources */, 367 | 9C86DE1421E10BC800C76017 /* Town.swift in Sources */, 368 | 9C86DE1321E10BC800C76017 /* NotificationsProxyTests.swift in Sources */, 369 | 9C86DE1521E10BC800C76017 /* UIKitNotifications.swift in Sources */, 370 | ); 371 | runOnlyForDeploymentPostprocessing = 0; 372 | }; 373 | /* End PBXSourcesBuildPhase section */ 374 | 375 | /* Begin PBXTargetDependency section */ 376 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = { 377 | isa = PBXTargetDependency; 378 | target = 607FACCF1AFB9204008FA782 /* RxSwiftNotifications_Example */; 379 | targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */; 380 | }; 381 | /* End PBXTargetDependency section */ 382 | 383 | /* Begin PBXVariantGroup section */ 384 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = { 385 | isa = PBXVariantGroup; 386 | children = ( 387 | 607FACDA1AFB9204008FA782 /* Base */, 388 | ); 389 | name = Main.storyboard; 390 | sourceTree = ""; 391 | }; 392 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { 393 | isa = PBXVariantGroup; 394 | children = ( 395 | 607FACDF1AFB9204008FA782 /* Base */, 396 | ); 397 | name = LaunchScreen.xib; 398 | sourceTree = ""; 399 | }; 400 | /* End PBXVariantGroup section */ 401 | 402 | /* Begin XCBuildConfiguration section */ 403 | 607FACED1AFB9204008FA782 /* Debug */ = { 404 | isa = XCBuildConfiguration; 405 | buildSettings = { 406 | ALWAYS_SEARCH_USER_PATHS = NO; 407 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 408 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 409 | CLANG_CXX_LIBRARY = "libc++"; 410 | CLANG_ENABLE_MODULES = YES; 411 | CLANG_ENABLE_OBJC_ARC = YES; 412 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 413 | CLANG_WARN_BOOL_CONVERSION = YES; 414 | CLANG_WARN_COMMA = YES; 415 | CLANG_WARN_CONSTANT_CONVERSION = YES; 416 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 417 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 418 | CLANG_WARN_EMPTY_BODY = YES; 419 | CLANG_WARN_ENUM_CONVERSION = YES; 420 | CLANG_WARN_INFINITE_RECURSION = YES; 421 | CLANG_WARN_INT_CONVERSION = YES; 422 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 423 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 424 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 425 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 426 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 427 | CLANG_WARN_STRICT_PROTOTYPES = YES; 428 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 429 | CLANG_WARN_UNREACHABLE_CODE = YES; 430 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 431 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 432 | COPY_PHASE_STRIP = NO; 433 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 434 | ENABLE_STRICT_OBJC_MSGSEND = YES; 435 | ENABLE_TESTABILITY = YES; 436 | GCC_C_LANGUAGE_STANDARD = gnu99; 437 | GCC_DYNAMIC_NO_PIC = NO; 438 | GCC_NO_COMMON_BLOCKS = YES; 439 | GCC_OPTIMIZATION_LEVEL = 0; 440 | GCC_PREPROCESSOR_DEFINITIONS = ( 441 | "DEBUG=1", 442 | "$(inherited)", 443 | ); 444 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 445 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 446 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 447 | GCC_WARN_UNDECLARED_SELECTOR = YES; 448 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 449 | GCC_WARN_UNUSED_FUNCTION = YES; 450 | GCC_WARN_UNUSED_VARIABLE = YES; 451 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 452 | MTL_ENABLE_DEBUG_INFO = YES; 453 | ONLY_ACTIVE_ARCH = YES; 454 | SDKROOT = iphoneos; 455 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 456 | SWIFT_VERSION = 5.0; 457 | }; 458 | name = Debug; 459 | }; 460 | 607FACEE1AFB9204008FA782 /* Release */ = { 461 | isa = XCBuildConfiguration; 462 | buildSettings = { 463 | ALWAYS_SEARCH_USER_PATHS = NO; 464 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 465 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 466 | CLANG_CXX_LIBRARY = "libc++"; 467 | CLANG_ENABLE_MODULES = YES; 468 | CLANG_ENABLE_OBJC_ARC = YES; 469 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 470 | CLANG_WARN_BOOL_CONVERSION = YES; 471 | CLANG_WARN_COMMA = YES; 472 | CLANG_WARN_CONSTANT_CONVERSION = YES; 473 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 474 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 475 | CLANG_WARN_EMPTY_BODY = YES; 476 | CLANG_WARN_ENUM_CONVERSION = YES; 477 | CLANG_WARN_INFINITE_RECURSION = YES; 478 | CLANG_WARN_INT_CONVERSION = YES; 479 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 480 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 481 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 482 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 483 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 484 | CLANG_WARN_STRICT_PROTOTYPES = YES; 485 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 486 | CLANG_WARN_UNREACHABLE_CODE = YES; 487 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 488 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 489 | COPY_PHASE_STRIP = NO; 490 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 491 | ENABLE_NS_ASSERTIONS = NO; 492 | ENABLE_STRICT_OBJC_MSGSEND = YES; 493 | GCC_C_LANGUAGE_STANDARD = gnu99; 494 | GCC_NO_COMMON_BLOCKS = YES; 495 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 496 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 497 | GCC_WARN_UNDECLARED_SELECTOR = YES; 498 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 499 | GCC_WARN_UNUSED_FUNCTION = YES; 500 | GCC_WARN_UNUSED_VARIABLE = YES; 501 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 502 | MTL_ENABLE_DEBUG_INFO = NO; 503 | SDKROOT = iphoneos; 504 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 505 | SWIFT_VERSION = 5.0; 506 | VALIDATE_PRODUCT = YES; 507 | }; 508 | name = Release; 509 | }; 510 | 607FACF01AFB9204008FA782 /* Debug */ = { 511 | isa = XCBuildConfiguration; 512 | baseConfigurationReference = 558CCB90B3B39B6E2DB202C6 /* Pods-RxSwiftNotifications_Example.debug.xcconfig */; 513 | buildSettings = { 514 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 515 | INFOPLIST_FILE = RxSwiftNotifications/Info.plist; 516 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 517 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 518 | MODULE_NAME = ExampleApp; 519 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 520 | PRODUCT_NAME = "$(TARGET_NAME)"; 521 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 522 | SWIFT_VERSION = 5.0; 523 | }; 524 | name = Debug; 525 | }; 526 | 607FACF11AFB9204008FA782 /* Release */ = { 527 | isa = XCBuildConfiguration; 528 | baseConfigurationReference = 2434BD0274318B8562433DDF /* Pods-RxSwiftNotifications_Example.release.xcconfig */; 529 | buildSettings = { 530 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 531 | INFOPLIST_FILE = RxSwiftNotifications/Info.plist; 532 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 533 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 534 | MODULE_NAME = ExampleApp; 535 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 536 | PRODUCT_NAME = "$(TARGET_NAME)"; 537 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 538 | SWIFT_VERSION = 5.0; 539 | }; 540 | name = Release; 541 | }; 542 | 607FACF31AFB9204008FA782 /* Debug */ = { 543 | isa = XCBuildConfiguration; 544 | baseConfigurationReference = A2BF3450ADED28B6F2B7BDD6 /* Pods-RxSwiftNotifications_Tests.debug.xcconfig */; 545 | buildSettings = { 546 | CLANG_ENABLE_MODULES = YES; 547 | FRAMEWORK_SEARCH_PATHS = ( 548 | "$(SDKROOT)/Developer/Library/Frameworks", 549 | "$(inherited)", 550 | ); 551 | GCC_PREPROCESSOR_DEFINITIONS = ( 552 | "DEBUG=1", 553 | "$(inherited)", 554 | ); 555 | INFOPLIST_FILE = Tests/Info.plist; 556 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 557 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 558 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 559 | PRODUCT_NAME = "$(TARGET_NAME)"; 560 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 561 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 562 | SWIFT_VERSION = 5.0; 563 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RxSwiftNotifications_Example.app/RxSwiftNotifications_Example"; 564 | }; 565 | name = Debug; 566 | }; 567 | 607FACF41AFB9204008FA782 /* Release */ = { 568 | isa = XCBuildConfiguration; 569 | baseConfigurationReference = 4E51EC63A4AA92181712BA5E /* Pods-RxSwiftNotifications_Tests.release.xcconfig */; 570 | buildSettings = { 571 | CLANG_ENABLE_MODULES = YES; 572 | FRAMEWORK_SEARCH_PATHS = ( 573 | "$(SDKROOT)/Developer/Library/Frameworks", 574 | "$(inherited)", 575 | ); 576 | INFOPLIST_FILE = Tests/Info.plist; 577 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 578 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 579 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 580 | PRODUCT_NAME = "$(TARGET_NAME)"; 581 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 582 | SWIFT_VERSION = 5.0; 583 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RxSwiftNotifications_Example.app/RxSwiftNotifications_Example"; 584 | }; 585 | name = Release; 586 | }; 587 | /* End XCBuildConfiguration section */ 588 | 589 | /* Begin XCConfigurationList section */ 590 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "RxSwiftNotifications" */ = { 591 | isa = XCConfigurationList; 592 | buildConfigurations = ( 593 | 607FACED1AFB9204008FA782 /* Debug */, 594 | 607FACEE1AFB9204008FA782 /* Release */, 595 | ); 596 | defaultConfigurationIsVisible = 0; 597 | defaultConfigurationName = Release; 598 | }; 599 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "RxSwiftNotifications_Example" */ = { 600 | isa = XCConfigurationList; 601 | buildConfigurations = ( 602 | 607FACF01AFB9204008FA782 /* Debug */, 603 | 607FACF11AFB9204008FA782 /* Release */, 604 | ); 605 | defaultConfigurationIsVisible = 0; 606 | defaultConfigurationName = Release; 607 | }; 608 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "RxSwiftNotifications_Tests" */ = { 609 | isa = XCConfigurationList; 610 | buildConfigurations = ( 611 | 607FACF31AFB9204008FA782 /* Debug */, 612 | 607FACF41AFB9204008FA782 /* Release */, 613 | ); 614 | defaultConfigurationIsVisible = 0; 615 | defaultConfigurationName = Release; 616 | }; 617 | /* End XCConfigurationList section */ 618 | }; 619 | rootObject = 607FACC81AFB9204008FA782 /* Project object */; 620 | } 621 | -------------------------------------------------------------------------------- /Example/RxSwiftNotifications.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/RxSwiftNotifications.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/RxSwiftNotifications/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // RxSwiftNotifications 4 | // 5 | // Created by leandromperez@gmail.com on 01/05/2019. 6 | // Copyright (c) 2019 leandromperez@gmail.com. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | return true 19 | } 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Example/RxSwiftNotifications/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/RxSwiftNotifications/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 | -------------------------------------------------------------------------------- /Example/RxSwiftNotifications/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Example/RxSwiftNotifications/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Example/RxSwiftNotifications/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // RxSwiftNotifications 4 | // 5 | // Created by leandromperez@gmail.com on 01/05/2019. 6 | // Copyright (c) 2019 leandromperez@gmail.com. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import RxSwiftNotifications 11 | import RxSwift 12 | 13 | class ViewController: UIViewController { 14 | 15 | let disposeBag = DisposeBag() 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | //Example of a standard notification listener. Checkout the tests for more examples 20 | UIApplication.didBecomeActiveNotification 21 | .addListener { 22 | print("App did become active") 23 | } 24 | .disposed(by: disposeBag) 25 | } 26 | 27 | override func didReceiveMemoryWarning() { 28 | super.didReceiveMemoryWarning() 29 | // Dispose of any resources that can be recreated. 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /Example/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 leandromperez@gmail.com 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. -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "RxSwiftNotifications", 7 | platforms: [ 8 | .iOS(.v10) 9 | ], 10 | products: [ 11 | .library(name: "RxSwiftNotifications", targets: ["RxSwiftNotifications"]) 12 | ], 13 | dependencies: [ 14 | .package(url: "https://github.com/ReactiveX/RxSwift", .upToNextMajor(from: "5.0.0")), 15 | ], 16 | targets: [ 17 | .target( 18 | name: "RxSwiftNotifications", 19 | dependencies: ["RxSwift", "RxCocoa"], 20 | path: "RxSwiftNotifications/Classes" 21 | ), 22 | .target( 23 | name: "RxSwiftNotificationsTests", 24 | dependencies: ["RxSwift", "RxCocoa", "RxSwiftNotifications"], 25 | path: "RxSwiftNotifications/Tests" 26 | ) 27 | ], 28 | swiftLanguageVersions: [.v5] 29 | ) 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RxSwiftNotifications 2 | 3 | [![Build Status](https://travis-ci.org/leandromperez/rxswift-notifications.svg?branch=master)](https://travis-ci.org/leandromperez/rxswift-notifications) 4 | [![Version](https://img.shields.io/cocoapods/v/RxSwiftNotifications.svg?style=flat)](https://cocoapods.org/pods/RxSwiftNotifications) 5 | [![License](https://img.shields.io/cocoapods/l/RxSwiftNotifications.svg?style=flat)](https://cocoapods.org/pods/RxSwiftNotifications) 6 | [![Platform](https://img.shields.io/cocoapods/p/RxSwiftNotifications.svg?style=flat)](https://cocoapods.org/pods/RxSwiftNotifications) 7 | 8 | ## Introduction 9 | This project contains some extensions on top of NSNotificationCenter that allows the creation of strong-typed notifications. My goal was to have a type-safe, reactive and easier-to-use mechanism. 10 | 11 | ## How to use them? 12 | 13 | ### 1. Declare the notification type 14 | 15 | Create a **struct, enum**, or **class**, that will represent the notification using the type system. : 16 | 17 | ```swift 18 | enum UserNotification : String, Notifiable { 19 | typealias ParameterType = User 20 | 21 | case userDidLogin 22 | case userDidLogout 23 | } 24 | ``` 25 | ### 1. Subscribe to the notification 26 | 27 | Subscribe to the notification and use the parameter directly. 28 | 29 | ⚠️ Notice that this is **type safe**, you don’t need to extract the parameter and cast it! 30 | The extensions will safely do that. 31 | 32 | #### Option 1: Add a listener to the notification 33 | 34 | ```swift 35 | UserNotification.userDidLogin 36 | .addListener { [unowned self] (user: User) in 37 | self.loadPreferences(of: user) 38 | } 39 | .disposed(by: disposeBag) 40 | ``` 41 | 42 | #### Option 2: You can also treat the notification like a regular Observable: 43 | 44 | ```swift 45 | UserNotification.userDidLogin.asObservable() 46 | .subscribe(onNext:{ [unowned self] (user:User) in 47 | self.loadPreferences(of: user) 48 | }) 49 | .disposed(by: disposeBag) 50 | ``` 51 | ## Notifications with no parameters. 52 | NoParamsNotifiable, lets you post notifications with no parameters: 53 | ```swift 54 | 55 | enum CalendarNotification : NoParamsNotifiable { 56 | case calendarDidSynchronize 57 | } 58 | 59 | CalendarNotification.caledarDidSynchronize 60 | .addListener{ 61 | print("Calendar synchronized") 62 | } 63 | .disposed(by:disposeBag) 64 | ``` 65 | 66 | ## Test cases 67 | 68 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 69 | It contains a set of unit tests that explain how to use other features. 70 | 71 | ## Requirements 72 | 73 | ## Installation 74 | 75 | RxSwiftNotifications is available through [CocoaPods](https://cocoapods.org). To install 76 | it, simply add the following line to your Podfile: 77 | 78 | ```ruby 79 | pod 'RxSwiftNotifications' 80 | ``` 81 | 82 | ## Author 83 | 84 | Leandro Perez, leandromperez@gmail.com 85 | 86 | ## License 87 | 88 | RxSwiftNotifications is available under the MIT license. See the LICENSE file for more info. 89 | -------------------------------------------------------------------------------- /RxSwiftNotifications.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "RxSwiftNotifications" 4 | s.version = "0.0.1" 5 | s.platform = :ios 6 | s.ios.deployment_target = '10.0' 7 | s.requires_arc = true 8 | s.summary = "A small group of extensions on top of NSNotification center and RxSwift that allows for strong-typed notifications" 9 | s.description = <<-DESC 10 | Have strong-typed notifications and parameters. Easyly register listeners and access the parameters of the notification with no boilerplate code. Transform the notification in a rx observavble to react to it in a seamless way. 11 | DESC 12 | s.homepage = "https://github.com/leandromperez/rxswift-notifications" 13 | s.license = { :type => "MIT", :file => "LICENSE" } 14 | s.author = { "Leandro Perez" => "leandromperez@gmail.com" } 15 | s.social_media_url = "https://medium.com/@leandromperez" 16 | s.source = { :git => "https://github.com/leandromperez/rxswift-notifications.git", :tag => "#{s.version}" } 17 | s.source_files = 'RxSwiftNotifications/Classes/**/*' 18 | 19 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 20 | s.framework = "UIKit" 21 | 22 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 23 | s.swift_version = "5.0" 24 | s.framework = "UIKit" 25 | s.dependency "RxSwift", "~> 5.0" 26 | s.dependency "RxCocoa", "~> 5.0" 27 | 28 | end 29 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandromperez/rxswift-notifications/ee3ec535d2245ea2a2fb4045fbbadf59a56ce124/RxSwiftNotifications/Assets/.gitkeep -------------------------------------------------------------------------------- /RxSwiftNotifications/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leandromperez/rxswift-notifications/ee3ec535d2245ea2a2fb4045fbbadf59a56ce124/RxSwiftNotifications/Classes/.gitkeep -------------------------------------------------------------------------------- /RxSwiftNotifications/Classes/Extras/GenNotification.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GenNotification.swift 3 | // Notifications 4 | // 5 | // Created by Leandro Perez on 11/24/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import RxSwift 11 | 12 | public struct GenNotification : Notifiable { 13 | 14 | public typealias ParameterType = T 15 | 16 | private(set) public var identifier : String 17 | 18 | public init (id:String) { 19 | self.identifier = id 20 | } 21 | 22 | public func asObservableNotification() -> Observable { 23 | return NotificationCenter.default.rx.notification(self.notificationName) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Classes/Extras/Notifiable + Listeners.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Notifiable + Listeners.swift 3 | // Notifications 4 | // 5 | // Created by Leandro Perez on 11/26/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import RxSwift 11 | 12 | public extension Notifiable { 13 | 14 | func addListener(handler: @escaping (ParameterType) -> Void) -> Disposable { 15 | return self.asObservable().subscribe(onNext: handler) 16 | } 17 | 18 | func addListener(handler: @escaping (ParameterType, Notification) -> Void) -> Disposable { 19 | return self.notificationObservable() 20 | .subscribe(onNext: { notification in 21 | guard let parameter = notification.userInfo?[self.identifier] as? ParameterType 22 | else {fatalError("The notification must have the right parameter")} 23 | handler(parameter, notification) 24 | }) 25 | } 26 | 27 | func addListener(weak object:T, handler: @escaping (T, ParameterType) -> Void ) -> Disposable { 28 | return self.addListener(weak: object, handler: curry(handler)) 29 | } 30 | 31 | func addListener(weak object:T, handler: @escaping (T) -> (ParameterType) -> Void ) -> Disposable { 32 | return self.addListener { [weak object] (parameter) in 33 | guard let object = object else {return} 34 | 35 | handler(object)(parameter) 36 | } 37 | } 38 | 39 | func addNoParamsListener(weak object:T, _ handler: @escaping (T) -> () -> Void ) -> Disposable { 40 | 41 | return self.addListener { [weak object] (_) in 42 | guard let object = object else {return} 43 | 44 | handler(object)() 45 | } 46 | } 47 | } 48 | 49 | //MARK:- private 50 | private func curry(_ f:@escaping (A,B) -> Void ) -> (A) -> (B) -> Void { 51 | return { a in { b in f(a,b) } } 52 | } 53 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Classes/Extras/NotificationsListener.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationsListener.swift 3 | // Notifications 4 | // 5 | // Created by Leandro Perez on 11/24/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import RxSwift 12 | 13 | public protocol NotificationsListener { 14 | func listenToNotification(named name:Notification.Name, do handler:@escaping (Notification) -> Void ) -> Disposable 15 | 16 | func listenTo( notification : T, do handler: @escaping () -> Void ) -> Disposable 17 | func listenTo( notification : T, do handler: @escaping (Notification) -> Void ) -> Disposable 18 | 19 | func listenTo( notification : T, do handler: @escaping () -> Void ) -> Disposable 20 | func listenTo( notification : T, do handler: @escaping (T.ParameterType) -> Void ) -> Disposable 21 | func listenTo( notification : T, do handler: @escaping (T.ParameterType, Notification) -> Void ) -> Disposable 22 | } 23 | 24 | public extension NotificationsListener { 25 | 26 | func listenToNotification(named name:Notification.Name, do handler:@escaping (Notification) -> Void ) -> Disposable { 27 | return NotificationCenter.default.rx 28 | .notification(name) 29 | .subscribe(onNext: handler) 30 | } 31 | 32 | func listenTo( notification : T, do handler: @escaping(Notification) -> Void ) -> Disposable { 33 | return notification.addListener(handler: handler) 34 | } 35 | 36 | func listenTo( notification : T, do handler: @escaping () -> Void ) -> Disposable { 37 | return notification.addListener(handler: handler) 38 | } 39 | 40 | func listenTo( notification : T, do handler: @escaping () -> Void ) -> Disposable { 41 | return notification.addListener{ _ in handler() } 42 | } 43 | 44 | func listenTo( notification : T, do handler: @escaping (T.ParameterType) -> Void ) -> Disposable { 45 | return notification.addListener(handler: handler) 46 | } 47 | 48 | func listenTo( notification : T, do handler: @escaping (T.ParameterType, Notification) -> Void ) -> Disposable { 49 | return notification.addListener(handler: handler) 50 | } 51 | } 52 | 53 | extension UIViewController : NotificationsListener {} 54 | 55 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Classes/Extras/NotificationsProxy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationsProxy.swift 3 | // Notifications 4 | // 5 | // Created by Leandro Perez on 11/24/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import RxSwift 11 | 12 | open class NotificationsProxy { 13 | private let disposeBag = DisposeBag() 14 | public var subject : Subject 15 | 16 | public init(subject: Subject) { 17 | self.subject = subject 18 | 19 | self.listenToNotifications() 20 | } 21 | 22 | open func listenToNotifications() { 23 | assertionFailure("override in subclasses") 24 | } 25 | 26 | public func listenTo( notification : T, do handler: @escaping(inout Subject, Notification) -> Void ) { 27 | notification.addListener { [unowned self] (notification) in 28 | handler(&self.subject, notification) 29 | } 30 | .disposed(by: self.disposeBag) 31 | } 32 | 33 | public func listenTo( notification : T, do handler: @escaping(inout Subject) -> Void ) { 34 | notification 35 | .addListener { [unowned self] in 36 | handler(&self.subject) 37 | } 38 | .disposed(by: self.disposeBag) 39 | } 40 | 41 | public func listenTo( notification : T, do handler: @escaping(inout Subject) -> Void ) { 42 | notification 43 | .addListener { [unowned self] (_) in 44 | handler(&self.subject) 45 | } 46 | .disposed(by: self.disposeBag) 47 | } 48 | 49 | public func listenTo( notification : T, do handler: @escaping(inout Subject) -> (T.ParameterType) -> Void ) { 50 | notification 51 | .addListener { [unowned self] (parameter: T.ParameterType) in 52 | handler(&self.subject)(parameter) 53 | } 54 | .disposed(by: self.disposeBag) 55 | } 56 | 57 | public func listenTo( notification : T, do handler: @escaping(inout Subject, T.ParameterType) -> Void ) { 58 | notification 59 | .addListener { [unowned self] (parameter: T.ParameterType) in 60 | handler(&self.subject, parameter) 61 | } 62 | .disposed(by: self.disposeBag) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Classes/NoParamNotifiable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NoParamNotificable.swift 3 | // Notifications 4 | // 5 | // Created by Leandro Perez on 11/24/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import RxCocoa 11 | import RxSwift 12 | 13 | public protocol NoParamNotifiable : NotificationObservable { 14 | func post() 15 | func addListener(handler: @escaping () -> Void) -> Disposable 16 | func addListener(handler: @escaping (Notification) -> Void) -> Disposable 17 | func addListener(weak obj:A, handler: @escaping (A) -> () -> Void) -> Disposable 18 | } 19 | 20 | public extension NoParamNotifiable { 21 | 22 | func post() { 23 | NotificationCenter.default.post(name: self.notificationName, object: nil, userInfo: nil) 24 | } 25 | 26 | func addListener(handler: @escaping () -> Void) -> Disposable { 27 | return self.notificationObservable() 28 | .subscribe(onNext: { (_) in 29 | handler() 30 | }) 31 | } 32 | 33 | func addListener(handler: @escaping (Notification) -> Void) -> Disposable { 34 | return self.notificationObservable() 35 | .subscribe(onNext: { notification in 36 | handler(notification) 37 | }) 38 | } 39 | 40 | func addListener(weak obj:A, handler: @escaping (A) -> () -> Void) -> Disposable { 41 | return self.addListener { [weak obj] in 42 | guard let obj = obj else {return} 43 | 44 | handler(obj)() 45 | } 46 | } 47 | } 48 | 49 | extension NSNotification.Name : NoParamNotifiable { 50 | public var notificationName : Notification.Name { 51 | return self 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Classes/Notifiable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Notificable.swift 3 | // Notifications 4 | // 5 | // Created by Leandro Perez on 11/24/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import RxSwift 11 | 12 | public protocol Notifiable : NotificationObservable { 13 | associatedtype ParameterType 14 | 15 | func post(parameter:ParameterType) 16 | func asObservable() -> Observable 17 | } 18 | 19 | public extension Notifiable { 20 | 21 | func post(parameter: ParameterType) { 22 | let userInfo : [AnyHashable: Any]? = [self.identifier : parameter] 23 | NotificationCenter.default.post(name: self.notificationName, object: nil, userInfo: userInfo) 24 | } 25 | 26 | func asObservable() -> Observable { 27 | return self.notificationObservable() 28 | .map{ 29 | guard let parameter = $0.userInfo?[self.identifier] as? ParameterType 30 | else {fatalError("The notification must have the right parameter")} 31 | return parameter 32 | } 33 | } 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Classes/NotificationObservable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationObservable.swift 3 | // Notifications 4 | // 5 | // Created by Leandro Perez on 11/24/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import RxSwift 11 | 12 | public protocol NotificationObservable { 13 | var identifier: String {get} 14 | var notificationName : Notification.Name {get} 15 | func notificationObservable() -> Observable 16 | } 17 | 18 | public extension NotificationObservable { 19 | var notificationName : Notification.Name { 20 | return Notification.Name(self.identifier) 21 | } 22 | 23 | func notificationObservable() -> Observable { 24 | return NotificationCenter.default.rx.notification(self.notificationName) 25 | } 26 | } 27 | 28 | public extension NotificationObservable where Self : RawRepresentable, Self.RawValue == String { 29 | var identifier: String { 30 | return "\(type(of: self))" + self.rawValue 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Tests/GenNotificationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GenNotificationTests.swift 3 | // NotificationsTests 4 | // 5 | // Created by Leandro Perez on 12/26/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import RxSwiftNotifications 11 | import RxSwift 12 | 13 | class GenNotificationTests: XCTestCase { 14 | 15 | func testObservable() { 16 | let disposeBag = DisposeBag() 17 | 18 | var received = "" 19 | 20 | MixedTypesNotifications.stringNotification 21 | .asObservable() 22 | .subscribe(onNext: { (value) in 23 | received = value 24 | }) 25 | .disposed(by: disposeBag) 26 | 27 | MixedTypesNotifications.stringNotification.post(parameter: "something") 28 | 29 | XCTAssertEqual(received, "something") 30 | } 31 | } 32 | 33 | enum MixedTypesNotifications : String, Notifiable { 34 | typealias ParameterType = Int 35 | 36 | case standardIntNotification 37 | 38 | static let stringNotification: GenNotification = GenNotification(id: "stringNotification") 39 | } 40 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Tests/NoParamNotifiableTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NoParamNotifiableTests.swift 3 | // NotificationsTests 4 | // 5 | // Created by Leandro Perez on 12/3/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import RxSwiftNotifications 11 | import RxSwift 12 | 13 | class NoParamNotifiableTests: XCTestCase { 14 | 15 | func testObservable() { 16 | let disposeBag = DisposeBag() 17 | 18 | var notificationsCount = 0 19 | 20 | NoParamsNotifications.somethingDidHappen 21 | .notificationObservable() 22 | .subscribe(onNext: { (notification) in 23 | notificationsCount += 1 24 | }) 25 | .disposed(by: disposeBag) 26 | 27 | NoParamsNotifications.somethingDidHappen.post() 28 | 29 | XCTAssertEqual(notificationsCount, 1) 30 | } 31 | 32 | func testAddListener() { 33 | let disposeBag = DisposeBag() 34 | 35 | var notificationsCount = 0 36 | 37 | NoParamsNotifications.somethingDidHappen 38 | .addListener { 39 | notificationsCount += 1 40 | } 41 | .disposed(by: disposeBag) 42 | 43 | NoParamsNotifications.somethingDidHappen.post() 44 | 45 | XCTAssertEqual(notificationsCount, 1) 46 | } 47 | 48 | 49 | func testAddListenerWithNotification() { 50 | let disposeBag = DisposeBag() 51 | 52 | var receivedNotification : Notification? 53 | NoParamsNotifications.somethingDidHappen 54 | .addListener { (notification) in 55 | receivedNotification = notification 56 | } 57 | .disposed(by: disposeBag) 58 | 59 | NoParamsNotifications.somethingDidHappen.post() 60 | 61 | 62 | XCTAssertNotNil(receivedNotification) 63 | } 64 | 65 | func testAddListenerWithWeakHandler() { 66 | let disposeBag = DisposeBag() 67 | 68 | let counter = Counter() 69 | 70 | NoParamsNotifications.somethingDidHappen 71 | .addListener(weak: counter, handler: Counter.increase) 72 | .disposed(by: disposeBag) 73 | 74 | NoParamsNotifications.somethingDidHappen.post() 75 | 76 | XCTAssertEqual(counter.count, 1) 77 | } 78 | 79 | 80 | 81 | } 82 | 83 | enum NoParamsNotifications : String, NoParamNotifiable { 84 | 85 | case somethingDidHappen 86 | } 87 | 88 | 89 | class Counter { 90 | var count = 0 91 | func increase() { 92 | count += 1 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Tests/NotifiableTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationsTests.swift 3 | // NotificationsTests 4 | // 5 | // Created by Leandro Perez on 11/24/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import RxSwiftNotifications 11 | import RxSwift 12 | 13 | class NotifiableTests: XCTestCase { 14 | 15 | let john = Person(name:"John") 16 | 17 | func testNotificationObservable() { 18 | let disposeBag = DisposeBag() 19 | 20 | var notificationsCount = 0 21 | 22 | PersonNotification.personDied 23 | .notificationObservable() 24 | .subscribe(onNext: { (notification) in 25 | notificationsCount += 1 26 | }) 27 | .disposed(by: disposeBag) 28 | 29 | PersonNotification.personDied.post(parameter: john) 30 | 31 | XCTAssertEqual(notificationsCount, 1) 32 | } 33 | 34 | func testAsObservable() { 35 | let disposeBag = DisposeBag() 36 | 37 | var deadPerson : Person? 38 | 39 | PersonNotification.personDied 40 | .asObservable() 41 | .subscribe(onNext: { (newDead) in 42 | deadPerson = newDead 43 | }).disposed(by: disposeBag) 44 | 45 | PersonNotification.personDied.post(parameter: john) 46 | 47 | XCTAssertEqual(deadPerson, john) 48 | } 49 | 50 | func testAddListener() { 51 | let disposeBag = DisposeBag() 52 | 53 | var deadPerson : Person? 54 | 55 | PersonNotification.personDied 56 | .addListener { deadPerson = $0 } 57 | .disposed(by: disposeBag) 58 | 59 | PersonNotification.personDied.post(parameter: john) 60 | 61 | XCTAssertEqual(deadPerson, john) 62 | } 63 | 64 | func testAddListenerDisposeBag() { 65 | var disposeBag = DisposeBag() 66 | 67 | var deadPerson : Person? 68 | 69 | PersonNotification.personDied 70 | .addListener { deadPerson = $0 } 71 | .disposed(by: disposeBag) 72 | 73 | disposeBag = DisposeBag() 74 | 75 | PersonNotification.personDied.post(parameter: john) 76 | 77 | XCTAssertEqual(deadPerson, nil) 78 | } 79 | 80 | } 81 | 82 | enum PersonNotification : String, Notifiable { 83 | 84 | typealias ParameterType = Person 85 | 86 | case personWasBorn 87 | case personDied 88 | } 89 | 90 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Tests/NotificationsProxyTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationsProxyTests.swift 3 | // NotificationsTests 4 | // 5 | // Created by Leandro Perez on 12/26/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import RxSwiftNotifications 11 | import RxSwift 12 | 13 | class NotificationsProxyTests: XCTestCase { 14 | 15 | var library : Library! 16 | var listener : ListenerForLibrary! 17 | 18 | override func setUp() { 19 | super.setUp() 20 | library = Library() 21 | listener = ListenerForLibrary(subject: library) 22 | } 23 | 24 | func testListenTo() { 25 | BookNotifications.bookWasWritten.post() 26 | 27 | XCTAssertEqual(library.booksCount, 1) 28 | } 29 | 30 | func testListenToWithParameter() { 31 | BookNotifications.bookWasWrittenWithTitle.post(parameter: "Title") 32 | 33 | XCTAssertEqual(library.booksCount, 1) 34 | XCTAssertEqual(library.lastTitle, "Title") 35 | } 36 | 37 | } 38 | 39 | class ListenerForLibrary : NotificationsProxy { 40 | override func listenToNotifications() { 41 | self.listenTo(notification: BookNotifications.bookWasWritten) { (library) in 42 | library.booksCount += 1 43 | } 44 | 45 | self.listenTo(notification: BookNotifications.bookWasWrittenWithTitle) { (library, title) in 46 | library.booksCount += 1 47 | library.lastTitle = title 48 | } 49 | } 50 | } 51 | 52 | class Library { 53 | var booksCount = 0 54 | var lastTitle = "" 55 | } 56 | 57 | enum BookNotifications : String, NoParamNotifiable { 58 | case bookWasWritten 59 | static var bookWasWrittenWithTitle = GenNotification(id: "bookWasWritten") 60 | } 61 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Tests/Town.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Town.swift 3 | // NotificationsTests 4 | // 5 | // Created by Leandro Perez on 11/24/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import RxSwiftNotifications 11 | import RxSwift 12 | 13 | struct Person { 14 | let name : String 15 | } 16 | 17 | extension Person : Equatable {} 18 | func == (lhs: Person, rhs:Person) -> Bool { 19 | return lhs.name == rhs.name 20 | } 21 | 22 | 23 | enum TimeNotification : String, NoParamNotifiable { 24 | case newYear 25 | } 26 | 27 | class Town { 28 | var deadPeople : [Person] = [] 29 | var alivePeople : [Person] = [] 30 | let disposeBag = DisposeBag() 31 | var year = 2000 32 | 33 | init() { 34 | PersonNotification.personDied 35 | .addListener { [unowned self] (person) in 36 | self.personDied(person) 37 | } 38 | .disposed(by: disposeBag) 39 | 40 | PersonNotification.personWasBorn 41 | .addListener { [unowned self] (person) in 42 | self.personWasBorn(person) 43 | } 44 | .disposed(by: disposeBag) 45 | 46 | TimeNotification.newYear 47 | .addListener { [unowned self] (person) in 48 | self.year += 1 49 | } 50 | .disposed(by: disposeBag) 51 | } 52 | 53 | func personDied(_ person: Person) { 54 | alivePeople.removeAll(where: {$0 == person}) 55 | deadPeople += [person] 56 | } 57 | 58 | func personWasBorn(_ person: Person) { 59 | alivePeople += [person] 60 | } 61 | 62 | var report : String { 63 | return "alive: \(self.alivePeople.map{$0.name}), dead: \(self.deadPeople.map{$0.name})" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /RxSwiftNotifications/Tests/UIKitNotifications.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIKitNotifications.swift 3 | // NotificationsTests 4 | // 5 | // Created by Leandro Perez on 12/26/18. 6 | // Copyright © 2018 Leandro perez. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | import RxSwiftNotifications 11 | import RxSwift 12 | import UIKit 13 | 14 | class UIKitNotificationsTests: XCTestCase { 15 | 16 | 17 | func testUIKitNotification() { 18 | let disposeBag = DisposeBag() 19 | 20 | //This is just to show you how to listen to a regular UIKit notification 21 | UIApplication.didBecomeActiveNotification 22 | .notificationObservable() 23 | .subscribe(onNext: { (notification) in 24 | }) 25 | .disposed(by: disposeBag) 26 | 27 | UIApplication.willTerminateNotification 28 | .notificationObservable() 29 | .subscribe(onNext: { _ in 30 | }) 31 | .disposed(by: disposeBag) 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj --------------------------------------------------------------------------------