我试图在Fire Monkey应用程序中的程序源文件中初始化表单属性,它会抛出异常.这是代码:
uses
System.StartUpCopy,
FMX.Forms,
uMainForm in 'Units\uMainForm.pas' {MainForm},
UDataModule in 'Units\UDataModule.pas' {DataMod: TDataModule},
DataHelperClasses in 'Units\DataHelperClasses.pas',
EXDIntf in 'Units\EXDIntf.pas',
Exd in 'Units\Exd.pas';
{$R *.res}
var
ViewModel: TEXDViewModel;
begin
Application.Initialize;
Application.CreateForm(TDataMod, DataMod);
Application.CreateForm(TMainForm, MainForm);
ViewModel := TEXDViewModel.Create;
MainForm.Data := DataMod;
MainForm.ViewModel := ViewModel; //This throws an access violation exception
ViewModel.Data := DataMod;
Application.Run;
end.
Run Code Online (Sandbox Code Playgroud)
在VCL应用程序中执行此操作我没有问题.我如何解决它?
VCL和FMX之间的行为有所不同 - FireMonkey Application.CreateForm方法.虽然在VCL中CreateForm实际上创建了表单,然后调用表单变量完全初始化并准备好使用,但在FMX CreateForm中不创建表单和表单变量仍然是未初始化的nil- 在该调用之后.因为使用表单变量抛出AV.
CreateForm不会立即创建给定的表单.它只是向待处理列表添加了一个请求.RealCreateForms创建真实的表单.
FMX具有Application.RealCreateForms自动调用的方法Application.Run.如果您需要在此之前使用表单变量,则可以自行调用Application.RealCreateForms.在该调用之后,您可以安全地使用添加到列表中的表单变量Application.CreateForm
请记住,Application.RealCreateForms只会进行一次表单创建过程,因此您必须在完成所有调用后调用它,Application.CreateForm否则最终会得到一些单元化表单.
begin
Application.Initialize;
Application.CreateForm(TDataMod, DataMod);
Application.CreateForm(TMainForm, MainForm);
// this forces creation of FireMonkey forms
Application.RealCreateForms;
....
Run Code Online (Sandbox Code Playgroud)
注意:在Windows和OSX平台RealCreateForms上首先调用Application.Run它,因此无论是由您调用还是自动调用它都无关紧要.但是,在Android和iOS平台上,在RealCreateForms调用之前会发生额外的(初始化)逻辑Application.Run,如果您为这些平台开发,则在使用RealCreateForms和注意潜在的副作用时应谨慎行事.移动平台的最佳选择可能是将自定义初始化移动到Form OnCreate事件中.