Donnerstag, 22. September 2016

FMX - IFDEF oder gibt es etwas besseres.

Warum haben wir IFDEF's in unseren Sourcecode?

Weil wir:
  1. unseren Code mit verschiedenen Delphi Versionen übersetzen wollen und hierfür Änderungen nötig sind.
  2. Funktionalitäten an- und abschalten wollen.
  3. auf die Prozessor Struktur reagieren müssen. (32/64 Bit)
  4. auf unterschiedliche Betriebssystem reagieren müssen...
Das sind doch die wichtigsten Gründe, oder?

Gibe es hier nicht bessere Lösungen?

Na Klar...

Nicht für alle 4 Punkte...

Um es einfach zu sagen: Die RTL macht es vor!

Über die Plattform-Dienste werden die eigentlichen Implementationen je nach Plattform registriert und der Rest linked gegen ein Interface...

Wenn es gut genug ist für dir RTL - sollten wir dieses Designpattern auch in unseren Applications anwenden.

Aber was ist, wenn wir kein IFDEF nehmen können, weil wir zur Laufzeit entscheiden müssen?

Klar nen IF auf eine Variable wird jeder sagen!

Ich mache es so (vereinfacht für das Beispiel! Im eigentlich Code passe ich das Ganze noch an den Text an):


type
  TMyOSPlatform = (Windows, OSX, iOS, Android);
  TOSPlatforms = Set of TMyOSPlatform;
 
 

Procedure InitFMX;
begin
  TGetByID.Default.Register(Windows,
   Function (Const Prop : String) : Single
     begin
       Case TFDKHelper.CaseSelector(Uppercase(Prop),[
        {0} 'WIDTH',
        {1} 'HEIGHT',
        {2} 'MARGINLEFT' ]) of
         0 : Result := 121;
         1 : Result := 22;
         2 : Result := 40;
       end; // of case
     end);

   TGetByID.Default.Register(OSX,
    Function (Const Prop : String) : Single
     begin
       Case TFDKHelper.CaseSelector(Uppercase(Prop),[
        {0} 'WIDTH',
        {1} 'HEIGHT',
        {2} 'MARGINLEFT' ]) of
         0 : Result := 128;
         1 : Result := 24;
         2 : Result := 40;
       end; // of case
     end);

   TGetByID.Default.Register(iOS,
    Function (Const Prop : String) : Single
     begin

       Case TFDKHelper.CaseSelector(Uppercase(Prop),[
        {0} 'WIDTH',
        {1} 'HEIGHT',
        {2} 'MARGINLEFT' ]) of
         0 : Result := 138;
         1 : Result := 24;
         2 : Result := 40;
       end; // of case
     end);

   TGetByID.Default.Register(Android,
    Function (Const Prop : String) : Single    
     begin
       Case TFDKHelper.CaseSelector(Uppercase(Prop),[
        {0} 'WIDTH',
        {1} 'HEIGHT',
        {2} 'MARGINLEFT' ]) of
         0 : Result := 140;
         1 : Result := 28;
         2 : Result := 40;
       end; // of case
    end);
end;

ByPlatform :=
  Function (Prop : String) : Single
   begin
     Result := TGetByID.Default.From(IDAktPlatform,Prop);
   end;

Procedure Whatever;
begin

  Button.Width        := ByPlatform('Width');
  Button.Height       := ByPlatform('Height');  
  Button.Margins.Left := ByPlatform('MarginLeft');
end;



So ist der Zugriff im Code einfacher!