Реализация `DelegateProxy` (RxSwift / RxCocoa), когда поле делегата не называется` делегат`

Из в блоге Guido :

Вычисление MRO было официально задокументировано как использование пройденного по глубине первого слева направо классов, как и раньше. Если какой-либо класс был дублирован в этом поиске, все, кроме последнего вхождения, будут удалены из списка MRO.

Итак, если у вас есть, например:

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

Вместо простого порядка разрешения глубины в D, B, A, C, A, MRO удаляет все, кроме последнего экземпляра повторяющегося элемента, поэтому у вас есть D, B, C, A. В вашем случае ваш класс C не называет его super() (поскольку вы его прокомментировали). Таким образом, если я не ошибаюсь, MRO отзывает вызов до A до C, но поскольку C не вызывает его super(), вы никогда не увидите A.go():

D.go() --> B.go() (--> A.go() removed by MRO) --> C.go() (x> A.go() not called)
]

0
задан Maxim Volgin 21 January 2019 в 06:15
поделиться

1 ответ

Причина, по которой вы получаете эту ошибку, в том, что ваша функция registerKnownImplementations() не запускается.

Должна работать следующая суть: https://gist.github.com/dtartaglia/9f1f937628504ca56dbb1aac7d91df2b

Код также приведен ниже, но суть может быть обновлена: [ 115]

//
//  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>])] = [:]
0
ответ дан Daniel T. 21 January 2019 в 06:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: