AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Immer Ärger mit ARC

Ein Thema von Ookami · begonnen am 24. Okt 2014 · letzter Beitrag vom 30. Okt 2014
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Ookami
Ookami

Registriert seit: 20. Nov 2009
Ort: Baden Württemberg
77 Beiträge
 
Delphi 2009 Architect
 
#1

Immer Ärger mit ARC

  Alt 24. Okt 2014, 18:05
Hallo zusammen,

ich habe in den vergangenen Tagen einen Thread geöffnet und bin in meiner Unwissenheit von einer falschen Idee ausgegangen.
Jetzt will ich's nochmal neu angehen und frage hier mal in die Landschaft, ob sich einer aufopfert, mir an der Stelle zu helfen.

Ich wollte schön sauber getrennt ein Programm entwerfen, erst mal nur als Test, um zu sehen, wie es läuft (nun, es lief nicht) und habe dies nun entschlankt und nochmal probiert.

Die Fehlermeldung ist dieselbe wie immer, ist auch unten als Screenshot angehängt.

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.
Ich gehe jetzt mal davon aus, das Stevie recht hat siehe:
Zitat:
Generell sei aber gesagt, dass viele Fehler bei Code, der unter Windows läuft aber auf Android/iOS nicht, in der unterschiedlichen Handhabung von Objekten zu suchen sind.
Auf den mobilen Geräten wird dort ARC genutzt - also Objekte werden genauso referenzgezählt, wie Interfaces.
ich aber auf der anderen Seite nicht wirklich weiß, wie das dann zu beheben ist.

Ich habe jetzt einfach mal den gesamten Quellcode reingesteckt, dann wird's zwar viel, aber letztlich klar. - Denke ich

Das Programm
Code:
program AppTwo;

uses
  System.StartUpCopy,
  FMX.MobilePreview,
  FMX.Forms,
  Viewer in 'Viewer.pas' {View},
  MBPresenter in 'MBPresenter.pas',
  MBModel in 'MBModel.pas',
  MBInterface in 'MBInterface.pas';

{$R *.res}

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;


begin
     Application.Initialize;
     Main;
end.

Die View
Code:
unit Viewer;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, MBInterface,
  FMX.Objects;

type
  TView = class(TForm, IMyInterfaceView)
    Text1: TText;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    Procedure SetHelloWorld (Value : String);
  end;

var
  View: TView;

implementation

{$R *.fmx}

Procedure TView.SetHelloWorld (Value : String);
Begin
     Text1.Text := Value;
End;

end.

Der Presenter
Code:
unit MBPresenter;

interface

uses    System.SysUtils, MBInterface;

Type    TPresenter                   = Class
           fView                      : IMyInterfaceView;
           fModel                     : IMyInterfaceModel;
          public
           constructor Create(const View: IMyInterfaceView; const Model: IMyInterfaceModel);
         End;

implementation


constructor TPresenter.Create(const View: IMyInterfaceView; const Model: IMyInterfaceModel);
Begin
     if not Assigned( View ) then
       raise System.SysUtils.EArgumentNilException.Create( 'View' );
     if not Assigned( Model ) then
       raise System.SysUtils.EArgumentNilException.Create( 'Model' );

     fView := View;
     fModel := Model;

     fView.SetHelloWorld(fModel.getHelloWorld);
End;

end.

Das Model
Code:
unit MBModel;

interface

uses    MBInterface;

Type    TModel                       = Class(TInterfacedObject, IMyInterfaceModel)
           fHelloWorld                : String;
           public
           constructor create;
           published
           Function getHelloWorld     : String;
         End;


implementation


constructor TModel.create;
begin
     fHelloWorld := 'Hello World';
end;
Function TModel.getHelloWorld : String;
begin
     Result := fHelloWorld;
end;

end.

Das Interface
Code:
unit MBInterface;

interface

Type    IMyInterfaceModel            = Interface(IInterface)
         ['{80AC074A-7D51-49F2-B94D-2716B9CBA938}']
           Function getHelloWorld     : String;
         End;


