Giter VIP home page Giter VIP logo

emitter-kit's Introduction

EmitterKit wants to replace your NSNotification, key-value observation, and general event handling habits!

  • Simpler syntax!
  • Type safety with generic Event class!
  • Built-in one-time listeners!
  • Key-value observation for NSObjects!
  • Has a Notification class for backwards-compatibility with NSNotificationCenter!
  • Removes the need to call removeObserver() for NSNotifications!

Installation

Not yet available on CocoaPods.

For now, add EmitterKit.xcodeproj as a submodule in your Xcode project and add EmitterKit.framework as a target dependency in your Build Phases. Then, add a Copy Files phase in your Build Phases to the Frameworks directory, and add EmitterKit.framework.


Event

An Event emits data. Its generic parameter specifies what type of data it emits! This is awesome.

All listeners are removed when an Event is deallocated.

let didLogin = Event<User>()

didLogin.once { user in
  println("Successfully logged in as \(user.name)!")
}

didLogin.emit(user)

Event is a subclass of Emitter.

I tend to use Events as properties of my Swift classes, when it makes sense.

class MyScrollView : UIScrollView, UIScrollViewDelegate {
  let didScroll = Event<CGPoint>()
  
  override init () {
    super.init()
    delegate = self
  }
  
  func scrollViewDidScroll (scrollView: UIScrollView) {
    didScroll.emit(scrollView.contentOffset)
  }
}

Otherwise, I can use a target to associate an Event with a specific AnyObject. This is useful for classes I cannot add properties to, like UIView for example.

let myView = UIView()
let didTouch = Event<UITouch>()

didTouch.once(myView) {
  println("We have a winner! \($0)")
}

didTouch.emit(myView, touch)

Signal

A Signal is essentially an Event that can't pass data. Convenient, huh?

This is a subclass of Emitter, too.

let didLogout = Signal()

didLogout.once {
  println("Logged out successfully... :(")
}

didLogout.emit()

Notification

Notification wraps around NSNotification to provide backwards-compatibility with Apple's frameworks (e.g. UIKeyboardWillShowNotification) and third party frameworks.

Use it to create NotificationListeners that will remove themselves when deallocated. Now, you no longer have to call removeObserver() in your deinit phase!

You do not need to retain a Notification for your listener to work correctly. This is one reason why Notification does not subclass Emitter.

Notification(UIKeyboardWillShowNotification).once { data in
  println("keyboard showing. data: \(data)")
}

Listener

A Listener represents a closure that will be executed when an Emitter emits.

When a Listener is constructed, it starts listening immediately.

Toggle on and off by setting the isListening: Bool property.

If a Listener's once: Bool property == true, it will stop listening after it executes once.

Important: Remember to retain a Listener if once == false! Make a [Listener] property and put it there.

var listeners = [Listener]()

// Retain that sucka
listeners += mySignal.on {
  println("beep")
}

// Single-use Listeners retain themselves ;)
mySignal.once {
  println("boop")
}

Key-Value Observation

EmitterKit adds on(), once(), and removeListeners() instance methods to every NSObject.

let myView = UIView()
let myProperty = "layer.bounds" // supports dot-notation!

listeners += myView.on(myProperty) { 
  (values: Change<NSValue>) in
  println(values)
}

Check out the Change class to see what wonders it contains. It implements the Printable protocol for easy debugging!

The NSKeyValueObservingOptions you know and love are also supported! Valid values are .Old, .New, .Initial, .Prior, and nil. If you don't pass a value at all, it defaults to .Old | .New.

myView.once("backgroundColor", .Prior | .Old | .New) { 
  (change: Change<UIColor>) in
  println(change)
}

It runs on top of traditional KVO techniques, so everything works as expected!

WARNING: If you use these methods, you must call removeListeners(myListenerArray) before your NSObject deinits. Otherwise, your program will crash. I suggest making a subclass of UIView, overriding willMoveToWindow(), and putting removeListeners() in there. That's not always ideal if you're not working with a UIView, but that's all I use it for right now, so I can't help you in other cases.


Crafted by Alec Larson @aleclarsoniv

emitter-kit's People

Contributors

aleclarson avatar justinmakaila avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.