Reputation: 533
I am trying to initialize form properties in the program source file in a Fire Monkey application and it throws an exception. Here is the code:
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.
I have no problem doing this in a VCL app. How do I fix it?
Upvotes: 3
Views: 511
Reputation: 28512
There is difference in behavior between VCL and FMX - FireMonkey Application.CreateForm
method. While in VCL CreateForm
actually creates form and after that call form variable is fully initialized and ready to be used, in FMX CreateForm
does not create form and form variable would still be uninitialized - nil
- after that call. Because of that using form variable throws AV.
CreateForm does not create the given form immediately. It just adds a request to the pending list. RealCreateForms creates the real forms.
FMX has Application.RealCreateForms
method that is automatically called in Application.Run
. If you need to use form variables before that, you can call Application.RealCreateForms
yourself. After that call you can safely use form variables you added to the list with Application.CreateForm
Keep in mind that Application.RealCreateForms
will go through form creation process only once, so you have to call it after you made all calls to Application.CreateForm
or you will end up with some unitialized forms.
begin
Application.Initialize;
Application.CreateForm(TDataMod, DataMod);
Application.CreateForm(TMainForm, MainForm);
// this forces creation of FireMonkey forms
Application.RealCreateForms;
....
Note: On Windows and OSX platforms RealCreateForms
is first thing that is called in Application.Run
, so it does not matter whether it is called by you or automatically. However, on Android and iOS platforms additional (initialization) logic happens before RealCreateForms
is called in Application.Run
, if you develop for those platforms, you should proceed with caution when using RealCreateForms
and watch for potential side-effects. Probably the best option for mobile platforms would be to move your custom initialization into Form OnCreate
event.
Upvotes: 8