Type    IMyInterfaceView             = Interface(IInterface)
         ['{D550D27A-57CA-4AAE-809E-60417E7E7DDC}']
           Procedure SetHelloWorld (Value : String);
         End;


implementation

end.
Angehängte Grafiken
Dateityp: png Exception.PNG (8,2 KB, 15x aufgerufen)
Wolfgang
Grüße und Danke
Wolfgang
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Immer Ärger mit ARC

  Alt 24. Okt 2014, 18:28
Du hast kein Problem mit ARC sondern mit dem Lesen der Doku Delphi-Referenz durchsuchenFMX.Forms.TApplication.CreateForm
http://docwiki.embarcadero.com/Libraries/de/FMX.Forms.TApplication.CreateForm

Erstellt zur Laufzeit ein neues FireMonkey-Formular.
Rufen Sie CreateForm auf, um ein FireMonkey-Formular dynamisch zur Laufzeit zu erstellen. Bei den meisten Formularen braucht kein eigener Quelltext geschrieben zu werden, da bei Verwendung des Formular-Designers üblicherweise ein oder mehrere Aufrufe von CreateForm automatisch in die Quelltextdatei des Projekts eingefügt werden.
Zitat von Tipp:
CreateForm erstellt das angegebene Formular nicht sofort. Mit der Methode wird lediglich der ausstehenden Liste eine Anforderung hinzugefügt. RealCreateForms erstellt die tatsächlichen Formulare.

Auf deinen Code angewendet sollte das hier die Lösung sein (klein aber fein)
Delphi-Quellcode:
program AppTwo;

uses
  System.StartUpCopy,
  FMX.MobilePreview,
  FMX.Forms,
  Viewer in 'Viewer.pas{View},
  MBPresenter in 'MBPresenter.pas',
  MBModel in 'MBModel.pas',
  MBInterface in 'MBInterface.pas';

{$R *.res}

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

     Application.RealCreateForms; // <-- da isser der pöse Pursche

     Model := TModel.Create;
     Presenter := TPresenter.Create(View, Model);

     try
        Application.Run;
     finally
        Presenter.Free;

        // ist eigentlich nicht notwendig, das Model-Interface wird am Ende diese Prozedur
        // automatisch freigegeben

        // Model._Release;

        // alternativ wäre noch ein
        // Model := nil;
        // denkbar
     end;
End;


begin
     Application.Initialize;
     Main;
