【问题标题】:Modifying an object of another view controller修改另一个视图控制器的对象
【发布时间】:2018-06-18 09:48:32
【问题描述】:

我想知道是否可以更改或修改对象,例如来自AppDelegate.swift 的另一个视图控制器的按钮。 这是我试图开始但不知何故卡住的。

func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable : Any],fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

   if application.applicationState == .active {
        if self.window?.rootViewController is homeViewController {
            //modify a button exist in homeViewController


        }
   }

}

感谢任何帮助。提前致谢。

【问题讨论】:

  • 理论上这是可能的,但它会破坏 MVC 模式 (developer.apple.com/library/content/documentation/General/…)。如果你将 rootViewController 转换为 homeViewController 你可以访问他的属性。
  • 哦,我明白了..问题是我想根据收到的通知更新 homeViewController 中的按钮...那么,除了我有什么之外,还有其他选择吗? @lorenzoliveto
  • 您可以使用答案中已发布的 NotificationCenter。

标签: ios swift uiviewcontroller appdelegate


【解决方案1】:

您可以使用 NotificationCenter 发送和接收内部通知(注意它们不同于本地和远程通知)。

首先创建你的通知做这样的事情:

extension Notification.Name {
    static let remoteNotificationReceived = Notification.Name("uk.co.company.app.remoteNotificationReceived")
}

然后在要响应的视图控制器中执行以下操作:

class TestViewController: UIViewController {
    var remoteNotificationReceivedObserver: NSObjectProtocol?

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        remoteNotificationReceivedObserver = NotificationCenter.default.addObserver(forName: Notification.Name.remoteNotificationReceived, object: nil, queue: nil, using: { (notification) in
            DispatchQueue.main.async { // because the notification won't be received on the main queue and you want to update the UI which must be done on the main queue.
                // Put the code to change the button here
            }
        })
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        if let remoteNotificationReceivedObserver = remoteNotificationReceivedObserver {
            NotificationCenter.default.removeObserver(remoteNotificationReceivedObserver)
        }
    }
}

然后在您应用的其他地方发布这样的通知:

    NotificationCenter.default.post(name: Notification.Name.remoteNotificationReceived, object: nil)

【讨论】:

    【解决方案2】:

    您可以使用NotificationCenter!在您的视图控制器中添加观察者并在您从该视图控制器返回时将其删除(自定义通知)。当你收到通知post它!

    如果您不知道如何处理NotificationCenter,请参考This SO post

    【讨论】:

    • 通知中心是广播。当您需要通知多个实例时,它是合适的。但是当你需要通知单个对象时,这几乎不是一种情况。
    • @MichaelVorontsov : 如果您使用NotificationCenter 通知单个对象,没有任何问题!
    • Apple 说“一种通知调度机制,可以向注册的观察者广播信息”,这并不意味着观察者的数量应该大于一个! @MichaelVorontsov
    • 如果你想打电话给你的朋友,你会用电话还是电台广播?
    • @MichaelVorontsov:呵呵呵呵!这是不同的情况!或者我可以说那个无关紧要的例子!
    【解决方案3】:

    您真正应该与另一个 vew 控制器进行交互的唯一地方是在 segues 期间(如果您使用的是 Storyboard)。即使这样,您也应该让该控制器的视图函数负责更改其按钮的状态,并将一些变量传递给控制器​​,或者最好将控制器设置为侦听通知。然后,您的应用委托或其他控制器可以发布您的家庭控制器监听的通知。

    【讨论】:

      【解决方案4】:

      这是可能的,但直接寻址另一个 ViewController 的成员会破坏责任。为内部交互定义接口协议是一种很好的做法。在这种特殊情况下,创建协议 RemoteNotificationReciverInterface 是一个好主意(或根据一些现代编码风格建议的一种 RemoteNotificationReciveable,尽管我发现在这种情况下很难找到合适的形容词):

      protocol RemoteNotificationReciverInterface: class {
          func didReciveNotification(info : [AnyHashable : Any])
      }
      

      然后扩展您的 ViewController(以及在最顶层时必须对通知做出反应的任何视图控制器)

      extension HomeViewController: RemoteNotificationReciverInterface {
          func didReciveNotification(info : [AnyHashable : Any]) {
              // Chnage you button, ignore para,eters
          }
      }
      

      您可以采用 UINavigationContorollerUITabBarConroller 等将通知转发到其最顶层的控制器,例如:

      extension UINavigationController: RemoteNotificationReciverInterface {
          func didReciveNotification(info : [AnyHashable : Any]) {
              (topViewController as? RemoteNotificationReciverInterface)?.didReciveNotification(info: info)
          }
      }
      

      并且可以轻松地从应用代理转发它。

      func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable : Any],fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
          if application.applicationState == .active {
              (window?.rootViewController as? RemoteNotificationReciverInterface).didReciveNotification(info: userInfo)
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多