2016-04-25 3 views
3

UIViewControllerのタイトルが変更されたときに通知を受けようとしています。Key-Value UIViewControllerサブクラスでトリガしないことを確認しますか?

私はUIViewControllerサブクラスのタイトルにオブザーバーを追加しようとしましたが、決してトリガーされませんでした。これについて奇妙なのは、それがプレーンなUIViewControllerで動作するということです。私は何か間違っているのですか?

は、ここに私の問題(Xamarin.iOS C#)を説明するコードの例です:UIViewController

using System; 

using UIKit; 
using System.Collections.Generic; 

namespace ObserverTests 
{ 
    public partial class ViewController : UIViewController 
    { 
     List<UIViewController> viewControllers = new List<UIViewController>(); 

     public override void ViewDidLoad() 
     { 
      UIViewController controller1 = new UIViewController() { Title = "Controller1" }; 
      UIViewController controller2 = new Test() { Title = "Controller2" }; 

      this.viewControllers.Add(controller1); 
      this.viewControllers.Add(controller2); 

      foreach(UIViewController viewController in viewControllers) 
      { 
       viewController.AddObserver("title", Foundation.NSKeyValueObservingOptions.New, (changes) => 
        { 
         Console.WriteLine(viewController.Title); 
         Console.WriteLine("Title Changed!"); 
        }); 
      } 

      controller1.Title = "TitleChanged1"; // Works 
      controller2.Title = "TitleChanged2"; // Fails 
     } 

     private class Test : UIViewController 
     { 
     } 
    } 
} 

答えて

2

。このためには、イベントの種類

public delegate void TitleChangedEvent(object sender, TitleChangedEventArgs args); 

public class TitleChangedEventArgs : EventArgs 
{ 
    public string NewTitle { get; set; } 
    public string OldTitle { get; set; } 

    public TitleChangedEventArgs(string newTitle, string oldTitle) 
    { 
     NewTitle = newTitle; 
     OldTitle = oldTitle; 
    } 
} 

あなたは、このイベントをサブスクライブすることができますし、変更の通知を受ける行方不明のUIViewController

public class UIObserveTitleChangedViewController : UIViewController 
{ 
    public event TitleChangedEvent TitleChanged; 
    public override string Title 
    { 
     get 
     { 
      return base.Title; 
     } 

     set 
     { 
      var oldTitle = base.Title; 
      if (oldTitle == value) 
       return; 
      base.Title = value; 
      OnTitleChanged(new TitleChangedEventArgs(value, oldTitle)); 
     } 
    } 

    protected virtual void OnTitleChanged(TitleChangedEventArgs args) 
    { 
     TitleChanged?.Invoke(this, args); 
    } 

    #region ctor 
    public UIObserveTitleChangedViewController() { } 
    public UIObserveTitleChangedViewController(NSCoder coder) : base(coder) { } 
    protected UIObserveTitleChangedViewController(NSObjectFlag t) : base(t) { } 
    protected internal UIObserveTitleChangedViewController(IntPtr handle) : base(handle) { } 
    public UIObserveTitleChangedViewController(string nibName, NSBundle bundle) : base(nibName, bundle) { } 
    #endregion 
} 

から派生し、実装

public partial class ViewController : UIObserveTitleChangedViewController 
{ 
    public ViewController(IntPtr handle) : base(handle) 
    { 
     this.TitleChanged += ViewController_TitleChanged; // Subscribe to TitleChanged 
    } 

    public override void ViewDidLoad() 
    { 
     base.ViewDidLoad(); 
     Title = "Some title";   // triggers TitleChanged 
     Title = "Another new title";  // triggers TitleChanged 
    } 

    private void ViewController_TitleChanged(object sender, TitleChangedEventArgs args) 
    { 
     Debug.WriteLine("Title changed from {0} to {1}", args.OldTitle, args.NewTitle); 
    } 
} 
0

Titleプロパティは、その代替ソリューションとして、あなたはBaseViewControllerクラスを定義し、overrideでき... virtualマークされていますTitleSetterでメソッドを呼び出します。

Public class BaseViewController : UIViewController 
{ 
    .... 

    public override string Title { 
    get { 
     return base.Title; 
    } 
    set { 
      base.Title = value; 
      OnTitleChanged(); 
     } 
    } 

    protected virtual void OnTitleChanged() 
    { 
     ...... 
    } 
} 

次にあなたが任意の上OnTitleChangedを上書きすることができますが変更されたときに、UIViewControllersのコールバックが発生する可能性があります。

0

はあなたのようなので、タイトルを設定することができ、それが動作します:あなたはこれを行うことができます

 controller2.SetValueForKey(new NSString("TitleChangedHAHA"), new NSString("title")); 
0

。最初に、変更されたときに新しいタイトルを保持する新しいイベント引数を定義します。あなたのテストクラスで

public class TitleChangedEventArgs: EventArgs 
{ 
    public string Title { get; private set; } 

    public TitleChangedEventArgs(string title) 
    { 
     Title = title; 
    } 
} 

、TitleChangedのための新しいイベントハンドラを追加したときにビューコントローラの新しいタイトルイベントを発生させるためにタイトルをオーバーライドします。

public class Test : UIViewController 
    { 
     public event EventHandler<TitleChangedEventArgs> TitleChanged; 

     public override string Title { 
      get { 
       return base.Title; 
      } 
      set { 
       base.Title = value; 
       OnTitleChanged(); 
      } 
     } 

     public virtual void OnTitleChanged() 
     { 
      if (TitleChanged != null) { 
       TitleChanged.Invoke(this, EventArgs.Empty); 
      } 
     } 
    } 

そして最後に、あなたがこのような何かを行うことができます自分のメイン・ビュー・コントローラで

:最良の方法は、継承を使用して、このような機能を追加することがありますXamarinで

public class ViewController : UIViewController 
    { 
     private Test _test; 

     public override void ViewDidLoad() 
     { 
      _test = new Test(); 
      base.ViewDidLoad(); 
     } 

     public override void ViewWillAppear(bool animated) 
     { 
      base.ViewWillAppear(animated); 
      _test.TitleChanged += Test_TitleChanged; 
     } 

     public override void ViewDidDisappear(bool animated) 
     { 
      _test.TitleChanged -= Test_TitleChanged; 
      base.ViewDidDisappear(animated); 
     } 

     void Test_TitleChanged(object sender, TitleChangedEventArgs e) 
     { 
      Console.WriteLine("Title Changed! " + e.Title); 
     } 

     public override void ViewWillDisappear(bool animated) 
     { 
      base.ViewWillDisappear(animated); 
     } 
    } 
関連する問題