【问题标题】:How to implement listener pattern in swift如何在swift中实现监听器模式
【发布时间】:2018-03-14 10:28:31
【问题描述】:

我是从 java 搬来的 swift 新手。还有一些设计模式的实现让我很困惑。

例如,我在 java 代码中有 presudo 模式观察者(回调)(下面有示例)。即 UI 将自己的侦听器传递给 Manager 类并侦听回调 isConnected 和 isDisconnected。如果执行回调,UI 类会显示某些消息“isConnected”或“isDisconnected”

    public class UI{
        private Manager mManager;
        void createManager(){
            mManager = new Manager(mManagerLister);
        }
        public void showMessage(String aMsg){
            print(aMsg)
        }
        private final IManagerListener mManagerLister = new IManagerListener{
            void isConnected(){
                this.showMessage("isConnected") 
            }
            void isDisconnected(){
                this.showMessage("isConnected")
            }
        }
    }

    public class Manager{
        interface IManagerListener{
            void isConnected();
            void isDisconnected();
        }
        private final mListener; 
        public Manager(IManagerListener aListener){
            mListener = aListener;
        }
    }

如何正确将此 java 代码移植到 swift 代码?我尝试移植,但错误消息'UI' 类型的值没有成员'showMessage' 显示

  public class UI{
    var manager: Manager?
    var managerListener: IManagerListener?
    func createManager(){
        managerListener = ManagerListenerImp(self)  
        manager = Manager(managerListener)
    }
    public func showMessage(msg: String){
        print(msg)
    }
    class ManagerListenerImp: IManagerListener{
        weak var parent: UI 
        init(parent : UI ){
            self.parent = parent
        }
        func isConnected(){
            parent.showMessage("isConnected") 
            // Value of type 'UI' has no member 'showMessage'
            }
        ..........
    } 
} 

也许存在更优雅的使用回调的方式,而我的方式不正确?

【问题讨论】:

  • 您的代码似乎有问题,parent 应该是可选的,如果它是 weak

标签: ios swift design-patterns


【解决方案1】:

有多种方法可以实现它。

  1. 委托模式(使用只是接口的协议 在 Java 中)
  2. 使用块/闭包
  3. 使用 KVO

因为您使用了下面正在详细说明的委托模式的接口。

如下修改你的代码

声明协议

@objc protocol ManagerListenerImp {
    func isConnected()
}

在 Manager 类中声明一个变量

class Manager {
    weak var delegate : ManagerListenerImp? = nil
}

在你的 UI 类中确认ManagerListenerImp

extension UI : ManagerListenerImp {
    func isConnected () {
        //your isConnected implementation here
    }
}

将 UI 实例(swift 中的 self 和 JAVA 中的 this 传递给管理器类)

func createManager(){
    manager = Manager()
    manager?.delegate = self
}

最后,当你想从Manager类触发isConnected时,只需说

self.delegate?.isConnected()

在你的经理类中

希望对你有帮助

【讨论】:

  • 你的解决方案不适合我。因为在我执行 extension UI: ManagerListenerImp 之后,UI.isConnected 方法可以在项目中的任何代码位置访问,甚至在 UI 类之外。
【解决方案2】:

我对哪个类引用了哪个感到有些困惑,但在下面的示例中应该不难改变。

您可能正在寻找观察者模式。这可以让多个对象监听相同的变化:

1. ManagerStateListener 协议

由任何应对管理器状态变化的类实现的协议

protocol ManagerStateListener: AnyObject {
    func stateChanged(to state: Manager.State)
}

2.经理类

Manager 类包含:

  1. 它的状态
  2. 听众名单
  3. 添加、删除和调用监听器的方法
  4. 实现 ManagerStateListener 协议的示例类

class Manager {
    
    /// The possible states of the Manager
    enum State {
        case one
        case two
        case three
    }
    
    /// The variable that stores the current state of the manager
    private var _currentState: State = .one
    var currentState: State {
        get {
            return _currentState
        }
        set {
            _currentState = newValue
            
            /// Calls the function that will alert all listeners
            /// that the state has changed
            invoke()
        }
    }
    
    /// The list with all listeners
    var listeners: [ManagerStateListener] = []
    
    /// A specific listener that gets initialised here
    let someListener = SomeListener()
    
    init() {
        addListener(someListener) /// Add the listener to the list
    }
    
    /// Method that invokes the stateChanged method on all listeners
    func invoke() {
        for listener in listeners {
            listener.stateChanged(to: currentState)
        }
    }
    
    /// Method for adding a listener to the list of listeners
    func addListener(_ listener: ManagerStateListener) {
        listeners.append(listener)
    }
    
    /// Method for removing a specific listener from the list of listeners
    func removeListener(_ listener: ManagerStateListener) {
        if let index = listeners.firstIndex(where: { $0 === listener }) {
            listeners.remove(at: index)
        }
    }
}

3. SomeListener 类

实现 ManagerStateListener 协议的示例侦听器,由 Manager 类持有

class SomeListener : ManagerStateListener {
    
    func stateChanged(to state: Manager.State) {
        /// Do something based on the newly received state
        switch state {
            case .one:
                print("State changed to one")
            case .two:
                print("State changed to two")
            case .three:
                print("State changed to three")
        }
    }
}

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2011-08-21
    • 2011-02-02
    • 2013-07-08
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 2019-04-01
    • 2012-06-06
    • 2019-12-25
    相关资源
    最近更新 更多