简体   繁体   English

当委托字段不称为`delegate`时实现`DelegateProxy`(RxSwift / RxCocoa)

[英]Implementing `DelegateProxy` (RxSwift/RxCocoa) when delegate field is not called `delegate`

I need some help with DelegateProxy implementation. 我需要有关DelegateProxy实施的帮助。 Specifically, what is the proper way of implementing it when the delegate field has different name than simply delegate ? 具体来说,当委托字段的名称不同于简单delegate名称时,实现它的正确方法是什么? Such as in SKPhysicsContactDelegate it is called contactDelegate . 例如在SKPhysicsContactDelegate它称为contactDelegate I tried defining a computed value delegate , but it did not do the trick - https://github.com/maxvol/RxSpriteKit/blob/master/Proxy/RxSKPhysicsContactDelegateProxy.swift 我尝试定义一个计算值delegate ,但没有成功-https: //github.com/maxvol/RxSpriteKit/blob/master/Proxy/RxSKPhysicsContactDelegateProxy.swift

It fails with "DelegateProxy has no factory of <PKPhysicsWorld: 0x280b18990>. Implement DelegateProxy subclass for <PKPhysicsWorld: 0x280b18990> first." 它失败,因为"DelegateProxy has no factory of <PKPhysicsWorld: 0x280b18990>. Implement DelegateProxy subclass for <PKPhysicsWorld: 0x280b18990> first." Perhaps it is not even related to the delegate field name, but this is the only difference with properly working proxies I could find. 也许它甚至与委托字段名称都不相关,但这是我能找到的与正常工作的代理唯一的区别。

UPDATE: Ha! 更新:哈! I just noticed that error message says PKPhysicsWorld , not SKPhysicsWorld . 我只是注意到错误消息显示PKPhysicsWorld而不是SKPhysicsWorld So my hypothesis is that it has something to do with the fact that object in DelegateProxyFactory.createProxy is a PKPhysicsWorld instead of SKPhysicsWorld and _factories[ObjectIdentifier(mirror.subjectType)] returns nil . 因此,我的假设是,与DelegateProxyFactory.createProxy中的objectPKPhysicsWorld而不是SKPhysicsWorld_factories[ObjectIdentifier(mirror.subjectType)]返回nil

The reason you are getting that error is because your registerKnownImplementations() function isn't getting run. 您收到该错误的原因是因为您的registerKnownImplementations()函数未运行。

The following gist should work: https://gist.github.com/dtartaglia/9f1f937628504ca56dbb1aac7d91df2b 以下要点应该起作用: https : //gist.github.com/dtartaglia/9f1f937628504ca56dbb1aac7d91df2b

The code is also below but the gist can be kept up to date: 代码也在下面,但要点可以保持最新:

//
//  SKPhysicsWorld+Rx.swift
//
//  Created by Daniel Tartaglia on 21 Jan 2019.
//  Copyright © 2019 Daniel Tartaglia. MIT License.
//

import RxSwift
import SpriteKit

public
extension Reactive where Base: SKPhysicsWorld {

    var didBegin: Observable<SKPhysicsContact> {
        return Observable.create { observer in
            physicsContatctDelegatesLock.lock(); defer { physicsContatctDelegatesLock.unlock() }
            let uuid = UUID()
            if let (delegate, beginners, enders) = physicsContatctDelegates[self.base] {
                var new = beginners
                new[uuid] = observer
                physicsContatctDelegates[self.base] = (delegate, new, enders)
            }
            else {
                let delegate = PhysicsContactDelegate(for: self.base)
                self.base.contactDelegate = delegate
                physicsContatctDelegates[self.base] = (delegate, [uuid: observer], [:])
            }

            return Disposables.create {
                physicsContatctDelegatesLock.lock(); defer { physicsContatctDelegatesLock.unlock() }
                let (delegate, beginners, enders) = physicsContatctDelegates[self.base]!
                var new = beginners
                new.removeValue(forKey: uuid)
                if new.isEmpty && enders.isEmpty {
                    physicsContatctDelegates.removeValue(forKey: self.base)
                }
                else {
                    physicsContatctDelegates[self.base] = (delegate, new, enders)
                }
            }
        }
    }

    var didEnd: Observable<SKPhysicsContact> {
        return Observable.create { observer in
            physicsContatctDelegatesLock.lock(); defer { physicsContatctDelegatesLock.unlock() }
            let uuid = UUID()
            if let (delegate, beginners, enders) = physicsContatctDelegates[self.base] {
                var new = enders
                new[uuid] = observer
                physicsContatctDelegates[self.base] = (delegate, beginners, new)
            }
            else {
                let delegate = PhysicsContactDelegate(for: self.base)
                self.base.contactDelegate = delegate
                physicsContatctDelegates[self.base] = (delegate, [:], [uuid: observer])
            }

            return Disposables.create {
                physicsContatctDelegatesLock.lock(); defer { physicsContatctDelegatesLock.unlock() }
                let (delegate, beginners, enders) = physicsContatctDelegates[self.base]!
                var new = enders
                new.removeValue(forKey: uuid)
                if new.isEmpty && enders.isEmpty {
                    physicsContatctDelegates.removeValue(forKey: self.base)
                }
                else {
                    physicsContatctDelegates[self.base] = (delegate, beginners, new)
                }
            }
        }
    }
}

private
class PhysicsContactDelegate: NSObject, SKPhysicsContactDelegate {

    init(for world: SKPhysicsWorld) {
        self.world = world
        super.init()
    }

    func didBegin(_ contact: SKPhysicsContact) {
        physicsContatctDelegatesLock.lock(); defer { physicsContatctDelegatesLock.unlock() }
        let (_, beginners, _) = physicsContatctDelegates[world]!
        for each in beginners.values {
            each.onNext(contact)
        }
    }

    func didEnd(_ contact: SKPhysicsContact) {
        physicsContatctDelegatesLock.lock(); defer { physicsContatctDelegatesLock.unlock() }
        let (_, _, enders) = physicsContatctDelegates[world]!
        for each in enders.values {
            each.onNext(contact)
        }
    }

    let world: SKPhysicsWorld
}

private let physicsContatctDelegatesLock = NSRecursiveLock()
private var physicsContatctDelegates: [SKPhysicsWorld: (SKPhysicsContactDelegate, [UUID: AnyObserver<SKPhysicsContact>], [UUID: AnyObserver<SKPhysicsContact>])] = [:]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM