2016-11-25 15 views
0

Я пытаюсь запустить свое приложение, написанное в Firemonkey, на iOS. я прочитал это http://docwiki.embarcadero.com/RADStudio/Seattle/en/Migrating_Delphi_Code_to_Mobile_from_Desktop, но я имею в виду, что это не все: -/Firemonkey Windows/iOS совместимый код

У меня есть эта процедура

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; 

на окнах работает нормально, но на КСН этот код StreamOutput.Read(S[1], StreamOutput.Size); рейза исключение и убить мое приложение.

Может ли кто-нибудь помочь в выборе варианта кода в {$ IFDEF IOS} в коде {ELSE} по их функциональности?

+1

Использование 'Low (s)', чтобы получить начальный индекс для всех платформ. «Длина» одинакова для всех платформ (обратите внимание, что символы Unicode имеют размер (Char)). 'TBytes' - динамический массив байтов, всегда индексированный с нуля. –

+0

Зачем вам все это нужно? Не можете ли вы использовать 'TEncoding.UTF8' для чтения и записи строк? –

+0

Используйте низко, как этот 'StreamInput.Write (S [Low (s)], Length (S));'? – Andy

ответ

1

Используйте Low(s), чтобы получить первый индекс строки для всех платформ:

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

Линия S := UTF8Bytes(DataText); неявно преобразует юникод строку DataText в строку utf8 перед входом в функцию.

TBytes - динамический массив байтов. Все динамические массивы основаны на нулевом значении.

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

Использование System.UTF8Encode альтернативный способ, чтобы преобразовать строку Юникода в массив байтов utf8:

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