我有一个经典的主 - 细节逻辑,并试图在点击事件中使用InstantiateViewController创建细节UIViewController的实例。
这是我的代码,
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()
,这意味着我无法在ViewDidload事件中按ID加载数据,因为ID为空。
所以我的问题是为什么ViewDidLoad()
被InstantiateViewController()调用,我应该在哪个方法中加载Id的数据?
感谢。
答案 0 :(得分:1)
VoewDidLoad
加载到内存中时, ViewController
为called。
因此,获取数据的正确位置在ViewDidAppear
。
ViewDidAppear
通知ViewController
其视图已添加到视图层次结构中。
更新:
根据评论中提供的新信息,您可以执行以下操作:
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 :(得分:1)
我会通过自定义segue来做到这一点。
1)创建一个可在整个应用程序中重复使用的自定义segue:
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