├── .codecov.yml ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── JSQNotificationObserverKit.podspec ├── JSQNotificationObserverKit.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ └── xcschemes │ ├── JSQNotificationObserverKit-OSX.xcscheme │ ├── JSQNotificationObserverKit-iOS.xcscheme │ ├── JSQNotificationObserverKit-tvOS.xcscheme │ └── JSQNotificationObserverKit-watchOS.xcscheme ├── LICENSE ├── Package.swift ├── README.md ├── Source ├── Info.plist ├── JSQNotificationObserverKit.h └── NotificationObserver.swift └── Tests ├── Info.plist └── NotificationObserverTests.swift /.codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | branch: develop 3 | 4 | coverage: 5 | precision: 2 6 | round: nearest 7 | range: "60...100" 8 | ignore: 9 | - Tests/* 10 | 11 | status: 12 | project: 13 | default: 14 | target: auto 15 | threshold: 2.0 16 | branches: 17 | - master 18 | - develop 19 | patch: 20 | default: 21 | target: auto 22 | branches: 23 | - master 24 | - develop 25 | 26 | comment: 27 | layout: header, diff, changes, sunburst, uncovered 28 | behavior: default 29 | branches: 30 | - master 31 | - develop 32 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How To Contribute 2 | 3 | Please follow these sweet [contribution guidelines](https://github.com/jessesquires/HowToContribute). 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## New issue checklist 2 | 3 | 4 | - [ ] I have read all of the [`README`](https://github.com/jessesquires/JSQNotificationObserverKit/blob/develop/README.md) and [documentation](http://www.jessesquires.com/JSQNotificationObserverKit/). 5 | - [ ] I have reviewed the [contributing guidelines](https://github.com/jessesquires/HowToContribute). 6 | - [ ] I have searched [existing issues](https://github.com/jessesquires/JSQNotificationObserverKit/issues?q=is%3Aissue+sort%3Acreated-desc) and **this is not a duplicate**. 7 | 8 | ## General information 9 | 10 | - Library version(s): 11 | - OS version(s): 12 | - Devices/Simulators affected: 13 | - Reproducible in the demo project (Yes/No): 14 | - Related issues: 15 | 16 | ## Expected behavior 17 | 18 | > ... 19 | 20 | ## Actual behavior 21 | 22 | > ... 23 | 24 | ## Steps to reproduce 25 | 26 | > ... 27 | 28 | ### Crash log? Screenshots? Videos? Sample project? 29 | 30 | > ... 31 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Pull request checklist 2 | 3 | - [ ] All tests pass. Demo project builds and runs. 4 | - [ ] I have resolved any merge conflicts. 5 | - [ ] I have followed the [coding style](https://github.com/jessesquires/HowToContribute#style-guidelines), and reviewed the [contributing guidelines](https://github.com/jessesquires/HowToContribute). 6 | 7 | #### This fixes issue #___. 8 | 9 | ## What's in this pull request? 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Xcode 4 | 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | *.moved-aside 17 | DerivedData 18 | *.hmap 19 | *.ipa 20 | *.xcuserstate 21 | 22 | .build/ 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode7.3 3 | 4 | env: 5 | global: 6 | - LANG=en_US.UTF-8 7 | 8 | - PROJECT="JSQNotificationObserverKit.xcodeproj" 9 | - IOS_SCHEME="JSQNotificationObserverKit-iOS" 10 | - OSX_SCHEME="JSQNotificationObserverKit-OSX" 11 | - TVOS_SCHEME="JSQNotificationObserverKit-tvOS" 12 | - WATCHOS_SCHEME="JSQNotificationObserverKit-watchOS" 13 | 14 | - IOS_SDK=iphonesimulator9.3 15 | - OSX_SDK=macosx10.11 16 | - TVOS_SDK=appletvsimulator9.2 17 | - WATCHOS_SDK=watchsimulator2.2 18 | 19 | matrix: 20 | - DESTINATION="OS=8.1,name=iPhone 4s" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="YES" 21 | - DESTINATION="OS=8.2,name=iPhone 5" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 22 | - DESTINATION="OS=8.3,name=iPhone 5s" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 23 | - DESTINATION="OS=8.4,name=iPhone 6" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 24 | 25 | - DESTINATION="OS=9.0,name=iPhone 5s" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 26 | - DESTINATION="OS=9.1,name=iPhone 6s" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 27 | - DESTINATION="OS=9.2,name=iPhone 6 Plus" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 28 | - DESTINATION="OS=9.3,name=iPhone 6s Plus" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 29 | 30 | - DESTINATION="OS=8.1,name=iPad 2" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 31 | - DESTINATION="OS=8.4,name=iPad 2" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 32 | - DESTINATION="OS=9.0,name=iPad Retina" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 33 | - DESTINATION="OS=9.1,name=iPad Air" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 34 | - DESTINATION="OS=9.2,name=iPad Air 2" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 35 | - DESTINATION="OS=9.3,name=iPad Pro" SDK="$IOS_SDK" SCHEME="$IOS_SCHEME" RUN_TESTS="YES" POD_LINT="NO" 36 | 37 | - DESTINATION="arch=x86_64" SDK="$OSX_SDK" SCHEME="$OSX_FRAMEWORK_SCHEME" RUN_TESTS="NO" POD_LINT="NO" 38 | 39 | - DESTINATION="OS=9.0,name=Apple TV 1080p" SDK="$TVOS_SDK" SCHEME="$TVOS_SCHEME" RUN_TESTS="NO" POD_LINT="NO" 40 | - DESTINATION="OS=9.2,name=Apple TV 1080p" SDK="$TVOS_SDK" SCHEME="$TVOS_SCHEME" RUN_TESTS="NO" POD_LINT="NO" 41 | 42 | - DESTINATION="OS=2.0,name=Apple Watch - 38mm" SDK="$WATCHOS_SDK" SCHEME="$WATCHOS_SCHEME" RUN_TESTS="NO" POD_LINT="NO" 43 | - DESTINATION="OS=2.2,name=Apple Watch - 42mm" SDK="$WATCHOS_SDK" SCHEME="$WATCHOS_SCHEME" RUN_TESTS="NO" POD_LINT="NO" 44 | 45 | script: 46 | 47 | - if [ $POD_LINT == "YES" ]; then 48 | pod spec lint; 49 | pod lib lint; 50 | fi 51 | 52 | - if [ $RUN_TESTS == "YES" ]; then 53 | xcodebuild test -project "$PROJECT" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO | xcpretty -c; 54 | else 55 | xcodebuild clean build -project "$PROJECT" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO | xcpretty -c; 56 | fi 57 | 58 | # Build for reporting test coverage 59 | - if [ $RUN_TESTS == "YES" ]; then 60 | xcodebuild test -project JSQNotificationObserverKit.xcodeproj -scheme JSQNotificationObserverKit-iOS -sdk iphonesimulator; 61 | fi 62 | 63 | after_success: 64 | - bash <(curl -s https://codecov.io/bash) 65 | 66 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | The changelog for `JSQNotificationObserverKit`. Also see the [releases](https://github.com/jessesquires/JSQNotificationObserverKit/releases) on GitHub. 4 | 5 | -------------------------------------- 6 | 7 | 5.0.0 8 | ----- 9 | 10 | This release closes the [5.0.0 milestone](https://github.com/jessesquires/JSQNotificationObserverKit/issues?utf8=✓&q=milestone%3A5.0.0+). 11 | 12 | ### Breaking changes :warning: 13 | 14 | - Updated to Swift 2.2 (#35). **Swift 2.2 and above is now required.** 15 | - The `notification:` parameter name has been removed from `NotificationObserver` initializers to reduce verbosity (#31). Example: 16 | 17 | ````swift 18 | // OLD 19 | let observer = NotificationObserver(notification: note) { (value, sender) in 20 | } 21 | 22 | // NEW 23 | let observer = NotificationObserver(note) { (value, sender) in 24 | } 25 | ```` 26 | 27 | - Renamed `ValueSenderHandler` to `ValueSenderClosure` 28 | - Renamed `NotificationHandler` to `NotificationClosure` 29 | 30 | ### New 31 | 32 | - New convenience typealiases for Cocoa notifications: `CocoaNotification`, `CocoaObserver`, `CocoaClosure` (#28, #33). Thanks @grosch ! See the [docs](http://www.jessesquires.com/JSQNotificationObserverKit/) for details. 33 | 34 | 4.0.0 35 | ----- 36 | 37 | This release closes the [4.0.0 milestone](https://github.com/jessesquires/JSQNotificationObserverKit/issues?q=milestone%3A4.0.0). :tada: 38 | 39 | * The previously added `withSender()` function on `Notification` has changed from `mutating` to non-mutating and now returns a new `Notification` instance. See discussion at #26. See the [docs](http://www.jessesquires.com/JSQNotificationObserverKit/Structs/Notification.html#/s:FV26JSQNotificationObserverKit12Notification10withSenderu0_Rq0_Ss9AnyObject_FGS0_q_q0__FGSqq0__GS0_q_q0__) for details. 40 | 41 | This is a minor, but breaking, change. 42 | 43 | 3.1.0 44 | ----- 45 | 46 | This release closes the [3.1.0 milestone](https://github.com/jessesquires/JSQNotificationObserverKit/issues?q=milestone%3A3.1.0). :tada: 47 | 48 | ### New 49 | 50 | * Support for [Swift package manager](https://github.com/apple/swift-package-manager) :package: 51 | 52 | * `Notification` now has a `withSender()` function to add/remove a sender. (#22, Thanks @grosch! :clap:) 53 | 54 | This is valuable if you want to declare global notifications where the specific sender instance isn't available in the global scope. This function can be chained with `post()`. 55 | 56 | Example usage: 57 | 58 | ```swift 59 | // in a view controller, for example 60 | 61 | notification.withSender(self).post(value) 62 | ``` 63 | 64 | See the [docs](http://www.jessesquires.com/JSQNotificationObserverKit/Structs/Notification.html#/s:FV26JSQNotificationObserverKit12Notification10withSenderu0_Rq0_Ss9AnyObject_FRGS0_q_q0__FGSqq0__GS0_q_q0__) for details. 65 | 66 | 3.0.0 67 | ----- 68 | 69 | This release closes the [3.0.0 milestone](https://github.com/jessesquires/JSQNotificationObserverKit/issues?q=milestone%3A3.0.0). 70 | 71 | ### New 72 | 73 | Official support for OS X, tvOS, watchOS via CocoaPods. :tada: 74 | 75 | ### Changes 76 | 77 | The `postNotification()` global function has moved to be a function on `Notification`. Thanks @grosch! 78 | See the [updated docs](http://www.jessesquires.com/JSQNotificationObserverKit/Structs/Notification.html) for details. 79 | 80 | 2.0.0 81 | ----- 82 | 83 | This release closes the [2.0.0 milestone](https://github.com/jessesquires/JSQNotificationObserverKit/issues?q=milestone%3A2.0.0). 84 | 85 | - Swift 2.0 :tada: 86 | - A few refinements 87 | - More unit tests 88 | - Updated [docs](http://www.jessesquires.com/JSQNotificationObserverKit) 89 | 90 | 1.0.0 91 | ----- 92 | 93 | It's here! :tada: 94 | 95 | Checkout the `README` and documentation. 96 | -------------------------------------------------------------------------------- /JSQNotificationObserverKit.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'JSQNotificationObserverKit' 3 | s.version = '5.0.1' 4 | s.license = 'MIT' 5 | 6 | s.summary = 'Generic notifications and observers for Cocoa and CocoaTouch' 7 | s.homepage = 'https://github.com/jessesquires/JSQNotificationObserverKit' 8 | s.documentation_url = 'http://jessesquires.com/JSQNotificationObserverKit/' 9 | s.social_media_url = 'https://twitter.com/jesse_squires' 10 | s.author = 'Jesse Squires' 11 | 12 | s.source = { :git => 'https://github.com/jessesquires/JSQNotificationObserverKit.git', :tag => s.version } 13 | s.source_files = 'Source/*.swift' 14 | 15 | s.ios.deployment_target = '8.0' 16 | s.osx.deployment_target = '10.10' 17 | s.tvos.deployment_target = '9.0' 18 | s.watchos.deployment_target = '2.0' 19 | 20 | s.requires_arc = true 21 | s.deprecated = true 22 | end 23 | -------------------------------------------------------------------------------- /JSQNotificationObserverKit.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8855BF2A1C3C9F1300D2876E /* JSQNotificationObserverKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 8855BF241C3C9F1300D2876E /* JSQNotificationObserverKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 8855BF2B1C3C9F1300D2876E /* JSQNotificationObserverKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 8855BF241C3C9F1300D2876E /* JSQNotificationObserverKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12 | 8855BF2C1C3C9F1300D2876E /* JSQNotificationObserverKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 8855BF241C3C9F1300D2876E /* JSQNotificationObserverKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | 8855BF2D1C3C9F1300D2876E /* JSQNotificationObserverKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 8855BF241C3C9F1300D2876E /* JSQNotificationObserverKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 14 | 8855BF2E1C3C9F1300D2876E /* NotificationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8855BF251C3C9F1300D2876E /* NotificationObserver.swift */; }; 15 | 8855BF2F1C3C9F1300D2876E /* NotificationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8855BF251C3C9F1300D2876E /* NotificationObserver.swift */; }; 16 | 8855BF301C3C9F1300D2876E /* NotificationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8855BF251C3C9F1300D2876E /* NotificationObserver.swift */; }; 17 | 8855BF311C3C9F1300D2876E /* NotificationObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8855BF251C3C9F1300D2876E /* NotificationObserver.swift */; }; 18 | 8855BF361C3C9F9700D2876E /* NotificationObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8855BF341C3C9F9700D2876E /* NotificationObserverTests.swift */; }; 19 | 886C35241B365733004B64EF /* JSQNotificationObserverKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 887D75E41ABFBD7A00AAE6E7 /* JSQNotificationObserverKit.framework */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 886C35251B365733004B64EF /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 887D75DB1ABFBD7A00AAE6E7 /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 887D75E31ABFBD7A00AAE6E7; 28 | remoteInfo = JSQNotificationObserverKit; 29 | }; 30 | /* End PBXContainerItemProxy section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 8855BF231C3C9F1300D2876E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | 8855BF241C3C9F1300D2876E /* JSQNotificationObserverKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQNotificationObserverKit.h; sourceTree = ""; }; 35 | 8855BF251C3C9F1300D2876E /* NotificationObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationObserver.swift; sourceTree = ""; }; 36 | 8855BF331C3C9F9700D2876E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | 8855BF341C3C9F9700D2876E /* NotificationObserverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationObserverTests.swift; sourceTree = ""; }; 38 | 8862F5711C37ECA200B44CA3 /* JSQNotificationObserverKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JSQNotificationObserverKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 8862F5801C37EDD400B44CA3 /* JSQNotificationObserverKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JSQNotificationObserverKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 8862F58F1C37F06100B44CA3 /* JSQNotificationObserverKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JSQNotificationObserverKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 886C351F1B365733004B64EF /* JSQNotificationObserverKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JSQNotificationObserverKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 887D75E41ABFBD7A00AAE6E7 /* JSQNotificationObserverKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JSQNotificationObserverKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | /* End PBXFileReference section */ 44 | 45 | /* Begin PBXFrameworksBuildPhase section */ 46 | 8862F56D1C37ECA200B44CA3 /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | 8862F57C1C37EDD400B44CA3 /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | 8862F58B1C37F06100B44CA3 /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | 886C351C1B365733004B64EF /* Frameworks */ = { 68 | isa = PBXFrameworksBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | 886C35241B365733004B64EF /* JSQNotificationObserverKit.framework in Frameworks */, 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | 887D75E01ABFBD7A00AAE6E7 /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | ); 80 | runOnlyForDeploymentPostprocessing = 0; 81 | }; 82 | /* End PBXFrameworksBuildPhase section */ 83 | 84 | /* Begin PBXGroup section */ 85 | 8855BF221C3C9F1300D2876E /* Source */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 8855BF251C3C9F1300D2876E /* NotificationObserver.swift */, 89 | 8855BF241C3C9F1300D2876E /* JSQNotificationObserverKit.h */, 90 | 8855BF231C3C9F1300D2876E /* Info.plist */, 91 | ); 92 | path = Source; 93 | sourceTree = ""; 94 | }; 95 | 8855BF321C3C9F9700D2876E /* Tests */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 8855BF331C3C9F9700D2876E /* Info.plist */, 99 | 8855BF341C3C9F9700D2876E /* NotificationObserverTests.swift */, 100 | ); 101 | path = Tests; 102 | sourceTree = ""; 103 | }; 104 | 887D75DA1ABFBD7A00AAE6E7 = { 105 | isa = PBXGroup; 106 | children = ( 107 | 8855BF221C3C9F1300D2876E /* Source */, 108 | 8855BF321C3C9F9700D2876E /* Tests */, 109 | 887D75E51ABFBD7A00AAE6E7 /* Products */, 110 | ); 111 | sourceTree = ""; 112 | }; 113 | 887D75E51ABFBD7A00AAE6E7 /* Products */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 887D75E41ABFBD7A00AAE6E7 /* JSQNotificationObserverKit.framework */, 117 | 886C351F1B365733004B64EF /* JSQNotificationObserverKitTests.xctest */, 118 | 8862F5711C37ECA200B44CA3 /* JSQNotificationObserverKit.framework */, 119 | 8862F5801C37EDD400B44CA3 /* JSQNotificationObserverKit.framework */, 120 | 8862F58F1C37F06100B44CA3 /* JSQNotificationObserverKit.framework */, 121 | ); 122 | name = Products; 123 | sourceTree = ""; 124 | }; 125 | /* End PBXGroup section */ 126 | 127 | /* Begin PBXHeadersBuildPhase section */ 128 | 8862F56E1C37ECA200B44CA3 /* Headers */ = { 129 | isa = PBXHeadersBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | 8855BF2C1C3C9F1300D2876E /* JSQNotificationObserverKit.h in Headers */, 133 | ); 134 | runOnlyForDeploymentPostprocessing = 0; 135 | }; 136 | 8862F57D1C37EDD400B44CA3 /* Headers */ = { 137 | isa = PBXHeadersBuildPhase; 138 | buildActionMask = 2147483647; 139 | files = ( 140 | 8855BF2B1C3C9F1300D2876E /* JSQNotificationObserverKit.h in Headers */, 141 | ); 142 | runOnlyForDeploymentPostprocessing = 0; 143 | }; 144 | 8862F58C1C37F06100B44CA3 /* Headers */ = { 145 | isa = PBXHeadersBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | 8855BF2D1C3C9F1300D2876E /* JSQNotificationObserverKit.h in Headers */, 149 | ); 150 | runOnlyForDeploymentPostprocessing = 0; 151 | }; 152 | 887D75E11ABFBD7A00AAE6E7 /* Headers */ = { 153 | isa = PBXHeadersBuildPhase; 154 | buildActionMask = 2147483647; 155 | files = ( 156 | 8855BF2A1C3C9F1300D2876E /* JSQNotificationObserverKit.h in Headers */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXHeadersBuildPhase section */ 161 | 162 | /* Begin PBXNativeTarget section */ 163 | 8862F5701C37ECA200B44CA3 /* JSQNotificationObserverKit tvOS */ = { 164 | isa = PBXNativeTarget; 165 | buildConfigurationList = 8862F5761C37ECA200B44CA3 /* Build configuration list for PBXNativeTarget "JSQNotificationObserverKit tvOS" */; 166 | buildPhases = ( 167 | 8862F56C1C37ECA200B44CA3 /* Sources */, 168 | 8862F56D1C37ECA200B44CA3 /* Frameworks */, 169 | 8862F56E1C37ECA200B44CA3 /* Headers */, 170 | 8862F56F1C37ECA200B44CA3 /* Resources */, 171 | ); 172 | buildRules = ( 173 | ); 174 | dependencies = ( 175 | ); 176 | name = "JSQNotificationObserverKit tvOS"; 177 | productName = "JSQNotificationObserverKit tvOS"; 178 | productReference = 8862F5711C37ECA200B44CA3 /* JSQNotificationObserverKit.framework */; 179 | productType = "com.apple.product-type.framework"; 180 | }; 181 | 8862F57F1C37EDD400B44CA3 /* JSQNotificationObserverKit OSX */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = 8862F5851C37EDD400B44CA3 /* Build configuration list for PBXNativeTarget "JSQNotificationObserverKit OSX" */; 184 | buildPhases = ( 185 | 8862F57B1C37EDD400B44CA3 /* Sources */, 186 | 8862F57C1C37EDD400B44CA3 /* Frameworks */, 187 | 8862F57D1C37EDD400B44CA3 /* Headers */, 188 | 8862F57E1C37EDD400B44CA3 /* Resources */, 189 | ); 190 | buildRules = ( 191 | ); 192 | dependencies = ( 193 | ); 194 | name = "JSQNotificationObserverKit OSX"; 195 | productName = "JSQNotificationObserverKit OSX"; 196 | productReference = 8862F5801C37EDD400B44CA3 /* JSQNotificationObserverKit.framework */; 197 | productType = "com.apple.product-type.framework"; 198 | }; 199 | 8862F58E1C37F06100B44CA3 /* JSQNotificationObserverKit watchOS */ = { 200 | isa = PBXNativeTarget; 201 | buildConfigurationList = 8862F5941C37F06100B44CA3 /* Build configuration list for PBXNativeTarget "JSQNotificationObserverKit watchOS" */; 202 | buildPhases = ( 203 | 8862F58A1C37F06100B44CA3 /* Sources */, 204 | 8862F58B1C37F06100B44CA3 /* Frameworks */, 205 | 8862F58C1C37F06100B44CA3 /* Headers */, 206 | 8862F58D1C37F06100B44CA3 /* Resources */, 207 | ); 208 | buildRules = ( 209 | ); 210 | dependencies = ( 211 | ); 212 | name = "JSQNotificationObserverKit watchOS"; 213 | productName = "JSQNotificationObserverKit watchOS"; 214 | productReference = 8862F58F1C37F06100B44CA3 /* JSQNotificationObserverKit.framework */; 215 | productType = "com.apple.product-type.framework"; 216 | }; 217 | 886C351E1B365733004B64EF /* JSQNotificationObserverKitTests */ = { 218 | isa = PBXNativeTarget; 219 | buildConfigurationList = 886C35271B365733004B64EF /* Build configuration list for PBXNativeTarget "JSQNotificationObserverKitTests" */; 220 | buildPhases = ( 221 | 886C351B1B365733004B64EF /* Sources */, 222 | 886C351C1B365733004B64EF /* Frameworks */, 223 | 886C351D1B365733004B64EF /* Resources */, 224 | ); 225 | buildRules = ( 226 | ); 227 | dependencies = ( 228 | 886C35261B365733004B64EF /* PBXTargetDependency */, 229 | ); 230 | name = JSQNotificationObserverKitTests; 231 | productName = JSQNotificationObserverKitTests; 232 | productReference = 886C351F1B365733004B64EF /* JSQNotificationObserverKitTests.xctest */; 233 | productType = "com.apple.product-type.bundle.unit-test"; 234 | }; 235 | 887D75E31ABFBD7A00AAE6E7 /* JSQNotificationObserverKit iOS */ = { 236 | isa = PBXNativeTarget; 237 | buildConfigurationList = 887D75FA1ABFBD7A00AAE6E7 /* Build configuration list for PBXNativeTarget "JSQNotificationObserverKit iOS" */; 238 | buildPhases = ( 239 | 887D75DF1ABFBD7A00AAE6E7 /* Sources */, 240 | 887D75E01ABFBD7A00AAE6E7 /* Frameworks */, 241 | 887D75E11ABFBD7A00AAE6E7 /* Headers */, 242 | 887D75E21ABFBD7A00AAE6E7 /* Resources */, 243 | ); 244 | buildRules = ( 245 | ); 246 | dependencies = ( 247 | ); 248 | name = "JSQNotificationObserverKit iOS"; 249 | productName = JSQNotificationObserverKit; 250 | productReference = 887D75E41ABFBD7A00AAE6E7 /* JSQNotificationObserverKit.framework */; 251 | productType = "com.apple.product-type.framework"; 252 | }; 253 | /* End PBXNativeTarget section */ 254 | 255 | /* Begin PBXProject section */ 256 | 887D75DB1ABFBD7A00AAE6E7 /* Project object */ = { 257 | isa = PBXProject; 258 | attributes = { 259 | LastSwiftUpdateCheck = 0700; 260 | LastUpgradeCheck = 0720; 261 | ORGANIZATIONNAME = "Hexed Bits"; 262 | TargetAttributes = { 263 | 8862F5701C37ECA200B44CA3 = { 264 | CreatedOnToolsVersion = 7.2; 265 | }; 266 | 8862F57F1C37EDD400B44CA3 = { 267 | CreatedOnToolsVersion = 7.2; 268 | }; 269 | 8862F58E1C37F06100B44CA3 = { 270 | CreatedOnToolsVersion = 7.2; 271 | }; 272 | 886C351E1B365733004B64EF = { 273 | CreatedOnToolsVersion = 7.0; 274 | }; 275 | 887D75E31ABFBD7A00AAE6E7 = { 276 | CreatedOnToolsVersion = 6.3; 277 | }; 278 | }; 279 | }; 280 | buildConfigurationList = 887D75DE1ABFBD7A00AAE6E7 /* Build configuration list for PBXProject "JSQNotificationObserverKit" */; 281 | compatibilityVersion = "Xcode 3.2"; 282 | developmentRegion = English; 283 | hasScannedForEncodings = 0; 284 | knownRegions = ( 285 | en, 286 | ); 287 | mainGroup = 887D75DA1ABFBD7A00AAE6E7; 288 | productRefGroup = 887D75E51ABFBD7A00AAE6E7 /* Products */; 289 | projectDirPath = ""; 290 | projectRoot = ""; 291 | targets = ( 292 | 887D75E31ABFBD7A00AAE6E7 /* JSQNotificationObserverKit iOS */, 293 | 886C351E1B365733004B64EF /* JSQNotificationObserverKitTests */, 294 | 8862F57F1C37EDD400B44CA3 /* JSQNotificationObserverKit OSX */, 295 | 8862F5701C37ECA200B44CA3 /* JSQNotificationObserverKit tvOS */, 296 | 8862F58E1C37F06100B44CA3 /* JSQNotificationObserverKit watchOS */, 297 | ); 298 | }; 299 | /* End PBXProject section */ 300 | 301 | /* Begin PBXResourcesBuildPhase section */ 302 | 8862F56F1C37ECA200B44CA3 /* Resources */ = { 303 | isa = PBXResourcesBuildPhase; 304 | buildActionMask = 2147483647; 305 | files = ( 306 | ); 307 | runOnlyForDeploymentPostprocessing = 0; 308 | }; 309 | 8862F57E1C37EDD400B44CA3 /* Resources */ = { 310 | isa = PBXResourcesBuildPhase; 311 | buildActionMask = 2147483647; 312 | files = ( 313 | ); 314 | runOnlyForDeploymentPostprocessing = 0; 315 | }; 316 | 8862F58D1C37F06100B44CA3 /* Resources */ = { 317 | isa = PBXResourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | }; 323 | 886C351D1B365733004B64EF /* Resources */ = { 324 | isa = PBXResourcesBuildPhase; 325 | buildActionMask = 2147483647; 326 | files = ( 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | }; 330 | 887D75E21ABFBD7A00AAE6E7 /* Resources */ = { 331 | isa = PBXResourcesBuildPhase; 332 | buildActionMask = 2147483647; 333 | files = ( 334 | ); 335 | runOnlyForDeploymentPostprocessing = 0; 336 | }; 337 | /* End PBXResourcesBuildPhase section */ 338 | 339 | /* Begin PBXSourcesBuildPhase section */ 340 | 8862F56C1C37ECA200B44CA3 /* Sources */ = { 341 | isa = PBXSourcesBuildPhase; 342 | buildActionMask = 2147483647; 343 | files = ( 344 | 8855BF301C3C9F1300D2876E /* NotificationObserver.swift in Sources */, 345 | ); 346 | runOnlyForDeploymentPostprocessing = 0; 347 | }; 348 | 8862F57B1C37EDD400B44CA3 /* Sources */ = { 349 | isa = PBXSourcesBuildPhase; 350 | buildActionMask = 2147483647; 351 | files = ( 352 | 8855BF2F1C3C9F1300D2876E /* NotificationObserver.swift in Sources */, 353 | ); 354 | runOnlyForDeploymentPostprocessing = 0; 355 | }; 356 | 8862F58A1C37F06100B44CA3 /* Sources */ = { 357 | isa = PBXSourcesBuildPhase; 358 | buildActionMask = 2147483647; 359 | files = ( 360 | 8855BF311C3C9F1300D2876E /* NotificationObserver.swift in Sources */, 361 | ); 362 | runOnlyForDeploymentPostprocessing = 0; 363 | }; 364 | 886C351B1B365733004B64EF /* Sources */ = { 365 | isa = PBXSourcesBuildPhase; 366 | buildActionMask = 2147483647; 367 | files = ( 368 | 8855BF361C3C9F9700D2876E /* NotificationObserverTests.swift in Sources */, 369 | ); 370 | runOnlyForDeploymentPostprocessing = 0; 371 | }; 372 | 887D75DF1ABFBD7A00AAE6E7 /* Sources */ = { 373 | isa = PBXSourcesBuildPhase; 374 | buildActionMask = 2147483647; 375 | files = ( 376 | 8855BF2E1C3C9F1300D2876E /* NotificationObserver.swift in Sources */, 377 | ); 378 | runOnlyForDeploymentPostprocessing = 0; 379 | }; 380 | /* End PBXSourcesBuildPhase section */ 381 | 382 | /* Begin PBXTargetDependency section */ 383 | 886C35261B365733004B64EF /* PBXTargetDependency */ = { 384 | isa = PBXTargetDependency; 385 | target = 887D75E31ABFBD7A00AAE6E7 /* JSQNotificationObserverKit iOS */; 386 | targetProxy = 886C35251B365733004B64EF /* PBXContainerItemProxy */; 387 | }; 388 | /* End PBXTargetDependency section */ 389 | 390 | /* Begin XCBuildConfiguration section */ 391 | 8862F5771C37ECA200B44CA3 /* Debug */ = { 392 | isa = XCBuildConfiguration; 393 | buildSettings = { 394 | DEBUG_INFORMATION_FORMAT = dwarf; 395 | DEFINES_MODULE = YES; 396 | DYLIB_COMPATIBILITY_VERSION = 1; 397 | DYLIB_CURRENT_VERSION = 1; 398 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 399 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 400 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 401 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 402 | PRODUCT_BUNDLE_IDENTIFIER = com.hexedbits.JSQNotificationObserverKit; 403 | PRODUCT_NAME = JSQNotificationObserverKit; 404 | SDKROOT = appletvos; 405 | SKIP_INSTALL = YES; 406 | TARGETED_DEVICE_FAMILY = 3; 407 | TVOS_DEPLOYMENT_TARGET = 9.1; 408 | }; 409 | name = Debug; 410 | }; 411 | 8862F5781C37ECA200B44CA3 /* Release */ = { 412 | isa = XCBuildConfiguration; 413 | buildSettings = { 414 | DEFINES_MODULE = YES; 415 | DYLIB_COMPATIBILITY_VERSION = 1; 416 | DYLIB_CURRENT_VERSION = 1; 417 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 418 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 419 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 420 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 421 | PRODUCT_BUNDLE_IDENTIFIER = com.hexedbits.JSQNotificationObserverKit; 422 | PRODUCT_NAME = JSQNotificationObserverKit; 423 | SDKROOT = appletvos; 424 | SKIP_INSTALL = YES; 425 | TARGETED_DEVICE_FAMILY = 3; 426 | TVOS_DEPLOYMENT_TARGET = 9.1; 427 | }; 428 | name = Release; 429 | }; 430 | 8862F5861C37EDD400B44CA3 /* Debug */ = { 431 | isa = XCBuildConfiguration; 432 | buildSettings = { 433 | CODE_SIGN_IDENTITY = "-"; 434 | COMBINE_HIDPI_IMAGES = YES; 435 | DEBUG_INFORMATION_FORMAT = dwarf; 436 | DEFINES_MODULE = YES; 437 | DYLIB_COMPATIBILITY_VERSION = 1; 438 | DYLIB_CURRENT_VERSION = 1; 439 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 440 | FRAMEWORK_VERSION = A; 441 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 442 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 443 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 444 | MACOSX_DEPLOYMENT_TARGET = 10.10; 445 | PRODUCT_BUNDLE_IDENTIFIER = com.hexedbits.JSQNotificationObserverKit; 446 | PRODUCT_NAME = JSQNotificationObserverKit; 447 | SDKROOT = macosx; 448 | SKIP_INSTALL = YES; 449 | }; 450 | name = Debug; 451 | }; 452 | 8862F5871C37EDD400B44CA3 /* Release */ = { 453 | isa = XCBuildConfiguration; 454 | buildSettings = { 455 | CODE_SIGN_IDENTITY = "-"; 456 | COMBINE_HIDPI_IMAGES = YES; 457 | DEFINES_MODULE = YES; 458 | DYLIB_COMPATIBILITY_VERSION = 1; 459 | DYLIB_CURRENT_VERSION = 1; 460 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 461 | FRAMEWORK_VERSION = A; 462 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 463 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 464 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 465 | MACOSX_DEPLOYMENT_TARGET = 10.10; 466 | PRODUCT_BUNDLE_IDENTIFIER = com.hexedbits.JSQNotificationObserverKit; 467 | PRODUCT_NAME = JSQNotificationObserverKit; 468 | SDKROOT = macosx; 469 | SKIP_INSTALL = YES; 470 | }; 471 | name = Release; 472 | }; 473 | 8862F5951C37F06100B44CA3 /* Debug */ = { 474 | isa = XCBuildConfiguration; 475 | buildSettings = { 476 | APPLICATION_EXTENSION_API_ONLY = YES; 477 | DEBUG_INFORMATION_FORMAT = dwarf; 478 | DEFINES_MODULE = YES; 479 | DYLIB_COMPATIBILITY_VERSION = 1; 480 | DYLIB_CURRENT_VERSION = 1; 481 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 482 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 483 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 484 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 485 | PRODUCT_BUNDLE_IDENTIFIER = com.hexedbits.JSQNotificationObserverKit; 486 | PRODUCT_NAME = JSQNotificationObserverKit; 487 | SDKROOT = watchos; 488 | SKIP_INSTALL = YES; 489 | TARGETED_DEVICE_FAMILY = 4; 490 | WATCHOS_DEPLOYMENT_TARGET = 2.1; 491 | }; 492 | name = Debug; 493 | }; 494 | 8862F5961C37F06100B44CA3 /* Release */ = { 495 | isa = XCBuildConfiguration; 496 | buildSettings = { 497 | APPLICATION_EXTENSION_API_ONLY = YES; 498 | DEFINES_MODULE = YES; 499 | DYLIB_COMPATIBILITY_VERSION = 1; 500 | DYLIB_CURRENT_VERSION = 1; 501 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 502 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 503 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 504 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 505 | PRODUCT_BUNDLE_IDENTIFIER = com.hexedbits.JSQNotificationObserverKit; 506 | PRODUCT_NAME = JSQNotificationObserverKit; 507 | SDKROOT = watchos; 508 | SKIP_INSTALL = YES; 509 | TARGETED_DEVICE_FAMILY = 4; 510 | WATCHOS_DEPLOYMENT_TARGET = 2.1; 511 | }; 512 | name = Release; 513 | }; 514 | 886C35281B365733004B64EF /* Debug */ = { 515 | isa = XCBuildConfiguration; 516 | buildSettings = { 517 | DEBUG_INFORMATION_FORMAT = dwarf; 518 | INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; 519 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 520 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 521 | PRODUCT_BUNDLE_IDENTIFIER = com.hexedbits.JSQNotificationObserverKitTests; 522 | PRODUCT_NAME = "$(TARGET_NAME)"; 523 | }; 524 | name = Debug; 525 | }; 526 | 886C35291B365733004B64EF /* Release */ = { 527 | isa = XCBuildConfiguration; 528 | buildSettings = { 529 | INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; 530 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 531 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 532 | PRODUCT_BUNDLE_IDENTIFIER = com.hexedbits.JSQNotificationObserverKitTests; 533 | PRODUCT_NAME = "$(TARGET_NAME)"; 534 | }; 535 | name = Release; 536 | }; 537 | 887D75F81ABFBD7A00AAE6E7 /* Debug */ = { 538 | isa = XCBuildConfiguration; 539 | buildSettings = { 540 | ALWAYS_SEARCH_USER_PATHS = NO; 541 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 542 | CLANG_CXX_LIBRARY = "libc++"; 543 | CLANG_ENABLE_MODULES = YES; 544 | CLANG_ENABLE_OBJC_ARC = YES; 545 | CLANG_WARN_BOOL_CONVERSION = YES; 546 | CLANG_WARN_CONSTANT_CONVERSION = YES; 547 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 548 | CLANG_WARN_EMPTY_BODY = YES; 549 | CLANG_WARN_ENUM_CONVERSION = YES; 550 | CLANG_WARN_INT_CONVERSION = YES; 551 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 552 | CLANG_WARN_UNREACHABLE_CODE = YES; 553 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 554 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 555 | COPY_PHASE_STRIP = NO; 556 | CURRENT_PROJECT_VERSION = 1; 557 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 558 | ENABLE_STRICT_OBJC_MSGSEND = YES; 559 | ENABLE_TESTABILITY = YES; 560 | GCC_C_LANGUAGE_STANDARD = gnu99; 561 | GCC_DYNAMIC_NO_PIC = NO; 562 | GCC_NO_COMMON_BLOCKS = YES; 563 | GCC_OPTIMIZATION_LEVEL = 0; 564 | GCC_PREPROCESSOR_DEFINITIONS = ( 565 | "DEBUG=1", 566 | "$(inherited)", 567 | ); 568 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 569 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 570 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 571 | GCC_WARN_UNDECLARED_SELECTOR = YES; 572 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 573 | GCC_WARN_UNUSED_FUNCTION = YES; 574 | GCC_WARN_UNUSED_VARIABLE = YES; 575 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 576 | MACOSX_DEPLOYMENT_TARGET = 10.10; 577 | MTL_ENABLE_DEBUG_INFO = YES; 578 | ONLY_ACTIVE_ARCH = YES; 579 | SDKROOT = iphoneos; 580 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 581 | TARGETED_DEVICE_FAMILY = "1,2"; 582 | VERSIONING_SYSTEM = "apple-generic"; 583 | VERSION_INFO_PREFIX = ""; 584 | }; 585 | name = Debug; 586 | }; 587 | 887D75F91ABFBD7A00AAE6E7 /* Release */ = { 588 | isa = XCBuildConfiguration; 589 | buildSettings = { 590 | ALWAYS_SEARCH_USER_PATHS = NO; 591 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 592 | CLANG_CXX_LIBRARY = "libc++"; 593 | CLANG_ENABLE_MODULES = YES; 594 | CLANG_ENABLE_OBJC_ARC = YES; 595 | CLANG_WARN_BOOL_CONVERSION = YES; 596 | CLANG_WARN_CONSTANT_CONVERSION = YES; 597 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 598 | CLANG_WARN_EMPTY_BODY = YES; 599 | CLANG_WARN_ENUM_CONVERSION = YES; 600 | CLANG_WARN_INT_CONVERSION = YES; 601 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 602 | CLANG_WARN_UNREACHABLE_CODE = YES; 603 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 604 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 605 | COPY_PHASE_STRIP = NO; 606 | CURRENT_PROJECT_VERSION = 1; 607 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 608 | ENABLE_NS_ASSERTIONS = NO; 609 | ENABLE_STRICT_OBJC_MSGSEND = YES; 610 | GCC_C_LANGUAGE_STANDARD = gnu99; 611 | GCC_NO_COMMON_BLOCKS = YES; 612 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 613 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 614 | GCC_WARN_UNDECLARED_SELECTOR = YES; 615 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 616 | GCC_WARN_UNUSED_FUNCTION = YES; 617 | GCC_WARN_UNUSED_VARIABLE = YES; 618 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 619 | MACOSX_DEPLOYMENT_TARGET = 10.10; 620 | MTL_ENABLE_DEBUG_INFO = NO; 621 | SDKROOT = iphoneos; 622 | TARGETED_DEVICE_FAMILY = "1,2"; 623 | VALIDATE_PRODUCT = YES; 624 | VERSIONING_SYSTEM = "apple-generic"; 625 | VERSION_INFO_PREFIX = ""; 626 | }; 627 | name = Release; 628 | }; 629 | 887D75FB1ABFBD7A00AAE6E7 /* Debug */ = { 630 | isa = XCBuildConfiguration; 631 | buildSettings = { 632 | CLANG_ENABLE_MODULES = YES; 633 | DEFINES_MODULE = YES; 634 | DYLIB_COMPATIBILITY_VERSION = 1; 635 | DYLIB_CURRENT_VERSION = 1; 636 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 637 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 638 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 639 | LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; 640 | PRODUCT_BUNDLE_IDENTIFIER = "com.hexedbits.$(PRODUCT_NAME:rfc1034identifier)"; 641 | PRODUCT_NAME = JSQNotificationObserverKit; 642 | SKIP_INSTALL = YES; 643 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 644 | }; 645 | name = Debug; 646 | }; 647 | 887D75FC1ABFBD7A00AAE6E7 /* Release */ = { 648 | isa = XCBuildConfiguration; 649 | buildSettings = { 650 | CLANG_ENABLE_MODULES = YES; 651 | DEFINES_MODULE = YES; 652 | DYLIB_COMPATIBILITY_VERSION = 1; 653 | DYLIB_CURRENT_VERSION = 1; 654 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 655 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 656 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 657 | LD_RUNPATH_SEARCH_PATHS = "$(inherited)"; 658 | PRODUCT_BUNDLE_IDENTIFIER = "com.hexedbits.$(PRODUCT_NAME:rfc1034identifier)"; 659 | PRODUCT_NAME = JSQNotificationObserverKit; 660 | SKIP_INSTALL = YES; 661 | }; 662 | name = Release; 663 | }; 664 | /* End XCBuildConfiguration section */ 665 | 666 | /* Begin XCConfigurationList section */ 667 | 8862F5761C37ECA200B44CA3 /* Build configuration list for PBXNativeTarget "JSQNotificationObserverKit tvOS" */ = { 668 | isa = XCConfigurationList; 669 | buildConfigurations = ( 670 | 8862F5771C37ECA200B44CA3 /* Debug */, 671 | 8862F5781C37ECA200B44CA3 /* Release */, 672 | ); 673 | defaultConfigurationIsVisible = 0; 674 | defaultConfigurationName = Release; 675 | }; 676 | 8862F5851C37EDD400B44CA3 /* Build configuration list for PBXNativeTarget "JSQNotificationObserverKit OSX" */ = { 677 | isa = XCConfigurationList; 678 | buildConfigurations = ( 679 | 8862F5861C37EDD400B44CA3 /* Debug */, 680 | 8862F5871C37EDD400B44CA3 /* Release */, 681 | ); 682 | defaultConfigurationIsVisible = 0; 683 | defaultConfigurationName = Release; 684 | }; 685 | 8862F5941C37F06100B44CA3 /* Build configuration list for PBXNativeTarget "JSQNotificationObserverKit watchOS" */ = { 686 | isa = XCConfigurationList; 687 | buildConfigurations = ( 688 | 8862F5951C37F06100B44CA3 /* Debug */, 689 | 8862F5961C37F06100B44CA3 /* Release */, 690 | ); 691 | defaultConfigurationIsVisible = 0; 692 | defaultConfigurationName = Release; 693 | }; 694 | 886C35271B365733004B64EF /* Build configuration list for PBXNativeTarget "JSQNotificationObserverKitTests" */ = { 695 | isa = XCConfigurationList; 696 | buildConfigurations = ( 697 | 886C35281B365733004B64EF /* Debug */, 698 | 886C35291B365733004B64EF /* Release */, 699 | ); 700 | defaultConfigurationIsVisible = 0; 701 | defaultConfigurationName = Release; 702 | }; 703 | 887D75DE1ABFBD7A00AAE6E7 /* Build configuration list for PBXProject "JSQNotificationObserverKit" */ = { 704 | isa = XCConfigurationList; 705 | buildConfigurations = ( 706 | 887D75F81ABFBD7A00AAE6E7 /* Debug */, 707 | 887D75F91ABFBD7A00AAE6E7 /* Release */, 708 | ); 709 | defaultConfigurationIsVisible = 0; 710 | defaultConfigurationName = Release; 711 | }; 712 | 887D75FA1ABFBD7A00AAE6E7 /* Build configuration list for PBXNativeTarget "JSQNotificationObserverKit iOS" */ = { 713 | isa = XCConfigurationList; 714 | buildConfigurations = ( 715 | 887D75FB1ABFBD7A00AAE6E7 /* Debug */, 716 | 887D75FC1ABFBD7A00AAE6E7 /* Release */, 717 | ); 718 | defaultConfigurationIsVisible = 0; 719 | defaultConfigurationName = Release; 720 | }; 721 | /* End XCConfigurationList section */ 722 | }; 723 | rootObject = 887D75DB1ABFBD7A00AAE6E7 /* Project object */; 724 | } 725 | -------------------------------------------------------------------------------- /JSQNotificationObserverKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JSQNotificationObserverKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /JSQNotificationObserverKit.xcodeproj/xcshareddata/xcschemes/JSQNotificationObserverKit-OSX.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /JSQNotificationObserverKit.xcodeproj/xcshareddata/xcschemes/JSQNotificationObserverKit-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 65 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 84 | 90 | 91 | 92 | 93 | 95 | 96 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /JSQNotificationObserverKit.xcodeproj/xcshareddata/xcschemes/JSQNotificationObserverKit-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /JSQNotificationObserverKit.xcodeproj/xcshareddata/xcschemes/JSQNotificationObserverKit-watchOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-present Jesse Squires 4 | 5 | http://jessesquires.com 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 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jesse Squires 3 | // http://www.jessesquires.com 4 | // 5 | // 6 | // Documentation 7 | // http://www.jessesquires.com/JSQNotificationObserverKit 8 | // 9 | // 10 | // GitHub 11 | // https://github.com/jessesquires/JSQNotificationObserverKit 12 | // 13 | // 14 | // License 15 | // Copyright © 2015-present Jesse Squires 16 | // Released under an MIT license: http://opensource.org/licenses/MIT 17 | // 18 | 19 | import PackageDescription 20 | 21 | let package = Package( 22 | name: "JSQNotificationObserverKit" 23 | ) 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) 2 | 3 | # :warning: Deprecated :warning: 4 | 5 | As Swift 3.0 and proposal [SE-0069](https://github.com/apple/swift-evolution/blob/master/proposals/0069-swift-mutability-for-foundation.md), this library is no longer necessary. 6 | 7 | Foundation now provides a `Notification` struct. Unfortunately, it is not generic like the value type provided by this library, `Notification`, but dealing with the trouble/confusion between the namespaces (`Foundation.Notification` vs. `JSQNotificationObserverKit.Notification`) makes this library not worth it. 8 | 9 | ## JSQNotificationObserverKit 10 | 11 | [![Build Status](https://secure.travis-ci.org/jessesquires/JSQNotificationObserverKit.svg)](http://travis-ci.org/jessesquires/JSQNotificationObserverKit) [![Version Status](https://img.shields.io/cocoapods/v/JSQNotificationObserverKit.svg)][podLink] [![license MIT](https://img.shields.io/cocoapods/l/JSQNotificationObserverKit.svg)][mitLink] [![codecov](https://codecov.io/gh/jessesquires/JSQNotificationObserverKit/branch/develop/graph/badge.svg)](https://codecov.io/gh/jessesquires/JSQNotificationObserverKit) [![Platform](https://img.shields.io/cocoapods/p/JSQNotificationObserverKit.svg)][docsLink] [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 12 | 13 | *Generic notifications and observers for Cocoa and CocoaTouch, inspired by [objc.io](http://www.objc.io/snippets/16.html)* 14 | 15 | ## About 16 | 17 | This library aims to provide better semantics regarding notifications and moves the responsibilty of observing and handling notifications to a lightweight, single-purpose object. It also brings type-safety and a cleaner interface to `NSNotificationCenter`. See objc.io's [snippet #16](http://www.objc.io/snippets/16.html) on *Typed Notification Observers* for more information. 18 | 19 | ## Requirements 20 | 21 | * Xcode 7.3+ 22 | * iOS 8.0+ 23 | * OSX 10.10+ 24 | * tvOS 9.1+ 25 | * watchOS 2.0+ 26 | * **Swift 2.2** 27 | 28 | ## Installation 29 | 30 | #### [CocoaPods](http://cocoapods.org) (recommended) 31 | 32 | ````ruby 33 | use_frameworks! 34 | 35 | # For latest release in cocoapods 36 | pod 'JSQNotificationObserverKit' 37 | 38 | # Feeling adventurous? Get the latest on develop 39 | pod 'JSQNotificationObserverKit', :git => 'https://github.com/jessesquires/JSQNotificationObserverKit.git', :branch => 'develop' 40 | ```` 41 | 42 | #### [Carthage](https://github.com/Carthage/Carthage) 43 | 44 | ````bash 45 | github "jessesquires/JSQNotificationObserverKit" 46 | ```` 47 | 48 | ## Documentation 49 | 50 | Read the [docs][docsLink]. Generated with [jazzy](https://github.com/realm/jazzy). Hosted by [GitHub Pages](https://pages.github.com). More information on the [`gh-pages`](https://github.com/jessesquires/JSQNotificationObserverKit/tree/gh-pages) branch. 51 | 52 | ## Getting Started 53 | 54 | ````swift 55 | import JSQNotificationObserverKit 56 | ```` 57 | 58 | >See the included unit tests for more examples and usage. 59 | 60 | #### Example 61 | 62 | ````swift 63 | // Suppose we have a UIView that posts a notification when its size changes 64 | let myView = UIView() 65 | 66 | // This notification posts a CGSize value from a UIView sender 67 | let notification = Notification(name: "NewViewSizeNotif", sender: myView) 68 | 69 | // This observer listens for the notification described above 70 | var observer: NotificationObserver? 71 | 72 | // Register observer, start listening for the notification 73 | observer = NotificationObserver(notification) { (value, sender) in 74 | // handle notification 75 | // the value and sender are both passed here 76 | } 77 | 78 | // Post the notification with the updated CGSize value 79 | notification.post(CGSizeMake(200, 200)) 80 | 81 | // Unregister observer, stop listening for notifications 82 | observer = nil 83 | ```` 84 | 85 | #### Notifications without a sender 86 | 87 | Not all notifications are associated with a specific sender object. Here's how to handle `nil` sender in `JSQNotificationObserverKit`. This observer will respond to notifications *regardless* of the instances sending them. 88 | 89 | ````swift 90 | // This notification posts a string value, the sender is nil 91 | let notification = Notification(name: "StringNotif") 92 | 93 | // Post the notification 94 | notification.post("new string") 95 | 96 | // Register observer, this handles notifications from *any* sender 97 | var observer: NotificationObserver? 98 | observer = NotificationObserver(notification) { (value, sender) in 99 | // handle notification 100 | // the value is passed here, sender is nil 101 | } 102 | 103 | // unregister observer, stop listening for notifications 104 | observer = nil 105 | ```` 106 | 107 | #### Using a custom queue and notification center 108 | 109 | You can optionally pass an `NSOperationQueue` and `NSNotificationCenter`. The default values are `nil` and `NSNotificationCenter.defaultCenter()`, respectively. 110 | 111 | ````swift 112 | // Initialize an observer and post a notification 113 | // with a custom notification center and operation queue 114 | let c = NSNotificationCenter.defaultCenter() 115 | 116 | let q = NSOperationQueue.mainQueue() 117 | 118 | let observer = NotificationObserver(n, queue: q, center: c) { (value, sender) in 119 | // handle notification 120 | } 121 | 122 | notification.post(v, center: c) 123 | ```` 124 | 125 | #### Notifications without a value 126 | 127 | Not all notifications are associated with a specific value. Sometimes notifications are used to simply broadcast an event, for example `UIApplicationDidReceiveMemoryWarningNotification`. 128 | 129 | ````swift 130 | let notification = Notification(name: "MyEventNotification") 131 | 132 | let observer = NotificationObserver(notification) { (value, sender) in 133 | // handle notification 134 | // value is nil, sender is nil 135 | } 136 | 137 | // notification value is `Any?`, so pass nil 138 | notification.post(nil) 139 | ```` 140 | 141 | #### Working with "traditional" Cocoa notifications 142 | 143 | The library can also handle "traditional" notifications that are posted by the OS. Instead of using the `(value, sender)` handler, use the `(notification)` handler which passes the full `NSNotification` object. 144 | 145 | ````swift 146 | let notification = CocoaNotification(name: UIApplicationDidReceiveMemoryWarningNotification) 147 | 148 | let observer = CocoaObserver(notification, handler: { (notification: NSNotification) in 149 | // handle the notification 150 | }) 151 | 152 | // the notification will be posted by iOS 153 | ```` 154 | 155 | ## Unit tests 156 | 157 | There's a suite of unit tests for the `JSQNotificationObserverKit.framework`. To run them, open `JSQNotificationObserverKit.xcodeproj`, select the `JSQNotificationObserverKit` scheme, then ⌘-u. 158 | 159 | These tests are well commented and serve as further documentation for how to use this library. 160 | 161 | ## Contribute 162 | 163 | Please follow these sweet [contribution guidelines](https://github.com/jessesquires/HowToContribute). 164 | 165 | ## Credits 166 | 167 | Created and maintained by [**@jesse_squires**](https://twitter.com/jesse_squires). 168 | 169 | ## License 170 | 171 | `JSQNotificationObserverKit` is released under an [MIT License][mitLink]. See `LICENSE` for details. 172 | 173 | >**Copyright © 2014-present Jesse Squires.** 174 | 175 | *Please provide attribution, it is greatly appreciated.* 176 | 177 | [mitLink]:http://opensource.org/licenses/MIT 178 | [docsLink]:http://www.jessesquires.com/JSQNotificationObserverKit 179 | [podLink]:https://cocoapods.org/pods/JSQNotificationObserverKit 180 | -------------------------------------------------------------------------------- /Source/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 | FMWK 17 | CFBundleShortVersionString 18 | 5.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Source/JSQNotificationObserverKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jesse Squires 3 | // http://www.jessesquires.com 4 | // 5 | // 6 | // Documentation 7 | // http://www.jessesquires.com/JSQNotificationObserverKit 8 | // 9 | // 10 | // GitHub 11 | // https://github.com/jessesquires/JSQNotificationObserverKit 12 | // 13 | // 14 | // License 15 | // Copyright © 2015-present Jesse Squires 16 | // Released under an MIT license: http://opensource.org/licenses/MIT 17 | // 18 | 19 | #import 20 | 21 | FOUNDATION_EXPORT double JSQNotificationObserverKitVersionNumber; 22 | 23 | FOUNDATION_EXPORT const unsigned char JSQNotificationObserverKitVersionString[]; 24 | -------------------------------------------------------------------------------- /Source/NotificationObserver.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jesse Squires 3 | // http://www.jessesquires.com 4 | // 5 | // 6 | // Documentation 7 | // http://www.jessesquires.com/JSQNotificationObserverKit 8 | // 9 | // 10 | // GitHub 11 | // https://github.com/jessesquires/JSQNotificationObserverKit 12 | // 13 | // 14 | // License 15 | // Copyright © 2015-present Jesse Squires 16 | // Released under an MIT license: http://opensource.org/licenses/MIT 17 | // 18 | 19 | import Foundation 20 | 21 | 22 | /// Describes a notification's userInfo dictionary. 23 | public typealias UserInfo = [NSObject : AnyObject] 24 | 25 | /// Describes a Cocoa notification. 26 | public typealias CocoaNotification = Notification 27 | 28 | /// Describes a Cocoa observer. 29 | public typealias CocoaObserver = NotificationObserver 30 | 31 | /// Describes a closure for Cocoa notifications. 32 | public typealias CocoaClosure = CocoaObserver.NotificationClosure 33 | 34 | 35 | /** 36 | - parameter lhs: A UserInfo instance. 37 | - parameter rhs: A UserInfo instance. 38 | 39 | - returns: True if `lhs` is equal to `rhs`, false otherwise. 40 | */ 41 | public func ==(lhs: UserInfo, rhs: UserInfo) -> Bool { 42 | guard lhs.count == rhs.count else { 43 | return false 44 | } 45 | 46 | for (key, value) in lhs { 47 | guard let rhsValue = rhs[key] else { 48 | return false 49 | } 50 | 51 | if !rhsValue.isEqual(value) { 52 | return false 53 | } 54 | } 55 | return true 56 | } 57 | 58 | 59 | /** 60 | A typed notification that contains a name and optional sender. 61 | 62 | - note: The `Value` type parameter acts as a phantom type, restricting the notification to posting only values of this type. 63 | */ 64 | public struct Notification { 65 | 66 | // MARK: Properties 67 | 68 | /// The name of the notification. 69 | public let name: String 70 | 71 | /// The object that posted the notification. 72 | public let sender: Sender? 73 | 74 | // MARK: Initialization 75 | 76 | /** 77 | Constructs a new notification instance having the specified name and sender. 78 | 79 | - parameter name: The name of the notification. 80 | - parameter sender: The object sending the notification. The default is `nil`. 81 | 82 | - returns: A new `Notification` instance. 83 | */ 84 | public init(name: String, sender: Sender? = nil) { 85 | self.name = name 86 | self.sender = sender 87 | } 88 | 89 | /** 90 | Posts the notification with the given value to the specified center. 91 | 92 | - parameter value: The data to be sent with the notification. 93 | - parameter center: The notification center from which the notification should be dispatched. 94 | The default is `NSNotificationCenter.defaultCenter()`. 95 | */ 96 | public func post(value: Value, center: NSNotificationCenter = .defaultCenter()) { 97 | center.postNotificationName(name, object: sender, userInfo: userInfo(value)) 98 | } 99 | 100 | /** 101 | Returns a new notification with the receiver's name and the specified sender. 102 | 103 | - warning: Note that this function returns a new `Notification` instance. 104 | 105 | - parameter sender: The instance posting this notification. 106 | 107 | - returns: A new `Notification` instance. 108 | */ 109 | public func withSender(sender: Sender?) -> Notification { 110 | return Notification(name: name, sender: sender) 111 | } 112 | } 113 | 114 | 115 | /** 116 | An instance of `NotificationObserver` is responsible for observing notifications. 117 | 118 | - warning: When an observer is initialized, it will immediately begin listening for its specified notification 119 | by registering with the specified notification center. To stop listening, dealloc the observer by setting it to `nil`. 120 | */ 121 | public final class NotificationObserver { 122 | 123 | // MARK: Typealiases 124 | 125 | /** 126 | The closure to be called when a `Notification` is received. 127 | 128 | - parameter value: The data sent with the notification. 129 | - parameter sender: The object that sent the notification, or `nil` if the notification is not associated with a specific sender. 130 | */ 131 | public typealias ValueSenderClosure = (value: V, sender: S?) -> Void 132 | 133 | /** 134 | The closure to be called when an `NSNotification` is received. 135 | 136 | - parameter notification: The notification received. 137 | */ 138 | public typealias NotificationClosure = (notification: NSNotification) -> Void 139 | 140 | 141 | // MARK: Properties 142 | 143 | private let observerProxy: NSObjectProtocol 144 | private let center: NSNotificationCenter 145 | 146 | 147 | // MARK: Initialization 148 | 149 | /** 150 | Constructs a new `NotificationObserver` instance and immediately registers to begin observing the specified `notification`. 151 | 152 | - warning: To unregister this observer and end listening for notifications, dealloc the object by setting it to `nil`. 153 | 154 | - parameter notification: The notification for which to register the observer. 155 | - parameter queue: The operation queue to which `handler` should be added. If `nil` (the default), the block is run synchronously on the posting thread. 156 | - parameter center: The notification center from which the notification should be dispatched. The default is `NSNotificationCenter.defaultCenter()`. 157 | - parameter handler: The closure to execute when the notification is received. 158 | 159 | - returns: A new `NotificationObserver` instance. 160 | */ 161 | public convenience init(_ notification: Notification, 162 | queue: NSOperationQueue? = nil, 163 | center: NSNotificationCenter = .defaultCenter(), 164 | handler: ValueSenderClosure) { 165 | self.init(notification, queue: queue, center: center, handler: { (notification: NSNotification) in 166 | if let value: V = unboxUserInfo(notification.userInfo) { 167 | handler(value: value, sender: notification.object as? S) 168 | } 169 | }) 170 | } 171 | 172 | /** 173 | Constructs a new `NotificationObserver` instance and immediately registers to begin observing the specified `notification`. 174 | 175 | - warning: To unregister this observer and end listening for notifications, dealloc the object by setting it to `nil`. 176 | 177 | - parameter notification: The notification for which to register the observer. 178 | - parameter queue: The operation queue to which `handler` should be added. If `nil` (the default), the block is run synchronously on the posting thread. 179 | - parameter center: The notification center from which the notification should be dispatched. The default is `NSNotificationCenter.defaultCenter()`. 180 | - parameter handler: The closure to execute when the notification is received. 181 | 182 | - returns: A new `NotificationObserver` instance. 183 | */ 184 | public init(_ notification: Notification, 185 | queue: NSOperationQueue? = nil, 186 | center: NSNotificationCenter = .defaultCenter(), 187 | handler: NotificationClosure) { 188 | self.center = center 189 | observerProxy = center.addObserverForName(notification.name, object: notification.sender, queue: queue, usingBlock: handler) 190 | } 191 | 192 | /// :nodoc: 193 | deinit { 194 | center.removeObserver(observerProxy) 195 | } 196 | } 197 | 198 | 199 | // MARK: Private 200 | 201 | 202 | // Key for user info dictionary 203 | private let UserInfoValueKey = "UserInfoValueKey" 204 | 205 | 206 | // This class allows the "boxing up" instances that are not reference types 207 | private final class Box { 208 | let value: T 209 | 210 | init(_ value: T) { 211 | self.value = value 212 | } 213 | } 214 | 215 | 216 | // Create user info dictionary 217 | private func userInfo(value: T) -> [String : Box] { 218 | return [UserInfoValueKey : Box(value)] 219 | } 220 | 221 | 222 | // Unbox user info dictionary 223 | private func unboxUserInfo(userInfo: UserInfo?) -> T? { 224 | if let box = userInfo?[UserInfoValueKey] as? Box { 225 | return box.value 226 | } 227 | return nil 228 | } 229 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Tests/NotificationObserverTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Jesse Squires 3 | // http://www.jessesquires.com 4 | // 5 | // 6 | // Documentation 7 | // http://www.jessesquires.com/JSQNotificationObserverKit 8 | // 9 | // 10 | // GitHub 11 | // https://github.com/jessesquires/JSQNotificationObserverKit 12 | // 13 | // 14 | // License 15 | // Copyright © 2015-present Jesse Squires 16 | // Released under an MIT license: http://opensource.org/licenses/MIT 17 | // 18 | 19 | import XCTest 20 | import Foundation 21 | import UIKit 22 | 23 | import JSQNotificationObserverKit 24 | 25 | 26 | 27 | // MARK: Fakes 28 | 29 | class TestSender: Equatable { 30 | let sender = NSUUID().UUIDString 31 | } 32 | 33 | struct TestValue: Equatable { 34 | let value = NSUUID().UUIDString 35 | } 36 | 37 | func ==(lhs: TestSender, rhs: TestSender) -> Bool { 38 | return lhs.sender == rhs.sender 39 | } 40 | 41 | func ==(lhs: TestValue, rhs: TestValue) -> Bool { 42 | return lhs.value == rhs.value 43 | } 44 | 45 | 46 | 47 | // MARK: Test cases 48 | 49 | let timeout = NSTimeInterval(5) 50 | 51 | 52 | final class NotificationObserverTests: XCTestCase { 53 | 54 | func test_ThatWithSender_ReturnsNewNotification() { 55 | // GIVEN: a notification and sender 56 | let sender = TestSender() 57 | let notif = Notification(name: "Notif", sender: sender) 58 | XCTAssertEqual(notif.sender, sender) 59 | 60 | let newNotif = notif.withSender(nil) 61 | XCTAssertEqual(newNotif.name, notif.name, "Notification names should be equal") 62 | XCTAssertNil(newNotif.sender, "New notification sender should be updated") 63 | 64 | XCTAssertNotNil(notif.sender, "Original notification sender should remain unchanged") 65 | 66 | let anotherSender = TestSender() 67 | let anotherNotif = notif.withSender(anotherSender) 68 | XCTAssertEqual(anotherNotif.name, notif.name, "Notification names should be equal") 69 | XCTAssertEqual(anotherNotif.sender, anotherSender, "New notification sender should be updated") 70 | 71 | XCTAssertEqual(notif.sender, sender, "Original notification sender should remain unchanged") 72 | } 73 | 74 | func test_ThatWithSender_PostsCorrectNotification() { 75 | // GIVEN: a notification 76 | let notif = Notification(name: "Notif") 77 | XCTAssertNil(notif.sender) 78 | 79 | let sender = TestSender() 80 | let value = 666 81 | let expect = self.expectationWithDescription("\(#function)") 82 | 83 | // GIVEN: an observer 84 | let observer = NotificationObserver(notif, handler: { (v, s) in 85 | XCTAssertEqual(s, sender) 86 | XCTAssertEqual(v, value) 87 | expect.fulfill() 88 | }) 89 | 90 | XCTAssertNotNil(observer) 91 | 92 | // WHEN: the notification is posted using a new sender 93 | let newNotif = notif.withSender(sender) 94 | newNotif.post(value) 95 | 96 | XCTAssertEqual(newNotif.sender, sender, "New notification sender should be updated") 97 | XCTAssertNil(notif.sender, "Original notification sender should remain unchanged") 98 | 99 | // THEN: the observer receives the correct notification and executes its handler 100 | self.waitForExpectationsWithTimeout(timeout, handler: { (error) in 101 | XCTAssertNil(error, "Expectation should not error") 102 | }) 103 | } 104 | 105 | func test_ThatNotificationIsPostedAndReceived_WithEmptyTupleAndNoSender() { 106 | // GIVEN: a notification 107 | let notif = Notification(name: "Notification") 108 | 109 | let expect = self.expectationWithDescription("\(#function)") 110 | 111 | // GIVEN: an observer 112 | let observer = NotificationObserver(notif, handler: { (value, sender) in 113 | XCTAssertNil(sender, "Sender should be nil") 114 | expect.fulfill() 115 | }) 116 | 117 | XCTAssertNotNil(observer) 118 | 119 | // WHEN: the notification is posted with an empty tuple and no sender 120 | notif.post(()) 121 | 122 | // THEN: the observer receives the notification and executes its handler 123 | self.waitForExpectationsWithTimeout(timeout, handler: { (error) in 124 | XCTAssertNil(error, "Expectation should not error") 125 | }) 126 | } 127 | 128 | func test_ThatNotificationIsPostedAndReceived_WithUserInfoAndSender() { 129 | // GIVEN: a userInfo dictionary 130 | let userInfo: UserInfo = ["someKey": 100, "anotherKey": NSDate()] 131 | 132 | // GIVEN: a notification 133 | let notif = Notification(name: "ExampleNotification", sender: self) 134 | 135 | let expect = self.expectationWithDescription("\(#function)") 136 | 137 | // GIVEN: an observer 138 | let observer = NotificationObserver(notif, handler: { [weak self] (value, sender) in 139 | XCTAssertTrue(value == userInfo, "Value should equal expected value") 140 | XCTAssertEqual(sender!, self, "Sender should equal expected sender") 141 | expect.fulfill() 142 | }) 143 | 144 | XCTAssertNotNil(observer) 145 | 146 | // WHEN: the notification is posted with userInfo and no sender 147 | notif.post(userInfo) 148 | 149 | // THEN: the observer receives the notification and executes its handler 150 | self.waitForExpectationsWithTimeout(timeout, handler: { (error) in 151 | XCTAssertNil(error, "Expectation should not error") 152 | }) 153 | } 154 | 155 | func test_ThatNotificationIsPostedAndReceived_WithUserInfoAndNoSender() { 156 | // GIVEN: a userInfo dictionary 157 | let userInfo = ["someKey": 100, "anotherKey": NSDate()] 158 | 159 | // GIVEN: a notification without a sender 160 | let notif = Notification<[String: NSObject], AnyObject>(name: "ExampleNotification") 161 | 162 | let expect = self.expectationWithDescription("\(#function)") 163 | 164 | // GIVEN: an observer 165 | let observer = NotificationObserver(notif, queue: .mainQueue(), center: .defaultCenter(), handler: { (value, sender) in 166 | XCTAssertEqual(value, userInfo, "Value should equal expected value") 167 | XCTAssertNil(sender, "Sender should be nil") 168 | expect.fulfill() 169 | }) 170 | 171 | XCTAssertNotNil(observer) 172 | 173 | // WHEN: the notification is posted with userInfo 174 | notif.post(userInfo) 175 | 176 | // THEN: the observer receives the notification and executes its handler 177 | self.waitForExpectationsWithTimeout(timeout, handler: { (error) in 178 | XCTAssertNil(error, "Expectation should not error") 179 | }) 180 | } 181 | 182 | func test_ThatNotificationIsPostedAndReceived_WithValueAndSender() { 183 | // GIVEN: a sender, value, and notification 184 | let fakeSender = TestSender() 185 | let fakeValue = TestValue() 186 | let notification = Notification(name: "NotificationName", sender: fakeSender) 187 | 188 | let expectation = self.expectationWithDescription("\(#function)") 189 | 190 | // GIVEN: an observer 191 | let observer = NotificationObserver(notification, handler: { (value, sender) in 192 | XCTAssertEqual(value, fakeValue, "Values should be equal") 193 | XCTAssertEqual(sender, fakeSender, "Senders should be equal") 194 | expectation.fulfill() 195 | }) 196 | 197 | XCTAssertNotNil(observer) 198 | 199 | // WHEN: the notification is posted 200 | notification.post(fakeValue) 201 | 202 | // THEN: the observer receives the notification and executes its handler 203 | self.waitForExpectationsWithTimeout(timeout, handler: { (error) in 204 | XCTAssertNil(error, "Expectation should not error") 205 | }) 206 | } 207 | 208 | func test_ThatNotificationIsPostedAndReceived_WithValueAndNoSender() { 209 | // GIVEN: a value, and notification without a sender 210 | let fakeValue = TestValue() 211 | let notification = Notification(name: "NotificationName") 212 | 213 | let expectation = self.expectationWithDescription("\(#function)") 214 | 215 | // GIVEN: an observer 216 | let observer = NotificationObserver(notification, handler: { (value, sender) in 217 | XCTAssertEqual(value.value, fakeValue.value, "Values should be equal") 218 | XCTAssertNil(sender, "Sender should be nil") 219 | expectation.fulfill() 220 | }) 221 | 222 | XCTAssertNotNil(observer) 223 | 224 | // WHEN: the notification is posted without a specific sender 225 | notification.post(fakeValue) 226 | 227 | // THEN: the observer receives the notification and executes its handler 228 | self.waitForExpectationsWithTimeout(timeout, handler: { (error) in 229 | XCTAssertNil(error, "Expectation should not error") 230 | }) 231 | } 232 | 233 | func test_ThatNotificationIsPostedAndReceived_WithNilValueAndNoSender() { 234 | // GIVEN: a notification with a sender 235 | let notification = Notification(name: "NotificationName") 236 | 237 | let expectation = self.expectationWithDescription("\(#function)") 238 | 239 | // GIVEN: an observer 240 | let observer = NotificationObserver(notification, handler: { (value, sender) in 241 | XCTAssertNil(value, "Value should be nil") 242 | XCTAssertNil(sender, "Sender should be nil") 243 | expectation.fulfill() 244 | }) 245 | 246 | XCTAssertNotNil(observer) 247 | 248 | // WHEN: the notification is posted without a specific sender 249 | notification.post(nil) 250 | 251 | // THEN: the observer receives the notification and executes its handler 252 | self.waitForExpectationsWithTimeout(timeout, handler: { (error) in 253 | XCTAssertNil(error, "Expectation should not error") 254 | }) 255 | } 256 | 257 | func test_ThatNotificationIsPostedAndReceived_TraditionalCocoa() { 258 | // GIVEN: a "traditional Cocoa" notification 259 | let notification = CocoaNotification(name: UIApplicationDidReceiveMemoryWarningNotification) 260 | 261 | let expectation = self.expectationWithDescription("\(#function)") 262 | 263 | // GIVEN: an "traditional Cocoa" observer 264 | let observer = CocoaObserver(notification, handler: { (notification: NSNotification) in 265 | expectation.fulfill() 266 | }) 267 | 268 | XCTAssertNotNil(observer) 269 | 270 | // WHEN: the notification is posted "by the system" 271 | NSNotificationCenter.defaultCenter().postNotificationName( 272 | notification.name, 273 | object: notification.sender, 274 | userInfo: nil) 275 | 276 | // THEN: the observer receives the notification and executes its handler 277 | self.waitForExpectationsWithTimeout(timeout, handler: { (error) in 278 | XCTAssertNil(error, "Expectation should not error") 279 | }) 280 | } 281 | 282 | func test_ThatObserverUnregistersForNotificationsOnDeinit() { 283 | // GIVEN: a notification and observer 284 | let fakeValue = TestValue() 285 | let notification = Notification(name: "NotificationName", sender: TestSender()) 286 | 287 | var didCallHandler = false 288 | var observer: NotificationObserver? = NotificationObserver(notification, handler: { (value, sender) in 289 | didCallHandler = true 290 | }) 291 | 292 | XCTAssertNotNil(observer) 293 | 294 | observer = nil 295 | 296 | // WHEN: the notification is posted after the observer is dealloc'd 297 | notification.post(fakeValue) 298 | 299 | // THEN: the observer does not receive the notification and does not execute its handler 300 | XCTAssertFalse(didCallHandler) 301 | } 302 | 303 | func test_ThatUserInfoObjectsAreEqual() { 304 | // GIVEN: two equal user info objects 305 | let first: UserInfo = [ 306 | "key0": "fake value", 307 | "key1": 234 308 | ] 309 | 310 | let second: UserInfo = [ 311 | "key0": "fake value", 312 | "key1": 234 313 | ] 314 | 315 | // WHEN: we compare them 316 | let result = (first == second) 317 | 318 | // THEN: they are equal 319 | XCTAssertTrue(result) 320 | } 321 | 322 | func test_ThatUserInfoObjectsAreNotEqual_MissingKeys() { 323 | // GIVEN: two distinct user info objects 324 | let first: UserInfo = [ 325 | "key0": "fake value", 326 | "key1": 234, 327 | "key2": NSDate() 328 | ] 329 | 330 | let second: UserInfo = [ 331 | "key0": "fake value" 332 | ] 333 | 334 | // WHEN: we compare them 335 | let result = (first == second) 336 | 337 | // THEN: they are not equal 338 | XCTAssertFalse(result) 339 | } 340 | 341 | func test_ThatUserInfoObjectsAreNotEqual_DifferentValues() { 342 | // GIVEN: two distinct user info objects 343 | let first: UserInfo = [ 344 | "key0": "fake value", 345 | "key1": 234, 346 | "key2": NSDate() 347 | ] 348 | 349 | let second: UserInfo = [ 350 | "key0": "different", 351 | "key1": 4567, 352 | "key2": NSDate() 353 | ] 354 | 355 | // WHEN: we compare them 356 | let result = (first == second) 357 | 358 | // THEN: they are not equal 359 | XCTAssertFalse(result) 360 | } 361 | 362 | func test_ThatUserInfoObjectsAreNotEqual_DifferentKeys() { 363 | // GIVEN: two distinct user info objects 364 | let first: UserInfo = [ 365 | "key0": "fake value", 366 | "key1": 234, 367 | "key2": NSDate() 368 | ] 369 | 370 | let second: UserInfo = [ 371 | "key7": "different", 372 | "key8": 4567, 373 | "key9": NSDate() 374 | ] 375 | 376 | // WHEN: we compare them 377 | let result = (first == second) 378 | 379 | // THEN: they are not equal 380 | XCTAssertFalse(result) 381 | } 382 | 383 | } 384 | --------------------------------------------------------------------------------