Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   Immer Ärger mit ARC (https://www.delphipraxis.net/182444-immer-aerger-mit-arc.html)

Ookami 24. Okt 2014 21:44

AW: Immer Ärger mit ARC
 
Ok, Sir Rufo,

nochmals Danke für den Vorschlag. Wenn ich die erste Portion verstanden habe, werde ich mich um den zuletzt genannten kümmern.
Jetzt möchte ich dich auch nicht länger belästigen, das war schon toll genug.

Sir Rufo 25. Okt 2014 00:41

AW: Immer Ärger mit ARC
 
Liste der Anhänge anzeigen (Anzahl: 1)
Im Anhang mal das ganze Projekt.

Zu den Änderungen:

Eine zentrale Instanz
Delphi-Quellcode:
TAppStarter
bekommt eine anonyme Factory mitgegeben um den Presenter zu erzeugen.

Aufgerufen wird diese Factory dann bei den Mobile-Plattformen (IOS/ANDROID) über den Delphi-Referenz durchsuchenIFMXApplicationEventService und zwar beim Event Delphi-Referenz durchsuchenTApplicationEvent.FinishedLaunching. Bei allen anderen Plattformen wird zunächst Delphi-Referenz durchsuchenTApplication.RealCreateForms aufgerufen und dann
Delphi-Quellcode:
TAppStarter.CreateMainPresenter
(die ruft dann die Factory auf).
Delphi-Quellcode:
unit App.Starter;

interface

{$INCLUDE 'Conditional.inc'}

uses
  System.SysUtils,
  FMX.Platform;

type
  TAppStarter = class
  private
    FPresenterFactory: TFunc<IInterface>;
    FMainPresenter: IInterface;
    FApplicationEventService: IFMXApplicationEventService;
    procedure GetPlatformServices;
    function ApplicationEventHandler( AAppEvent: TApplicationEvent; AContext: TObject ): Boolean;
{$IFDEF MOBILE}
  private // bei Mobile-Platform verstecken
{$ELSE}
  public // sonst öffentlich aufrufbar
{$ENDIF}
    procedure CreateMainPresenter;
  public
    constructor Create( PresenterFactory: TFunc<IInterface> );

  end;

implementation

{ TAppStarter }

function TAppStarter.ApplicationEventHandler( AAppEvent: TApplicationEvent; AContext: TObject ): Boolean;
begin
  if AAppEvent = TApplicationEvent.FinishedLaunching
  then
    CreateMainPresenter;
  Result := True;
end;

constructor TAppStarter.Create( PresenterFactory: TFunc<IInterface> );
begin
  inherited Create;
  FPresenterFactory := PresenterFactory;
  GetPlatformServices;
end;

procedure TAppStarter.CreateMainPresenter;
begin
  if not Assigned( FMainPresenter )
  then
    FMainPresenter := FPresenterFactory( );
end;

procedure TAppStarter.GetPlatformServices;
begin
  if TPlatformServices.Current.SupportsPlatformService( IFMXApplicationEventService, FApplicationEventService )
  then
    FApplicationEventService.SetApplicationEventHandler( Self.ApplicationEventHandler );
end;

end.
und die Projekt-Datei
Delphi-Quellcode:
program dp_182444;

{$INCLUDE 'Conditional.inc'}

uses
  System.StartUpCopy,
  FMX.Forms,
  Form.Main in 'Form.Main.pas' {MainForm} ,
  Interfaces.Main in 'Interfaces.Main.pas',
  Model.Main in 'Model.Main.pas',
  MVP.Base in 'MVP.Base.pas',
  Presenter.Main in 'Presenter.Main.pas',
  App.Starter in 'App.Starter.pas';

{$R *.res}

procedure Main;
var
  LAppStarter: TAppStarter;
begin
  Application.Initialize;

  LAppStarter := TAppStarter.Create(
      function: IInterface
    var
      LPresenter: IMainPresenter;
    begin
      LPresenter := TMainPresenter.Create( MainForm, TMainModel.Create );
      LPresenter.SetAppStarter( LAppStarter );
      Result := LPresenter;
    end );
  try

    Application.CreateForm( TMainForm, MainForm );
{$IFNDEF MOBILE}
    Application.RealCreateForms;
    LAppStarter.CreateMainPresenter;
{$ENDIF}
    Application.Run;
  finally
    LAppStarter.Free;
  end;
end;

begin
  ReportMemoryLeaksOnShutdown := True;
  Main;

end.

Olli73 25. Okt 2014 11:48

AW: Immer Ärger mit ARC
 
Zitat:

Zitat von Ookami (Beitrag 1277326)
Im AVD lässt sich das als App aufrufen, der Compiler meldet keinen Fehler. Im Debug-Modus zeigt mir das ganze schon im "program"-Teil Main ab "Presenter := TPresenter.Create(View, Model);", dass View= NIL ist.

Code:
program AppTwo;

...

Procedure Main;
Var      Model    : IMyInterfaceModel;
          View     : TView;
          Presenter : TPresenter;
Begin
     Application.CreateForm(TView, View);
     Model := TModel.Create;
     Presenter := TPresenter.Create(View, Model);

     try
        Application.Run;
     finally
        Presenter.Free;
        Model._Release;
     end;
End;

...
Code:
unit Viewer;

...

var
  View: TView;

...
Du hast eine lokale Variable "View" in der Prozedur Main und eine gleichnamige globale in der Unit Viewer. Eine von beiden ist wohl NIL.

Gruß,
Olli

Sir Rufo 25. Okt 2014 13:23

AW: Immer Ärger mit ARC
 
Durch den Scope ist aber klar welche Variable hier benutzt wird, nämlich die lokale. Die globale wird immer auf
Delphi-Quellcode:
nil
bleiben und die lokale ist aber auch nach
Delphi-Quellcode:
Application.CreateForm (TView, View);
auf
Delphi-Quellcode:
nil
. Das steht auch in der Doku so.

Die Vorgehensweise ist prinzipiell schon richtig, da die richtige Variable benutzt wird, allerdings gibt es ein Problem mit dem Timing!

Ookami 25. Okt 2014 16:29

AW: Immer Ärger mit ARC
 
Hallo Sir Rufo,

vielen Dank, ich habe mir dein Beispiel runtergeladen und versuche mich nun da durchzuwursteln. Das Beispiel, das du mir gestern geliefert hast läuft Fehlerfrei.
Auf dem AVD dauert es zwar zw. 10 und 15 Sekunden, auf dem Smartphone geht es deutlich schneller, ca. 3-4 Sec.
Damit bin ich schon mehr als zufrieden. Nochmal vielen Dank dafür.

Und jetzt kommst du sogar nochmal mit einer anderen Lösung. -Wow. auch das muss mal in aller Kürze gesagt werden.
Lass es gut sein, damit werde ich zurechtkommen. Du hast mehr geholfen als ich erwartet hätte.

Btw: ich komme bestimmt mit neuen Fragen wieder.

Sir Rufo 30. Okt 2014 16:01

AW: Immer Ärger mit ARC
 
Da habe ich doch gerade herausgefunden, dass man vom Delphi-Referenz durchsuchenSystem.Messaging.TMessageManager.DefaultManager auch benachrichtigt werden kann, wenn die Form erzeugt wird.

Logischer-(Emba-)weise wird in der versendeten Message nicht die Form-Instanz mitgegeben (nachher kann man noch damit etwas sinnvolles anfangen, das muss sofort unterbunden werden :roll:).

Als
Delphi-Quellcode:
Sender
bekommt man dafür die
Delphi-Quellcode:
Application
-Instanz geliefert. Die ist auch wichtig ... da kommt man immer so schwer dran ... aber im Kontext gesehen ist das richtig, denn
Delphi-Quellcode:
Application
schickt die Nachricht auf die Reise. Na gut.
Delphi-Quellcode:
TMessageManager.DefaultManager.SubscribeToMessage( 
  TFormsCreatedMessage,
  procedure ( const Sender : TObject; const AMessage : TMessage )
  begin
    // hier irgendwas sinnvolles machen
  end );
Ach ja, nicht verwirren lassen, dass die Nachricht
Delphi-Quellcode:
TFormsCreatedMessage
lautet und jeder aufmerksame Leser da eine Nachricht vermutet, die verschickt wird, wenn alle Forms Created sind. Nein, die kommt logischerweise bei jeder Form (die über
Delphi-Quellcode:
TApplication.CreateForm
erzeugt wird).

Irgendwie beschleicht mich das Gefühl, die haben sich da vertan und wollten die Nachricht am Ende der Schleife verschicken (da würde der Message-Name einen Sinn ergeben und auch das Fehlen der Form-Instanz)


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:29 Uhr.
Seite 2 von 2     12   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz