2016-06-12 48 views
2

我有一個經典的主 - 細節邏輯,並嘗試在Click事件中創建具有InstantiateViewController的詳細UIViewController實例。InstantiateViewController調用ViewDidLoad

這裏是我的代碼,

MasterViewController.cs

detailButton += delegate { 
    UIStoryboard Storyboard = UIStoryboard.FromName ("Main", null); 
    Console.WriteLine("InstantiateViewController() started"); 
    var profileController = Storyboard.InstantiateViewController("ProfileController") as ProfileController; 
    Console.WriteLine("InstantiateViewController() ended"); 
    profileController.Id = 5; 
}; 

ProfileViewController.cs

public partial class ProfileController : UIViewController 
{ 
    public int Id { get; set; } 
    public override void ViewDidLoad() 
    { 
     Console.WriteLine("ViewDidLoad() called"); 
    } 
} 

當我按一下按鈕輸出,

InstantiateViewController() started 
ViewDidLoad() called 
InstantiateViewController() ended 

這意味着profileController.Id設置在ViewDidLoad()之後,這意味着我無法通過Id在ViewDidload事件中加載數據,因爲Id爲null。

所以我的問題是爲什麼ViewDidLoad()由InstantiateViewController()調用,在哪個方法中應該通過Id加載數據?

謝謝。

回答

1

VoewDidLoadcalledViewController被加載到內存中時。

因此,獲取數據的正確位置在ViewDidAppearViewDidAppear通知ViewController其視圖已添加到視圖層次結構中。

UPDATE:

基於你可以做這樣的事情在評論中提供的新信息:

public partial class ProfileController : UIViewController 
{ 
    private int _id; 

    public void SetupProfile (int id) 
    { 
     // Save the Id if necessary. 
     _id = id; 
     // Add event with this id related. 
    } 
    public override void ViewDidLoad() 
    { 
     Console.WriteLine("ViewDidLoad() called"); 
    } 
} 

在選擇,如果你仍然想要做的事件設置在ViewDidAppear,你可以使用這種方法與事件:

yourClass.Event -= MyHandler; 
yourClass.Event += MyHandler; 
+1

或許viewWillAppear更好;可以在視圖在屏幕上之前開始加載。如果它是異步的,那麼操作仍然需要在視圖確實出現之前加載沒有完成的情況 – Paulw11

+0

好的方法,但我也會設置單擊事件處理程序,我知道ViewDidAppear會在每次查看時都會被調用窗口,所以我的點擊事件將在每次通話中再創建一次。那這個呢? – ocanal

+0

在這種情況下,它不是異步的,所以我認爲ViewDidAppear很好。 – jzeferino

1

我會通過自定義segue來做到這一點。

1)創建一個自定義賽格瑞整個應用程序,可以重複使用:

public class CustomSeque : UIStoryboardSegue // or UIStoryboardPopoverSegue depending upon UI design so you can "POP" controller 
{ 
    public CustomSeque(String identifier, UIViewController source, UIViewController destination) : base (identifier, source, destination) { } 

    public override void Perform() 
    { 
     if (Identifier == "StackOverflow") 
     { 
      // Are you using a NavigationController? 
      if (SourceViewController.NavigationController != null) 
       SourceViewController.NavigationController?.PushViewController(DestinationViewController, animated: true); 
      else 
       SourceViewController.ShowViewController(DestinationViewController, this); 
     } else 
      base.Perform(); 
    } 
} 

2)然後,您可以:

UIStoryboard Storyboard = UIStoryboard.FromName("Main", null); 
Console.WriteLine("InstantiateViewController() started"); 
var profileController = Storyboard.InstantiateViewController("ProfileController") as ProfileController; 
var seque = new CustomSeque($"StackOverflow", this, profileController); 
profileController.Id = 5; 
profileController.PrepareForSegue(seque, this); // instead of *this*, you can pass any NSObject that contains data for your controller 
seque.Perform(); 
Console.WriteLine("InstantiateViewController() ended"); 

如果您ProfileController看起來是這樣的:

public partial class ProfileController : UIViewController 
{ 

    public ProfileController (IntPtr handle) : base (handle) 
    { 
     Id = -99; 
    } 

    public int Id { get; set; } 

    public override bool ShouldPerformSegue(string segueIdentifier, NSObject sender) 
    { 
     if (segueIdentifier == "StackOverflow") 
      return true; 
     return base.ShouldPerformSegue(segueIdentifier, sender); 
    } 

    [Export("prepareForSegue:sender:")] 
    public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender) 
    { 
     base.PrepareForSegue(segue, sender); 
     Console.WriteLine("ProfileController.PrepareForSegue()"); 
     Console.WriteLine($" - ID = {Id}"); 
    } 

    public override void ViewDidLoad() 
    { 
     base.ViewDidLoad(); 
     Console.WriteLine("ProfileController.ViewDidLoad()"); 
     Console.WriteLine($" - ID = {Id}"); 
    } 

    public override void ViewWillAppear(bool animated) 
    { 
     base.ViewWillAppear(animated); 
     Console.WriteLine("ProfileController.ViewWillAppear()"); 
     Console.WriteLine($" - ID = {Id}"); 
    } 
} 

您的測序輸出爲:

InstantiateViewController() started 
ProfileController.PrepareForSegue() 
- ID = 5 
ProfileController.ViewDidLoad() 
- ID = 5 
InstantiateViewController() ended 
ProfileController.ViewWillAppear() 
- ID = 5