针对 Swift 和 Objective-C 的现代线程安全和类型安全键值观察

现已存档和分叉

PMKVObserver以后将不会在此存储库中维护。请使用位于此处的 PMKVObserver 的分支,在上面创建问题并进行 PR。

PMKVObserver

版本
平台
语言
许可证
迦太基兼容
可可豆荚

PMKVObserver 围绕键值观察提供了一个安全的基于块的包装器,其中包含适用于 Obj-C 和 Swift 的 API。功能包括:

  • 线程安全。观察者可以在与发送 KVO 通知不同的线程上注册,并且可以在另一个线程上取消。甚至可以同时从两个线程中取消观察器。
  • 当观察到的对象解除分配时自动取消注册。
  • 支持提供提供给块的观察对象,并在该观察对象解除分配时自动取消注册。这使您可以调用方法而不保留它或处理弱引用。self
  • 自动释放的线程安全。这可以防止在对象解除分配时在另一个线程上接收消息。
  • 对 Obj-C 和 Swift 的一流支持,包括 Swift API 中的强类型。

例子

迅速

// Observe an object for as long as the object is alive.
_ = KVObserver(object: user, keyPath: \User.fullName) { object, _, _ in
    // `object` has the same type as `user`
    print("User's full name changed to \(object.fullName)")
}

// Convenience methods for working with the change dictionary
_ = KVObserver(object: user, keyPath: \User.fullName, options: [.old, .new]) { _, change, _ in
    // unfortunately we don't know what the type of fullName is, so change uses Any
    let old = change.old as? String
    let new = change.new as? String
    if old != new {
        print("User's full name changed to \(new ?? "nil")")
    }
}

// Unregistering can be done from within the block, even in an .initial callback
_ = KVObserver(object: user, keyPath: \User.fullName, options: [.initial]) { object, _, kvo in
    guard !object.fullName.isEmpty else { return }
    print("User's full name is \(object.fullName)")
    kvo.cancel()
}

// Or you can unregister externally
let token = KVObserver(object: user, keyPath: \User.fullName) { object, _, _ in
    print("User's full name changed to \(object.fullName)")
}
// ... sometime later ...
token.cancel()

// You can also pass an observing object and KVO will be unregistered when that object deallocates
_ = KVObserver(observer: self, object: user, keyPath: \User.fullName) { observer, object, _, _ in
    // `observer` has the same type as `self`
    observer.nameLabel.text = object.fullName
}
迅速

Objective-C

Objective-C provides all the same functionality as Swift, albeit without the strong-typing of the observer/object.

// Observe an object for as long as the object is alive.
[PMKVObserver observeObject:self.user keyPath:@"fullName" options:0
                      block:^(id  _Nonnull object, NSDictionary<NSKeyValueChangeKey,id> * _Nullable change, PMKVObserver * _Nonnull kvo) {
    NSLog(@"User's full name changed to %@", [object fullName]);
}];

// Change dictionary is provided, but without the convenience methods.
[PMKVObserver observeObject:self.user keyPath:@"fullName"
                    options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
                      block:^(id  _Nonnull object, NSDictionary<NSKeyValueChangeKey,id> * _Nullable change, PMKVObserver * _Nonnull kvo) {
    NSString *old = change[NSKeyValueChangeOldKey];
    NSString *new = change[NSKeyValueChangeNewKey];
    if (old != new && (new == nil || ![old isEqualToString:new])) {
        NSLog(@"User's full name changed to %@", new);
    }
}];

// Unregistering and observing object support is also provided (see Swift examples).
Objc

Requirements

Installing as a framework requires a minimum of iOS 8, OS X 10.9, watchOS 2.0, or tvOS 9.0.

If you install by copying the source into your project, it should work on iOS 7 or later (iOS 6 if you remove KVObserver.swift), and OS X 10.7 or later. Please note that it has not been tested on these versions.

PMKVObserver requires Xcode 9 or higher.

Installation

After installing with any mechanism, you can use this by adding (Swift) or (Objective-C) to your code.import PMKVObserver@import PMKVObserver;

Carthage

To install using Carthage, add the following to your Cartfile:

github "postmates/PMKVObserver" ~> 4.0

CocoaPods

To install using CocoaPods, add the following to your Podfile:

pod 'PMKVObserver', '~> 4.0'

Manual Installation

You may also install manually by adding the framework to your workspace, or by adding the 3 files KVObserver.h, KVObserver.m, and (optionally) KVObserver.swift to your project.

License

Licensed under either of

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions.

Version History

v4.1.3 (2020-04-01)

  • Work around bug with Swift compiler 5.1.5 and above relating to properties of type (#25, SR-12486).Any?

v4.1.2 (2019-01-24)

  • Fix compatibility with Swift compiler versions other than 4.2 when observing optional values and KVO delivers an value.NSNull

v4.1.1 (2018-11-28)

  • Add and properties to . The property is named in Swift..object.keyPathPMKVObserver.keyPath.objcKeyPath

v4.1.0 (2018-11-27)

  • Handle observing optional values better. We now make stronger guarantees about when and are non-..old.newnil

v4.0.0 (2018-09-05)

  • Set Swift version to 4.

  • Work around Xcode 10 issue with value conversions involving in the object (SR-8704).AnyKVObserver.Change

  • Handle types in 's and properties.RawRepresentableKVObserver.Change.old.new

    Note: Optional types (such as those produced by a path like ) are only supported in Swift 4.1 and later.RawRepresentable\.foo?.bar

v3.0.2 (2018-05-22)

  • Squelch some warnings when building with CocoaPods.

v3.0.1 (2017-09-13)

  • Set Swift version back to Swift 3.2. The new stuff is usable from 3.2 so there's no reason to require 4. PMVKObserver will still compile with Swift 3.1, but the APIs won't be available unless compiling with Swift 3.2.KeyPathKeyPath

v3.0.0 (2017-09-12)

  • Convert to Swift 4.
  • Add new initializers that use Swift 4 s.KeyPath
  • Make and non-optional.Change.rawDictChange.kind

v2.0.2 (2017-07-25)

  • Switch to an unfair lock in teardown. This uses on platforms that support it, otherwise it uses an unfair mutex.os_unfair_lock

v2.0.1 (2016-09-15)

  • Fix CocoaPods.

v2.0.0 (2016-09-08)

  • Update for Swift 3.0.

v1.0.5 (2016-09-08)

  • Update for Swift 2.3.

v1.0.4 (2016-03-02)

  • Update CocoaPods podspec to split Swift support into a subspec.

v1.0.3 (2015-01-28)

  • Add property to .cancelledPMKVObserver

v1.0.2 (2016-01-26)

  • Switch to dual-licensed as MIT or Apache 2.0.

v1.0.1 (2015-12-17)

  • Stop leaking our s.pthread_mutex_t

v1.0 (2015-12-17)

Initial release.

GitHub

https://github.com/postmates/PMKVObserver/