end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (24. Okt 2014 um 18:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Ookami
Ookami

Registriert seit: 20. Nov 2009
Ort: Baden Württemberg
77 Beiträge
 
Delphi 2009 Architect
 
#3

AW: Immer Ärger mit ARC

  Alt 24. Okt 2014, 19:18
Danke dir erst mal,


ich habe das mal ausprobiert. Sagen wir mal so: Es stürzt nicht ab, aber ich fürchte, ich sehe schwarz. Jep, es ist auch nach einer Minute noch schwarz.
Auch dann, wenn ich's auf's Smartphone installiere, ist das Resultat dasselbe.

zumindest ist der pöse Pursche schon mal lokalisiert.

ich habe dann die Form nochmal frisch aufgesetzt, HeaderFooterApplication. Dachte mir, vielleicht ist die leere Anwendung einfach schwarz. Dem ist aber nicht so.
Wolfgang
Grüße und Danke
Wolfgang
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Immer Ärger mit ARC

  Alt 24. Okt 2014, 19:48
Nimm mal das fView.SetHelloWorld aus dem TPresenter.Create dann sollte die Anwendung schon mal fehlerfrei starten
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Ookami
Ookami

Registriert seit: 20. Nov 2009
Ort: Baden Württemberg
77 Beiträge
 
Delphi 2009 Architect
 
#5

AW: Immer Ärger mit ARC

  Alt 24. Okt 2014, 20:07
Hab ich so gemacht, die Anwendung startet, beim Debuggen werden alle Objekte angezeigt.
Auf dem Bildschirm aber tut sich nach wie vor nix. Scharzer Adler auf schwazem Grund.

Gestern hab ich mal was anderes ausprobiert, das läuft zwar, ist aber nicht so gestrickt, wie ich das haben möchte.
Sprich: Was ich hier an der Stelle erreichen möchte, ist, die Trennung in MVP, um das eine, oder andere austauschbar zu machen.
Die Tuts, die ich bislang gefunden habe zeigen zwar was her, erwähnen aber sowas nicht mal ansatzweise.

Und du hast recht, in der Doku habe ich wirklich nicht nachgeschaut. Das liegt aber nicht an einer Lesefaulheit, sondern schlicht daran, dass ich mich auf das falsche konzentriert habe.
Den Befehl kannte ich absolut nicht.
Wolfgang
Grüße und Danke
Wolfgang
  Mit Zitat antworten Zitat
Benutzerbild von Ookami
Ookami

Registriert seit: 20. Nov 2009
Ort: Baden Württemberg
77 Beiträge
 
Delphi 2009 Architect
 
#6

AW: Immer Ärger mit ARC

  Alt 24. Okt 2014, 21:10
Und noch mal an alle,

ich habe das Testprojekt nochmal frisch aufgesetzt. Das Interface ist dasselbe wie oben, wurde aber nicht verwendet.

Code:
program AppThree;

uses
  System.StartUpCopy,
  FMX.MobilePreview,
  FMX.Forms,
  HeaderFooterTemplate in 'HeaderFooterTemplate.pas' {View},
  MBInterface in '..\TryAppTwo\MBInterface.pas';

{$R *.res}

Procedure Main;
Var      View : TView;
Begin
     Application.CreateForm(TView, View);
     Application.RealCreateForms;

     try
        Application.Run;
     finally
     end;
End;


begin
     Application.Initialize;
     Main;
end.
Code:
unit HeaderFooterTemplate;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls,
  MBInterface;

type
  TView = class(TForm)
    Header: TToolBar;
    Footer: TToolBar;
    HeaderLabel: TLabel;
  private
    { Private declarations }
  public
    { Public declarations }
    Procedure SetHelloWorld (Value : String);
  end;

var
  View: TView;

implementation

{$R *.fmx}

Procedure TView.SetHelloWorld (Value : String);
Begin

End;

ohne "Application.RealCreateForms; " geht es, mit, geht es nicht mehr, der Bildschirm bleibt schwarz. Dabei habe ich aber den gesamten Businescode weggelassen.
Zu den Interface-Einbindungen, geschweige den Einbindungen für den Presenter / Model bin ich gar nicht gekommen.

Funktioniert das denn bei Apps für Android so anders?
Rethorisch: Auf was muss ich mich den dann noch bei IOs / MacOSx einlassen?
Wolfgang
Grüße und Danke
Wolfgang
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: Immer Ärger mit ARC

  Alt 24. Okt 2014, 21:12
So ich habe hier mal eine Version, die jetzt auch mit FMX und Windows/Android funktioniert. Grundproblem ist hier die Besonderheit der MainForm (Basis der gesamten Anwendung) und dem Startverhalten bei den Mobile-Plattformen. Dadurch kommt es nur bei der MainForm zum Bruch der ganz strikten Trennung.
Delphi-Quellcode:
unit MVP.Base;

interface

type
  IView = interface
    ['{7B9FA290-778D-4E2F-8112-92ECACBEBB5A}']
  end;

  IModel = interface
    ['{E690A24A-C5D2-47B5-9DBC-45F7695AE167}']
  end;

  IPresenter = interface
    ['{A3BA4F9C-7E67-4D15-BE4A-514FBE85113B}']
  end;

  TModel = class abstract( TInterfacedObject, IModel )
  end;

  TPresenter<TViewType: IView; TModelType: IModel> = class abstract( TInterfacedObject, IPresenter )
  private
    FView: TViewType;
    FModel: TModelType;
  protected
    property View: TViewType read FView;
    property Model: TModelType read FModel;
  public
    constructor Create( AView: TViewType; AModel: TModelType ); virtual;
  end;

implementation

{ TPresenter<TViewType, TModelType> }

constructor TPresenter<TViewType, TModelType>.Create( AView: TViewType; AModel: TModelType );
begin
  inherited Create;
  FView := AView;
  FModel := AModel;
end;

end.
Delphi-Quellcode:
unit Interfaces.Main;

interface

uses
  MVP.Base;

type
  IMainView = interface( IView )
    ['{02D78A1F-3749-4A60-82A0-747E8F2D65FE}']
    procedure setHelloWorld( const Value: string );
  end;

  IMainModel = interface( IModel )
    ['{3F9AC82F-2AF6-485D-BF63-279A9C42B4AA}']
    function getHelloWorld: string;
  end;

  IMainPresenter = interface( IPresenter )
    ['{67D69F7B-539F-4124-B204-90A03973E26D}']
  end;

implementation

end.
Delphi-Quellcode:
unit Presenter.Main;

interface

uses
  MVP.Base, Interfaces.Main;

type
  TMainPresenter = class( TPresenter<IMainView, IMainModel>, IMainPresenter )

  public
    procedure AfterConstruction; override;
  end;

implementation

{ TMainPresenter }

procedure TMainPresenter.AfterConstruction;
begin
  inherited;
  View.setHelloWorld( Model.getHelloWorld );
end;

end.
Delphi-Quellcode:
unit Model.Main;

interface

uses
  MVP.Base,
  Interfaces.Main;

type
  TMainModel = class( TModel, IMainModel )
  public
    function getHelloWorld: string;
  end;

implementation

{ TMainModel }

function TMainModel.getHelloWorld: string;
begin
  Result := 'Hello World!';
end;

end.
Delphi-Quellcode:
unit Form.Main;

interface

uses
  MVP.Base,
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  Interfaces.Main, FMX.Objects;

type
  TMainForm = class( TForm, IView, IMainView )
    Text1: TText;
  private
    FPresenter: IPresenter;
    procedure setHelloWorld( const Value: string );
  public
    procedure AfterConstruction; override;

  end;

var
  MainForm: TMainForm;

implementation

{$R *.fmx}

uses
  Presenter.Main, Model.Main;

{ TMainForm }

procedure TMainForm.AfterConstruction;
begin
  inherited;
  // Hier der Bruch, denn die View erstellt sich selbst den Presenter
  // Das könnte man auch noch auslagern mit einer Automatik, wo
  // der passende Presenter zur View erzeugt wird
  FPresenter := TMainPresenter.Create( Self, TMainModel.Create );
end;

procedure TMainForm.setHelloWorld( const Value: string );
begin
  Text1.Text := Value;
end;

end.
Delphi-Quellcode:
program dp_182444;

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';

{$R *.res}

begin
  ReportMemoryLeaksOnShutdown := True;
  Application.Initialize;
  Application.CreateForm(TMainForm, MainForm);
  Application.Run;

end.
Die Unit MVP.Base ist eigentlich nur Spielerei
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73
Online

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
780 Beiträge
 
#8

AW: Immer Ärger mit ARC

  Alt 25. Okt 2014, 11:48
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
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: Immer Ärger mit ARC

  Alt 25. Okt 2014, 13:23
Durch den Scope ist aber klar welche Variable hier benutzt wird, nämlich die lokale. Die globale wird immer auf nil bleiben und die lokale ist aber auch nach Application.CreateForm (TView, View); auf 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!
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Ookami
Ookami

Registriert seit: 20. Nov 2009
Ort: Baden Württemberg
77 Beiträge
 
Delphi 2009 Architect
 
#10

AW: Immer Ärger mit ARC

  Alt 25. Okt 2014, 16:29
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.
Wolfgang
Grüße und Danke
Wolfgang
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:52 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz