Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/106.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 斯威夫特:倾听;结构变量"-改变事件?_Ios_Swift_Struct_Instance - Fatal编程技术网

Ios 斯威夫特:倾听;结构变量"-改变事件?

Ios 斯威夫特:倾听;结构变量"-改变事件?,ios,swift,struct,instance,Ios,Swift,Struct,Instance,我有个小问题: 如何监听另一个(“不可编辑”!!”)类中声明的结构实例变量的更改 我添加了一些小代码片段,以澄清我的想法 说明: let fixedClass: FixedClass = FixedClass() class FixedClass { struct MyObject { var abc = 0 } var instance = MyObject() public init() { Timer.scheduledTimer(time

我有个小问题:

如何监听另一个(“不可编辑”!!”)类中声明的
结构实例变量的更改


我添加了一些小代码片段,以澄清我的想法

说明

let fixedClass: FixedClass = FixedClass()
class FixedClass {
    struct MyObject {
        var abc = 0
    }
    var instance = MyObject()
    public init() { Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.updateVar), userInfo: nil,  repeats: true) }

    @objc func updateVar() {
        instance.abc+=1
    }
    func getVar() -> Int {
        return instance.abc
    }
}


let editableClass: EditableClass = EditableClass()
class EditableClass {
    public init() { }
    func listenForChange() {
        // listen for change event of FixedClass.getVar()
        print("Variable: \(fixedClass.getVar())")
    }
}
  • FixedClass
    是一个不可编辑的类:我不想更改“
    FixedClass
    ”的任何代码

  • EditableClass
    可以编辑-我相信您会看到代码(^ ^)/


代码

let fixedClass: FixedClass = FixedClass()
class FixedClass {
    struct MyObject {
        var abc = 0
    }
    var instance = MyObject()
    public init() { Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.updateVar), userInfo: nil,  repeats: true) }

    @objc func updateVar() {
        instance.abc+=1
    }
    func getVar() -> Int {
        return instance.abc
    }
}


let editableClass: EditableClass = EditableClass()
class EditableClass {
    public init() { }
    func listenForChange() {
        // listen for change event of FixedClass.getVar()
        print("Variable: \(fixedClass.getVar())")
    }
}

调用时使用:
editableClass.listenForChange()


总之,我想听听
FixedClass.getVar()
结果的变化-最好避免使用
循环
计时器
。然而,最重要的是至少让它工作起来


非常感谢您的帮助,谢谢

一种方法是使用NotificationCenter广播更改,并让您的
EditableClass
收听该更改并对其作出反应。您的实现可能如下所示:

class FixedClass { //Class names should start with capital letters
  struct MyObject { //Struct names should also start with capital letters
    var abc = 0
  }
  var instance = myObject()
  public init() { Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.updateVar), userInfo: nil,  repeats: true) }

  @objc func updateVar() {
    instance.abc+=1
    //Broadcast the change, and pass this FixedClass instance
    NotificationCenter.default.post(name: Notification.Name("fixedClassChanged"), object: self)
  }
  func getVar() -> Int {
    return instance.abc
  }
}
var newFixedClass: NewFixedClass = NewFixedClass()
var editableClass: EditableClass = EditableClass()

protocol NewFixedClassProtocol: class {
    func changed(newFixedClass: NewFixedClass)
}

class NewFixedClass: FixedClass {
    public weak var delegate: NewFixedClassProtocol?

    override var instance: FixedClass.MyObject {
        didSet {
            self.delegate?.changed(newFixedClass: self)
        }
    }
}

class EditableClass: NewFixedClassProtocol {
    public init() {
        newFixedClass.delegate = self
    }

    func changed(newFixedClass: NewFixedClass) {
        print ("Value = \(newFixedClass.instance.abc)")
    }
}
然后您可以在
EditableClass
中对该广播做出如下反应:

class EditableClass {
  public init() { }
  func listenForChange() {
    //Observe same notification being broadcast by the other class
    NotificationCenter.default.addObserver(self, selector: #selector(processChange(_:)), name: Notification.Name("fixedClassChanged"), object: nil)
  }

  @objc func processChange(_ sender: Notification) {
    //When the notification comes in, check to see if the object passed in was a FixedClass, and if so process whatever needs to be processed
    if let fixed = sender.object as? FixedClass {
        print("Class changed to \(fixed.getVar())")
    }
  }
}

这将完全取决于“真正的”FixedClass是如何定义的。也就是说,它是否是NSObject的子类,是否是ObjectVec类,您想要观察的属性是如何定义的

就您的实际示例而言,您可以通过如下子类化来实现:

class FixedClass { //Class names should start with capital letters
  struct MyObject { //Struct names should also start with capital letters
    var abc = 0
  }
  var instance = myObject()
  public init() { Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.updateVar), userInfo: nil,  repeats: true) }

  @objc func updateVar() {
    instance.abc+=1
    //Broadcast the change, and pass this FixedClass instance
    NotificationCenter.default.post(name: Notification.Name("fixedClassChanged"), object: self)
  }
  func getVar() -> Int {
    return instance.abc
  }
}
var newFixedClass: NewFixedClass = NewFixedClass()
var editableClass: EditableClass = EditableClass()

