-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4c0fca0
commit b70d8c9
Showing
9 changed files
with
791 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
7 changes: 7 additions & 0 deletions
7
SwiftNotifications.xcodeproj/project.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
99 changes: 99 additions & 0 deletions
99
SwiftNotifications.xcodeproj/xcshareddata/xcschemes/SwiftNotifications.xcscheme
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<Scheme | ||
LastUpgradeVersion = "0810" | ||
version = "1.3"> | ||
<BuildAction | ||
parallelizeBuildables = "YES" | ||
buildImplicitDependencies = "YES"> | ||
<BuildActionEntries> | ||
<BuildActionEntry | ||
buildForTesting = "YES" | ||
buildForRunning = "YES" | ||
buildForProfiling = "YES" | ||
buildForArchiving = "YES" | ||
buildForAnalyzing = "YES"> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "9FBE0F541E095EB600604C8F" | ||
BuildableName = "SwiftNotifications.framework" | ||
BlueprintName = "SwiftNotifications" | ||
ReferencedContainer = "container:SwiftNotifications.xcodeproj"> | ||
</BuildableReference> | ||
</BuildActionEntry> | ||
</BuildActionEntries> | ||
</BuildAction> | ||
<TestAction | ||
buildConfiguration = "Debug" | ||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
shouldUseLaunchSchemeArgsEnv = "YES"> | ||
<Testables> | ||
<TestableReference | ||
skipped = "NO"> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "9FBE0F5D1E095EB600604C8F" | ||
BuildableName = "SwiftNotificationsTests.xctest" | ||
BlueprintName = "SwiftNotificationsTests" | ||
ReferencedContainer = "container:SwiftNotifications.xcodeproj"> | ||
</BuildableReference> | ||
</TestableReference> | ||
</Testables> | ||
<MacroExpansion> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "9FBE0F541E095EB600604C8F" | ||
BuildableName = "SwiftNotifications.framework" | ||
BlueprintName = "SwiftNotifications" | ||
ReferencedContainer = "container:SwiftNotifications.xcodeproj"> | ||
</BuildableReference> | ||
</MacroExpansion> | ||
<AdditionalOptions> | ||
</AdditionalOptions> | ||
</TestAction> | ||
<LaunchAction | ||
buildConfiguration = "Debug" | ||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
launchStyle = "0" | ||
useCustomWorkingDirectory = "NO" | ||
ignoresPersistentStateOnLaunch = "NO" | ||
debugDocumentVersioning = "YES" | ||
debugServiceExtension = "internal" | ||
allowLocationSimulation = "YES"> | ||
<MacroExpansion> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "9FBE0F541E095EB600604C8F" | ||
BuildableName = "SwiftNotifications.framework" | ||
BlueprintName = "SwiftNotifications" | ||
ReferencedContainer = "container:SwiftNotifications.xcodeproj"> | ||
</BuildableReference> | ||
</MacroExpansion> | ||
<AdditionalOptions> | ||
</AdditionalOptions> | ||
</LaunchAction> | ||
<ProfileAction | ||
buildConfiguration = "Release" | ||
shouldUseLaunchSchemeArgsEnv = "YES" | ||
savedToolIdentifier = "" | ||
useCustomWorkingDirectory = "NO" | ||
debugDocumentVersioning = "YES"> | ||
<MacroExpansion> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "9FBE0F541E095EB600604C8F" | ||
BuildableName = "SwiftNotifications.framework" | ||
BlueprintName = "SwiftNotifications" | ||
ReferencedContainer = "container:SwiftNotifications.xcodeproj"> | ||
</BuildableReference> | ||
</MacroExpansion> | ||
</ProfileAction> | ||
<AnalyzeAction | ||
buildConfiguration = "Debug"> | ||
</AnalyzeAction> | ||
<ArchiveAction | ||
buildConfiguration = "Release" | ||
revealArchiveInOrganizer = "YES"> | ||
</ArchiveAction> | ||
</Scheme> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>CFBundleDevelopmentRegion</key> | ||
<string>en</string> | ||
<key>CFBundleExecutable</key> | ||
<string>$(EXECUTABLE_NAME)</string> | ||
<key>CFBundleIdentifier</key> | ||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
<key>CFBundleInfoDictionaryVersion</key> | ||
<string>6.0</string> | ||
<key>CFBundleName</key> | ||
<string>$(PRODUCT_NAME)</string> | ||
<key>CFBundlePackageType</key> | ||
<string>FMWK</string> | ||
<key>CFBundleShortVersionString</key> | ||
<string>1.0.0</string> | ||
<key>CFBundleVersion</key> | ||
<string>$(CURRENT_PROJECT_VERSION)</string> | ||
<key>NSPrincipalClass</key> | ||
<string></string> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
public extension NotificationCenter { | ||
public func watch<T: SerializableNotification>( | ||
_ object: AnyObject? = nil, | ||
queue: OperationQueue = OperationQueue.main, | ||
handler: @escaping (T) -> Void) -> NSObjectProtocol | ||
{ | ||
return addObserver( | ||
forName: T.notificationName, | ||
object: object, | ||
queue: queue, | ||
using: { notification in | ||
guard let userInfo = notification.userInfo else { | ||
fatalError("Serializable notifications require userInfo") | ||
} | ||
|
||
do { | ||
let serializedNotification = try T(userInfo: userInfo as [NSObject : AnyObject]) | ||
|
||
handler(serializedNotification) | ||
} catch { | ||
fatalError("Error during deserialization of notification: \(error)") | ||
} | ||
}) | ||
} | ||
|
||
public func post<T: SerializableNotification>(_ notification: T, object: AnyObject? = nil) { | ||
self.post(name: T.notificationName, object: object, userInfo: notification.toUserInfo()) | ||
} | ||
|
||
public func post(_ name: Notification.Name, object: AnyObject? = nil) { | ||
self.post(name: name, object: object, userInfo: nil) | ||
} | ||
|
||
public func watch( | ||
for name: Notification.Name, | ||
object: AnyObject? = nil, | ||
queue: OperationQueue = OperationQueue.main, | ||
handler: @escaping (Void) -> Void) -> NSObjectProtocol | ||
{ | ||
return addObserver(forName: name, object: object, queue: queue) { _ in | ||
handler() | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
public protocol SerializableNotification { | ||
init(userInfo: [AnyHashable: Any]) throws | ||
|
||
static var notificationName: Notification.Name { get } | ||
|
||
func toUserInfo() -> [AnyHashable: Any]? | ||
} | ||
|
||
public extension SerializableNotification { | ||
public static var notificationName: Notification.Name { | ||
return Notification.Name("\(Self.self)") | ||
} | ||
} | ||
|
||
public enum NotificationSerializationError: Error { | ||
case noUserInfo, missingRequiredInfo | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// | ||
// SwiftNotifications.h | ||
// SwiftNotifications | ||
// | ||
// Created by Allen on 20/12/16. | ||
// Copyright © 2016 Allen. All rights reserved. | ||
// | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
//! Project version number for SwiftNotifications. | ||
FOUNDATION_EXPORT double SwiftNotificationsVersionNumber; | ||
|
||
//! Project version string for SwiftNotifications. | ||
FOUNDATION_EXPORT const unsigned char SwiftNotificationsVersionString[]; | ||
|
||
// In this header, you should import all the public headers of your framework using statements like #import <SwiftNotifications/PublicHeader.h> | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>CFBundleDevelopmentRegion</key> | ||
<string>en</string> | ||
<key>CFBundleExecutable</key> | ||
<string>$(EXECUTABLE_NAME)</string> | ||
<key>CFBundleIdentifier</key> | ||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
<key>CFBundleInfoDictionaryVersion</key> | ||
<string>6.0</string> | ||
<key>CFBundleName</key> | ||
<string>$(PRODUCT_NAME)</string> | ||
<key>CFBundlePackageType</key> | ||
<string>BNDL</string> | ||
<key>CFBundleShortVersionString</key> | ||
<string>1.0.0</string> | ||
<key>CFBundleVersion</key> | ||
<string>1</string> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import XCTest | ||
|
||
@testable import SwiftNotifications | ||
|
||
class SerializableNotificationTests: XCTestCase { | ||
private var listener: NSObjectProtocol? | ||
|
||
private let notificationName = Notification.Name("test") | ||
|
||
override func tearDown() { | ||
if let listener = listener { | ||
NotificationCenter.default.removeObserver(listener) | ||
} | ||
|
||
super.tearDown() | ||
} | ||
|
||
func testWatchForName_notificationObserverEstablished() { | ||
runAsyncTest { expectation in | ||
listener = NotificationCenter.default.watch(for: notificationName) { | ||
expectation.fulfill() | ||
} | ||
|
||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: nil) | ||
} | ||
} | ||
|
||
func testPostName_notificationDelivered() { | ||
runAsyncTest { expectation in | ||
listener = NotificationCenter.default.addObserver( | ||
forName: notificationName, | ||
object: nil, | ||
queue: OperationQueue.main, | ||
using: { _ in | ||
expectation.fulfill() | ||
}) | ||
|
||
NotificationCenter.default.post(notificationName) | ||
} | ||
} | ||
|
||
func testWatchForSerializableNotification_notificationObserverEstablished() { | ||
runAsyncTest { expectation in | ||
let expectedString = "alsdkjfaldkjf" | ||
let expectedNumber = 84 | ||
listener = NotificationCenter.default.watch { (notification: TestNotification) in | ||
XCTAssertEqual(expectedString, notification.string) | ||
XCTAssertEqual(expectedNumber, notification.number) | ||
|
||
expectation.fulfill() | ||
} | ||
|
||
NotificationCenter.default.post( | ||
name: TestNotification.notificationName, | ||
object: nil, | ||
userInfo: [ | ||
"number": expectedNumber, | ||
"string": expectedString]) | ||
} | ||
} | ||
|
||
func testPostSerializableNotification_notificationDelivered() { | ||
runAsyncTest { expectation in | ||
let expectedString = "sljkt" | ||
let expectedNumber = 432 | ||
|
||
listener = NotificationCenter.default.addObserver( | ||
forName: TestNotification.notificationName, | ||
object: nil, | ||
queue: OperationQueue.main, | ||
using: { notification in | ||
guard let userInfo = notification.userInfo else { | ||
XCTFail("missing userInfo") | ||
return | ||
} | ||
|
||
XCTAssertEqual(expectedString, userInfo["string"] as? String) | ||
XCTAssertEqual(expectedNumber, userInfo["number"] as? Int) | ||
XCTAssertEqual(2, userInfo.count) | ||
expectation.fulfill() | ||
}) | ||
|
||
NotificationCenter.default.post(TestNotification(string: expectedString, number: expectedNumber)) | ||
} | ||
} | ||
|
||
private func runAsyncTest(testBody: (XCTestExpectation) -> Void) { | ||
let expectation = self.expectation(description: #function) | ||
|
||
testBody(expectation) | ||
|
||
waitForExpectations(timeout: 1) { | ||
if let error = $0 { | ||
XCTFail(error.localizedDescription) | ||
} | ||
} | ||
} | ||
|
||
private struct TestNotification: SerializableNotification { | ||
let string: String | ||
let number: Int | ||
|
||
init(string: String, number: Int) { | ||
self.string = string | ||
self.number = number | ||
} | ||
|
||
init(userInfo: [AnyHashable: Any]) throws { | ||
guard | ||
let string = userInfo["string"] as? String, | ||
let number = userInfo["number"] as? Int else | ||
{ | ||
throw NotificationSerializationError.missingRequiredInfo | ||
} | ||
|
||
self.string = string | ||
self.number = number | ||
} | ||
|
||
func toUserInfo() -> [AnyHashable: Any]? { | ||
return [ | ||
"string": string, | ||
"number": number] | ||
} | ||
} | ||
} |