- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
这是一个非常具体和冗长的问题,但我不够聪明,无法自己解决..
我对 this YouTube-video 很感兴趣来自 raywenderlich.com,它使用“装箱”方法观察值。
他们的 Box
看起来像这样:
class Box<T> {
typealias Listener = T -> Void
var listener: Listener?
var value: T {
didSet {
listener?(value)
}
init(_ value: T) {
self.value = value
}
func bind(listener: Listener?) {
self.listener = listener
listener?(value)
}
}
很明显,每个“框”只允许一个 监听器。
let bindable:Box<String> = Box("Some text")
bindable.bind { (text) in
//This will only be called once (from initial setup)
}
bindable.bind { (text) in
// - because this listener has replaced it. This one will be called when value changes.
}
每当设置这样的绑定(bind)时,之前的绑定(bind)将被释放,因为 Box
替换 listener
与新的听众。
我需要能够从不同的地方观察到相同的值。我修改了 Box
像这样:
class Box<T> {
typealias Listener = (T) -> Void
var listeners:[Listener?] = []
var value:T{
didSet{
listeners.forEach({$0?(value)})
}
}
init(_ value:T){
self.value = value
}
func bind(listener:Listener?){
self.listeners.append(listener)
listener?(value)
}
}
但是 - 这也给我带来了麻烦,显然..有些地方我想要新绑定(bind)删除旧绑定(bind)。例如,如果我从可重用 UITableViewCell
中观察对象中的值, 滚动时会绑定(bind)几次。我现在需要一种可控的方式来处理特定的绑定(bind)。
我试图通过将这个函数添加到 Box
来解决这个问题:
func freshBind(listener:Listener?){
self.listeners.removeAll()
self.bind(listener)
}
这在某种程度上起作用了,我现在可以使用 freshBind({})
每当我想删除旧的听众时,但这也不是我想要的。在观察来自 UITableViewCell
的值时,我必须使用它s,但我还需要从其他地方观察到相同的值。一旦单元被重用,我就删除了旧的观察者以及我需要的其他观察者。
我现在确信我需要一种方法来保留一次性元素,无论我以后想把它们放在什么地方。
我不够聪明,无法自己解决这个问题,所以我需要帮助。
我几乎没有使用过一些响应式编程框架(比如 ReactiveCocoa),现在我明白了为什么他们的订阅会返回 Disposable
我必须保留并在需要时处理的元素。我需要这个功能。
我想要的是:func bind(listener:Listener?)->Disposable{}
我的计划是创建一个名为 Disposable
的类其中包含(可选)监听器,然后转 listeners:[Listener?]
进入listeners:[Disposable]
, 但我遇到了 <T>
的问题..
Cannot convert value of type 'Box<String?>.Disposable' to expected argument type 'Box<Any>.Disposable'
有什么聪明的建议吗?
最佳答案
我想解决这个问题的方法是给每个观察者一个唯一的标识符(比如 UUID),并使用它来允许 Disposable 在适当的时候移除观察者。例如:
import Foundation
// A Disposable holds a `dispose` closure and calls it when it is released
class Disposable {
let dispose: () -> Void
init(_ dispose: @escaping () -> Void) { self.dispose = dispose }
deinit { dispose() }
}
class Box<T> {
typealias Listener = (T) -> Void
// Replace your array with a dictionary mapping
// I also made the Observer method mandatory. I don't believe it makes
// sense for it to be optional. I also made it private.
private var listeners: [UUID: Listener] = [:]
var value: T {
didSet {
listeners.values.forEach { $0(value) }
}
}
init(_ value: T){
self.value = value
}
// Now return a Disposable. You'll get a warning if you fail
// to retain it (and it will immediately be destroyed)
func bind(listener: @escaping Listener) -> Disposable {
// UUID is a nice way to create a unique identifier; that's what it's for
let identifier = UUID()
// Keep track of it
self.listeners[identifier] = listener
listener(value)
// And create a Disposable to clean it up later. The Disposable
// doesn't have to know anything about T.
// Note that Disposable has a strong referene to the Box
// This means the Box can't go away until the last observer has been removed
return Disposable { self.listeners.removeValue(forKey: identifier) }
}
}
let b = Box(10)
var disposer: Disposable? = b.bind(listener: { x in print(x)})
b.value = 5
disposer = nil
b.value = 1
// Prints:
// 10
// 5
// (Doesn't print 1)
这可以很好地扩展到像 DisposeBag
这样的概念:
// Nothing but an array of Disposables.
class DisposeBag {
private var disposables: [Disposable] = []
func append(_ disposable: Disposable) { disposables.append(disposable) }
}
extension Disposable {
func disposed(by bag: DisposeBag) {
bag.append(self)
}
}
var disposeBag: DisposeBag? = DisposeBag()
b.bind { x in print("bag: \(x)") }
.disposed(by: disposeBag!)
b.value = 100
disposeBag = nil
b.value = 500
// Prints:
// bag: 1
// bag: 100
// (Doesn't print "bag: 500")
自己构建一些这样的东西很好,这样您就可以了解它们的工作原理,但对于严肃的项目来说,这通常是不够的。主要问题是它不是线程安全的,因此如果在后台线程上处理某些内容,您可能会破坏整个系统。您当然可以使其成为线程安全的,这并不难。
但后来您意识到您真的想要编写听众。您需要一个监听器来观察另一个监听器并对其进行转换。所以你构建 map
。然后你意识到你想要过滤值被设置为其旧值的情况,所以你构建了一个“只向我发送不同的值”然后你意识到你想要 filter
来帮助你,并且然后....
你意识到你正在重建 RxSwift。
这根本不是避免自己编写的理由,RxSwift 包含许多项目永远不需要的大量功能(可能是太多的功能),但是在进行过程中,您应该不断问自己“我应该现在切换到 RxSwift 了吗?”
关于ios - 使用 "Boxing"样式的多重绑定(bind)和处置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50135742/
释放 MKMapView 后,我遇到了奇怪的(?)崩溃。 MKMapView 是我的 View Controller 中的 subview ,在我从导航堆栈中删除该 View 并释放它后,应用程序崩溃
我正在尝试使用以下方法处理我的 JFrame: private void killJFrame(JFrame jFrame) { SwingUtilities.invokeLater(() -
我用的是asp net 4.5。 我有 Marker.aspx 页面和页面 Marker.aspx.cs 背后的代码。每当回发发生时,Page_Load 函数将在代码隐藏中触发并创建 GeoMarku
在 C# 中,如 Documentation 中所述, 和 this nice post接受的答案,声明类不继承其父类的析构函数。 问题:如果我想确保释放基类的私有(private)元素,在所有子类中
我想知道是否有人知道如何知道 InheritedWidget 何时被释放? 这个问题的原因是我正在做一些实验,并且我正在使用 InheritedWidget 作为 BLoC 的提供者。此 BLoC 在
如果应用程序意外关闭,如何安全地处理 ReportViewer 对象 Public Shared rv As New Microsoft.Reporting.WinForms.ReportViewe
有没有办法销毁 WebView 实例?如果页面加载,并说视频开始播放,我希望能够,当我隐藏 WebView 时,基本上可以销毁它,或者至少重置它。 我知道我可以听 visibleProperty 并执
在总体情况下,Close 方法在语义上只是更改对象的状态,而该对象可以使用 Open 方法无限期地再次更改。 另一方面,IDisposable.Dispose() 方法的语义将对象置于无法撤消的状态。
我使用StreamResourceInfo.Stream从资源中获取BitmapImage。使用流后 Close 和 Dispose 是否正确?我问这个问题是因为在内存分析器中,如果这样做我会收到错误
我正在编写一个程序,显示在屏幕上移动的图像,但是对于作业,我必须使用drawImage方法。我创建一个名为turtle的新图像,然后在一个点绘制该图像,然后在稍后的时间点再次绘制它,但是,第一个绘制的
这个问题在这里已经有了答案: Do you need to dispose of objects and set them to null? (12 个答案) 关闭 4 年前。 我在我的代码中使用
我有一个使用 Entity Framework 的 MVC 3 应用程序,我在其中设置了自定义角色提供程序。 我的角色提供者依赖于一个存储库,而该存储库依赖于 DbContext。 我在应用程序启动方
我正在尝试创建处理整个 BST 的迭代方法。 通过函数 insert_nodes 插入节点后,我没有得到预期的输出。 它应该打印如下内容:left,right, #nr #nr #nr 对于数字 5,
我正在使用 MemoryAppender 来读取单元测试中的日志消息。 我按以下方式使用 BasicConfigurator: class LogVerifier { pr
谁能给出一个完整的例子来说明 qooxdoo 1.6 中的 dispose 和 destruct 是如何工作的? ,我在 qooxdoo 演示或文档中找不到任何好的示例。 谢谢你的建议。 最佳答案 处
我在处理屏幕时遇到问题。当我尝试处置 OrthogonalTiledMapRenderer 时,收到此错误消息。我在网上查了一下,没有发现任何其他这样的例子或发生这种情况的情况。 Exception
我正在使用匿名方法来处理 COM 对象中的事件。程序终止后,我在匿名方法中使用的资源似乎没有被“正确关闭”,因为我正在观看的每个资源都会出现第一次机会异常 (InvalidComObjectExcep
我有一个用 C# 编写的方法,它接受一个包含 XML 文档的字符串和一个 XSD 流数组。字符串文档根据 XSD 进行验证: private static XmlValidationResult Va
有没有办法“清理”您创建的对象和其他变量?还是它们会自动处理掉,或者我的整个概念都错了?这样做的正确方法是什么?我尽量避免 GC。 最佳答案 在没有内存管理的 GC 语言中,唯一的清理方法是 GC 。
当您在 ASP.Net 框架中创建和使用 Web 服务代理类时,该类最终继承自 Component,后者实现了 IDisposable。 我从未在网上看到过人们处理 Web 代理类的例子,但想知道是否
我是一名优秀的程序员,十分优秀!