我正在尝试在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.
我在VCL应用程序中执行此操作没有任何问题。我该如何解决?
答案 0 :(得分:8)
VCL和FMX之间的行为存在差异 - FireMonkey Application.CreateForm
方法。虽然在VCL中CreateForm
实际上创建了表单,然后调用表单变量已完全初始化并准备好使用,但在FMX中CreateForm
不创建表单和表单变量仍然未初始化 - nil
- 那次电话之后。因为使用表单变量抛出AV。
CreateForm不会立即创建给定的表单。它只是增加了一个 请求待处理列表。 RealCreateForms创建真实的表单。
FMX拥有Application.RealCreateForms
方法,该方法在Application.Run
中自动调用。如果您之前需要使用表单变量,可以自己调用Application.RealCreateForms
。在该调用之后,您可以安全地使用您使用Application.CreateForm
请注意,Application.RealCreateForms
只会经历一次表单创建过程,因此您必须在 所有调用之后将其称为 {{1或者你会得到一些单元化的形式。
Application.CreateForm
注意:在Windows和OSX平台上begin
Application.Initialize;
Application.CreateForm(TDataMod, DataMod);
Application.CreateForm(TMainForm, MainForm);
// this forces creation of FireMonkey forms
Application.RealCreateForms;
....
是在RealCreateForms
中调用的第一件事,因此无论是由您调用还是自动调用都无关紧要。但是,在Android和iOS平台上,在Application.Run
中调用RealCreateForms
之前会发生其他(初始化)逻辑,如果您为这些平台开发,则在使用Application.Run
时应谨慎行事并注意潜在的副作用。移动平台的最佳选择可能是将自定义初始化移动到Form RealCreateForms
事件。