Rasat 2.0.0

Rasat 2.0.0

Goksel Koksal维护。



Rasat 2.0.0

Rasat🗼

Carthage CocoaPods CI Status Platform Language License

Swtif中的pub-sub/observer模式实现的微库。👁

组件

通道📻

通道就是一个可以广播消息的事件总线。

enum UserEvent {
  case loggedIn(id: String)
  case loggedOut(id: String)
}

// Define a channel:
let userChannel = Channel<UserEvent>()

// Broadcast a message:
userChannel.broadcast(.loggedIn(id: "gokselkk"))

可观察对象👁

可观察对象使您能够监听通道上的消息。

// Listen for changes:
let subscription = userChannel.observable.subscribe { event in
  self.handleUserEvent(event)
}

// End the subscription when needed:
subscription.dispose()

主题📦

主题封装了一个值,并在变化时进行广播。

enum Theme {
  case light, dark
}

// Define a subject:
let themeSubject = Subject(Theme.light)

// Listen for changes:
themeSubject.observable.subscribe { theme in
  self.updateTheme(theme)
}

// Update the value:
themeSubject.value = .dark

示例🏰

监听视图控制器中的主题变更

class ThemeManager {

  var observable: Observable<Theme> {
    return channel.observable
  }
  
  private let channel = Channel<Theme>()
  
  func updateTheme(_ theme: Theme) {
    channel.broadcast(theme)
  }
}

class FeedViewController: UIViewController {
  
  var themeManager: ThemeManager!
  private let disposeBag = DisposeBag()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    disposeBag += themeManager.observable.subscribe { theme in
      self.updateTheme(theme)
    }
}

注意DisposeBag是一个集合,包含了订阅(或可处理)对象,需要在视图控制器生命周期内存在。在这个例子中,当视图控制器解除分配时,订阅对象会与DisposeBag一起被销毁。

动机

Apple框架广泛使用代理和观察者模式来传递信息。

  • 代理模式适用于一对一、双向通信。它被用来将工作委托给其他组件。
  • 观察者模式适用于一对一、单向通信。它被用来观察对象上的更改。

观察者模式的一些用法示例:

  • UIApplication发布willEnterForegroundNotification
  • UIResponder发布keyboardDidShowNotification

不要忘了,所有这些都在NotificationCenter.default实例上发生。这正是NotificationCenter的缺点所在。

  • 任何来源的任何通知都可以发布到它上面。
  • post(...)userInfo API都不是类型安全的。这导致了许多样板代码。
  • API不提倡关注点的分离。

Rasat旨在解决这些问题,并提供更多功能。

类型安全

Channel是类型安全的。类型安全也可以限制开发者为每种消息类型创建不同的通道,因此促进关注点的分离。

例如,键盘事件可以这样实现

enum KeyboardEvent {
  case didShow(frame: CGRect)
  case didDismiss(frame: CGRect)
}

let keyboardChannel = Channel<KeyboardEvent>()
// ...
let subscription = keyboardChannel.observable.subscribe { event in
  // Handle event here.
}

仅观察API与Observable

NotificationCenter提供统一的API用于广播和观察。如果您有一个NotificationCenter实例,您可以通过它广播或观察,没有限制。

这导致了几个问题

  • 有可能出错。某些对象只会被期望观察,而不是广播。使用纯NotificationCenter API无法实施这种限制。
  • 这降低了可读性。难以区分广播者和观察者。

例如

let center = NotificationCenter.default

// The object that posts notifications on given center:
let broadcaster = Broadcaster(notificationCenter: center)

// The object that observes notifications on given center: 
let observer = Observer(notificationCenter: center)

在这一刻,我们只是希望观察者不在给定的通知中心发布任何内容,而只观察广播者发布的通知。

可以使用ChannelObservable对以更安全、更方便的方式呈现

let channel = Channel<Message>()
let broadcaster = Broadcaster(channel: channel)
let observer = Observer(observable: channel.observable)

甚至更好,Broadcaster可以创建一个内部通道并使其观察者公开

let broadcaster = Broadcaster()
let observer = Observer(observable: broadcaster.observable)

安装

使用CocoaPods

将以下行添加到您的Podfile

pod 'Rasat'

使用Carthage

将以下行添加到您的Cartfile

github "gokselkoksal/Rasat"

手动安装

Sources文件夹拖到您的项目中。

强烈建议使用如CocoaPodsCarthage之类的依赖管理器。

许可证

Rasat提供MIT许可证。