簡體   English   中英

如何觀察繼承對象屬性的變化並存儲以前的值?

[英]How to observe changes, and store previous values, of an inherited object's property?

設置:

我將SKSpriteNode()子類化以創建一個名為SubNode()的自定義子類。

SKSPriteNode() class 有一個名為physicsBody的屬性,它存儲一個SKPhysicsBody() object。 SKPhysicsBody有一個名為“velocity”的屬性,它是一個CGVector()

目標:

在我的子類中,我想要一個始終保留以前的CGVector()的變量。 例如,只要我調用subNode.physicsBody?.velocity = CGVector(dx: 10, dy: 10)就意味着。 subNode.previousVelocity應該設置為之前的subNode.physicsBody?.velocity值。

問題

如果velocity只是超類的繼承屬性,我可以override該屬性並附加一個didSet觀察者。 但是由於velocitySKPhysicsBody()的一個屬性,而SKPhysicsBody() object 在其中一個屬性發生變化時不會發生變化, didSet不會被觸發,我無法聽到它的變化。

如果我的解釋不清楚,請要求更多澄清。

我的子類:

class SubNode: SKSpriteNode {
    
    var previousVelocity: CGVector = .zero

    // This doesn't get triggered because the physiceBody object doesn't change when one of its properties changes.
    override var physicsBody: SKPhysicsBody? {
        didSet {
            previousVelocity = oldValue?.velocity
        }
    }
    
    // If velocity would be a property of the superclass, this would trigger.
    override var velocity: CGVector {
        didSet {
            previousVelocity = oldValue
        }
    }
}

從 SubNode() 子類創建 object 子節點,設置物理體,然后設置速度"

let subNode = SubNode()
subNode.physicsBody = SKPhysicsBody()
subNode.physicsBody?.velocity = CGVector(dx: 10, dy: 10)
subNode.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
//should be true: subnode.previousVelocity == CGVector(dx: 10, dy: 10)

這只是部分答案。 只是試圖找到解決問題的方法。

我試圖以某種方式找到解決方法。 我注意到,只要 object 的屬性發生更改,之前就會觸發 object 的吸氣劑。 我創建了以下游樂場文件,它似乎工作。 只要我更改 object 的文本,以前的名稱就會存儲在另一個變量中。 但從我的測試來看,這似乎有效。 我不確定我的邏輯是否正確,或者我是否遺漏了一些東西,實現應該更簡單的東西也可能有點太多了。

下面我為我的子類添加了代碼,並且到目前為止我可以測試它確實有效。 但是,我希望得到一些反饋,因為該解決方案可能存在缺陷。

import UIKit

class ObjectClass {
    var name: String = "Initial Name"
}

class SuperClass {
    var object: ObjectClass?
}

class SubClass: SuperClass {
    
    var _oldObjectName: [String?] = [nil]
    
    var oldObjectName: String? {
        _ = object?.name
        return _oldObjectName.first ?? nil
    }
    
    override var object: ObjectClass? {
        get {
            // Is also being called before the object has been written to.
            if !_oldObjectName.contains(super.object?.name) {
                _oldObjectName.append(super.object?.name)
                _oldObjectName = _oldObjectName.suffix(2)
            }
            return super.object
        }
        set {
            super.object = newValue
        }
    }
}

let subClass = SubClass()

subClass.object = ObjectClass()

將上述解決方案與我的子類一起使用:

class SubNode: SKSpriteNode {
    
    private var _previousVelocity: [CGVector?] = []
    var previousVelocity: CGVector {
        _ = physicsBody?.velocity
        return (_previousVelocity.first ?? CGVector.zero)!
    }
    
    override var physicsBody: SKPhysicsBody? {
        get {
            if !_previousVelocity.contains(super.physicsBody?.velocity) {
                _previousVelocity.append(super.physicsBody?.velocity)
                _previousVelocity = _previousVelocity.suffix(2)
            }
            return super.physicsBody
        }
        set {
            super.physicsBody = newValue
        }
    }
}

從我最初的測試來看,這似乎到目前為止有效:

let subNode = SubNode()
subNode.physicsBody = SKPhysicsBody()
subNode.physicsBody?.velocity = CGVector(dx: 10, dy: 10)
subNode.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
//true: subnode.previousVelocity == CGVector(dx: 10, dy: 10)

更新:

我發現這個解決方案的一個問題是,當 ObjectClass() 中的 object 首先創建為自己的變量,然后直接通過變量進行更改時,子類的 getter 將不會被觸發,直到通過子類訪問它。 就我而言,這不是問題,但絕對不理想。

let subClass = SubClass()

let object = ObjectClass()

subClass.object = object

// This won't trigger the getter obviously since the subclass is not accessed.
object.name = "New Name"
object.name = "Another Name"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM