Search code examples
iosdelphifiremonkeymultiplatform

Firemonkey Windows/iOS compatible code


I am trying to run my app, written in Firemonkey, on iOS. I was read this http://docwiki.embarcadero.com/RADStudio/Seattle/en/Migrating_Delphi_Code_to_Mobile_from_Desktop but i mean that it's not all :-/

I have this procedure

procedure generateData(Var OutVar:String;DataText:String);
var
  S: TBytes;
  StreamInput, StreamOutput: TMemoryStream;
  // String to TBytes
  function UTF8Bytes(const s: UTF8String): TBytes;
  begin
    SetLength(Result, Length(s));
    {$IFDEF IOS} // iOS strings are 0 based but hor about retyped ???
    // this ?
    if Length(Result)>0 then Move(s[0], Result[0], Length(s)-1);
    // or this ?
    //if Length(Result)>0 then Move(s[0], Result[0], Length(s));
    // or this ?
    //if Length(Result)>0 then Move(s[1], Result[0], Length(s));
    {$ELSE} // Win strings are 1 based
    if Length(Result)>0 then Move(s[1], Result[0], Length(s));
    {$ENDIF}
  end;
begin
  StreamInput := TMemoryStream.Create;
  StreamOutput := TMemoryStream.Create;
  S := UTF8Bytes(DataText);

  {$IFDEF IOS} // What about TBytes? They are different too ?
  // this ?
  //StreamInput.Write(S[0], Length(S)-1);
  // or this ?
  StreamInput.Write(S[0], Length(S));
  {$ELSE}
  StreamInput.Write(S[1], Length(S));
  {$ENDIF}

  StreamInput.Position := 0;

  MyCryptoStreamFunction(StreamInput, StreamOutput);
  StreamOutput.Position := 0;

  SetLength(S, StreamOutput.Size);
  {$IFDEF IOS}
  // this ?
  StreamOutput.Read(S[0], StreamOutput.Size);
  // or this ?
  //StreamOutput.Read(S[0], StreamOutput.Size-1);
  // this will raise exception and kill app
  //StreamOutput.Read(S[1], StreamOutput.Size);
  {$ELSE}
  StreamOutput.Read(S[1], StreamOutput.Size);
  {$ENDIF}
  OutVar := StringReplace(EncodeBase64(S,Length(S)), sLineBreak, '',[rfReplaceAll]);
end;

on windows works normally but on ios this code StreamOutput.Read(S[1], StreamOutput.Size); raise exception and kill my app.

Can anyone help what of code variant in {$IFDEF IOS} is equal to code in {ELSE} by their functionality?


Solution

  • Use Low(s) to get the first index of the string for all platforms:

    // utf8 string to TBytes
    function UTF8Bytes(const s: UTF8String): TBytes;
    begin
      SetLength(Result, Length(s));
      if (Length(s) > 0) then
        Move(s[Low(s)],Result[0],Length(s));
    end;
    

    The line S := UTF8Bytes(DataText); implicitly converts the unicode string DataText to an utf8 string before entering the function.

    TBytes is dynamic byte array. All dynamic arrays are zero based.

    StreamInput.Write(S[0],Length(S));
    

    Using System.UTF8Encode is an alternate way to convert a unicode string to an utf8 byte array:

    procedure UTF8Encode(const US: UnicodeString; var B: array of Byte);