protocol NewFixedClassProtocol: class {
    func changed(newFixedClass: NewFixedClass)
}

class NewFixedClass: FixedClass {
    public weak var delegate: NewFixedClassProtocol?

    override var instance: FixedClass.MyObject {
        didSet {
            self.delegate?.changed(newFixedClass: self)
        }
    }
}

class EditableClass: NewFixedClassProtocol {
    public init() {
        newFixedClass.delegate = self
    }

    func changed(newFixedClass: NewFixedClass) {
        print ("Value = \(newFixedClass.instance.abc)")
    }
}
因此,您基本上创建了一个进行观察的类支持的协议,创建了FixedClass的一个子类,该子类有一个协议类型的委托,并使用didSet观察者覆盖您想要观察的FixedClass的属性,然后该观察者调用委托方法。在某些时候,您必须将类指定为子类的委托(我在init方法中作为测试进行了此操作)

这样我就可以观察结构的变化,但我还没有接触FixedClass

但是请注意,此方法在很大程度上依赖于了解原始FixedClass,因此可能不适用于“真实世界”的情况

(顺便说一句,我无法让它处理全局定义的类实例,必须将它们放在我的初始视图控制器中,但这可能与我的测试方式有关,不会改变所涉及的方法)

有几件事:

  • 如果原始类是Objective-C或以其他方式参与KVO(如Swift
    dynamic
    properties of
    NSObject
    subclass等),则可以观察到更改。但这是一个相当狭窄的用例。但这是一个使一个人的属性被其他物体观察到的一般模式。有关更多信息,请参阅

  • 如果你不能编辑这个类,在某些狭隘的情况下,理论上你可以对它进行子类化,并添加你想要的任何观察系统。显然,这只有在手动实例化
    FixedClass
    时才有效,这取决于
    FixedClass
    的实现方式,但在某些狭窄的情况下,您可以通过子类化实现所需的功能

    你问:

    您能和我们分享一些代码片段吗

    当然,考虑一下你的代码> FixedClass <代码>:

    class FixedClass {
        struct MyObject {
            var abc = 0
        }
        var instance = MyObject()
        public init() { Timer.scheduledTimer(timeInterval: 0.4, target: self, selector: #selector(self.updateVar), userInfo: nil,  repeats: true) }
    
        @objc func updateVar() {
            instance.abc+=1
        }
        func getVar() -> Int {
            return instance.abc
        }
    }
    
    然后可以定义一个子类:

    class FixedClassSubclass: FixedClass {
        static let changeNotification = NSNotification.Name(rawValue: Bundle.main.bundleIdentifier! + ".FixedClassSubclassNotification")
    
        override func updateVar() {
            super.updateVar()
            NotificationCenter.default.post(name: FixedClassSubclass.changeNotification, object: self)
        }
    }
    
    然后你可以做:

    let fixed = FixedClassSubclass()
    

    您可以使用任何您想要的通知过程<代码>通知中心
  • 。KVN。委托协议模式。无论什么这方面的细节将完全取决于
    FixedClass
    的细节,您给了我们一个人为的示例,在许多情况下不太可能扩展


    我必须承认,对于试图与不可编辑类的内部实现细节挂钩的想法,我有一些普遍的疑虑。我们通常致力于松散耦合的对象,这些对象只依赖于已发布的、受支持的接口。这种努力违反了这两个目标。但是我假设你有一些很好的理由去做你想做的事情。

    这修改了
    FixedClass
    ,这是问题所禁止的。@RobNapier你说得对-我道歉。我以为他是说那门课是私人的,但我觉得我读得不够仔细。无论哪种方式,我都不认为不以某种方式修改就可以完成要求的操作。谢谢你的回答,但是你知道。。这与我的问题不太相符。然而。如果我将struct
    MyObject
    作为公共值,会怎么样?所以我可以使用'let thevar=MyObject.abc'从每一个类中获取信息?现在可能吗?据我所知,如果不在FixedClass中添加至少一行内容,您就无法完成此任务,但请检查其他注释。正如您所写的,没有真正实用的答案。如果实际代码的细节不同,可能会有答案,但正如所写的那样,没有好的方法来观察该属性。“如果实际代码的细节不同”的一个例子是
    FixedClass
    是否是
    NSObject
    的子类(以及
    updateVar
    是否是唯一发生变化的
    instance.abc
    )。如果这是真的,那么swizzling
    updateVar
    将使这成为可能(swizzling在生产代码中非常危险,但是如果您有源代码,它会更安全)。听起来没那么糟糕。但是tbh-我不能百分之百地了解你的想法。您能和我们分享一些代码片段吗@RobIs
    FixedClass
    an
    NSObject
    子类?
    updateVar
    是唯一修改该值的东西吗(因此您确实想知道何时调用
    updateVar
    ,而不是何时更改该值)?