Skip to content

A proposal on how to make the use of notifications more type-safe.

License

Notifications You must be signed in to change notification settings

wltrup/Swift-Typed-Notifications

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Typed Notifications

Swift Xcode

What

I recently watched some of the excellent Swift Talk episodes and two, in particular, got me thinking in a different direction than what they suggest in those talks. I'm speaking of typed notifications.

If you haven't watched them, you should. Actually, you should watch the entire series because there's a lot of good stuff there.

The problem

If you have done much iOS development, especially in the olden days of Objective-C, you'll have noticed that a lot of it is very much "stringly" typed, that is, a lot of things are determined by strings (NSString instances). Notifications are no exception and, in fact, are one of the more annoying examples. Not only the notification names are strings that you could accidentally mistype but the user-info dictionary is, well, a dictionary that can contain anything, of any object type. Upon receiving a notification, you have to make sure that everything in it has the expected type and then you do a lot of casting. That's very error-prone and there has to be a better, more swifty, way to handle all that.

My solution

I propose that you can define your custom notifications (and even wrap the system ones) as cases of an enumerated type satisfying a particular protocol. Here's an example of how you'd go about defining and using some silly custom notifications:

// Defining your custom notifications:
enum MyAppNotifs: NotificationEnum {

    case appHasLaunched(launchDate: Date)
    case appDownloadedData(title: String, index: Int)
    case appWillCrash(error: Error)

    var name: Notification.Name {
        switch self {
        case .appHasLaunched(_):
            return MyAppNotifs.appHasLaunchedNotif
        case .appDownloadedData(_, _):
            return MyAppNotifs.appDownloadedDataNotif
        case .appWillCrash(_):
            return MyAppNotifs.appWillCrashNotif
        }
    }

    static let appHasLaunchedNotif    = Notification.Name(rawValue: "MyAppNotifs.appHasLaunched")
    static let appDownloadedDataNotif = Notification.Name(rawValue: "MyAppNotifs.appDownloadedData")
    static let appWillCrashNotif      = Notification.Name(rawValue: "MyAppNotifs.appWillCrash")

}


// This is how an interested party would subscribe to receive notifications of a particular kind and case:
// (The token is an object you store --- say, in your view controller --- so that when the view controller
//  goes out of scope, the observer gets automatically removed from the notification center)
var token = center.addObserver(name: MyAppNotifs.appDownloadedDataNotif) {
    (notification: MyAppNotifs, object: Any?) in

    switch notification {
    case .appDownloadedData(let title, let index):
        print("title: \(title), index: \(index)")
    default:
        break
    }

}

// This is how a notification is posted. I think this reads particularly nicely.
let notif = MyAppNotifs.appDownloadedData(title: "Test", index: 5)
center.post(notification: notif)

For details and the full implementation of the necessary extensions, take a look at the playground in this repository.

License

The playground file is available under the MIT license. See the LICENSE file for more info.

About

A proposal on how to make the use of notifications more type-safe.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages