Перейти к содержанию
Fire Monkey от А до Я

Евгений Корепов

Пользователи
  • Постов

    738
  • Зарегистрирован

  • Посещение

  • Победитель дней

    100

Сообщения, опубликованные Евгений Корепов

  1. В 24.04.2017 в 11:29, Mars M сказал:

    Загружаю большой список в ListView, время загрузки где то 5-7 секунд.

    Это много, по этому переделал что бы список загружался динамически, как к концу пролистывается, подгружаются новые данные.

    Все бы хорошо, но вот ScrollBar при загрузке новых данных меняет размер и позицию. 

    Это не очень нравиться :)

    Можно как то заранее настроить его размер под конечное число итемов?

    Или может как то по другому сделать.

    Вы можете поступить следующим образом - сразу создать нужное количество итемов и задать им высоту (или среднюю высоту) готово итема. Это будет очень быстро, по крайней мере для нескольких тысяч итемов время менее секунды на среднем телефоне. А потом динамически наполнять их данными. 

    P.S Не забудьте отключить события ListViewUpdatingObjects и ListViewUpdateObjects на время создания итемов.

  2. Попробуйте избавится от ImageList на время тестов, замените на TArray<TBitmap> к примеру. Так же попробуйте после oConnectImage.ImageIndex:=r; делать oConnectImage.Bitmap.SaveToFile('d:\0\'+Автоинкремент+'.jpg'). У меня в подобной ситуации несколько процентов картинок в папке 'd:\0\' были черными, видимо пустые, отказался по этой причине от связки ImageList и ListView.

  3. Вот так сделайте:

    procedure TForm1.LsvObjectsUpdateObjects(const Sender: TObject;
      const AItem: TListViewItem);
    var
      ...
      oConnectImage: TListItemImage;
      r: integer;
    begin
      r:=Random(ImageList1.Count);
    
      oConnectImage:=aItem.Objects.FindDrawable('ConnectImage') as TListItemImage;
      if (oConnectImage<>nil) then
      begin
        oConnectImage.OwnsBitmap:=True;
        oConnectImage.ImageIndex:=r;
      end;
      ...
    end;

    Добавьте строчку oConnectImage.OwnsBitmap:=True. В соседней теме я долго бился над этим.

  4. В 13.04.2017 в 19:06, GASCHE сказал:

    Думаю нет, вы не знаете какой поток к ней обратиться в тот или иной момент времени. В Windows у вас отрабатывает сначала основной поток потом ForceQueue в андроид ForceQueue вклинивается в основной поток.

    Напишите свой, "правильный" код если хотите доказать что TThread.ForceQueue работает в андроиде и я ошибаюсь. К чему этот бесполезный флуд?

  5. 1 минуту назад, GASCHE сказал:

    А может не работает потому что неправильно написано? На мой взгляд MyLog не потокобезопасная процедура, а вы к ней обращаетесь из разных потоков. Из своего опыта я бы даже для Windows так делать не стал бы, один раз прокатит другой нет.

    Все с ней хорошо, ведь там есть

    TThread.Synchronize(Nil,
        procedure
        begin
          Memo.Lines.Add(LMessage);
        end);

    К тому же это упрощенный вариант, в рабочем вместо Memo использовалась отсылка данных на сервер логов. Результат тот же.

  6. TThread.ForceQueue не работает в Android. Но можно утешить себя тем, что отлично работает в Windows ;-)

    Код следующий:

    unit Unit1;
    
    interface
    
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Memo,
      FMX.Controls.Presentation, FMX.ScrollBox;
    
    type
      TForm1 = class(TForm)
        Memo: TMemo;
        procedure FormShow(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        procedure MyLog(AMessage : String);
        procedure TestForceQueue;
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.fmx}
    
    procedure TForm1.TestForceQueue;
    begin
      MyLog('In main thread start');
      TThread.ForceQueue(Nil,
        procedure
        begin
          MyLog('In ForceQueue start');
          TThread.Sleep(2000);
          MyLog('In ForceQueue stop');
        end);
      MyLog('In main thread stop');
    end;
    
    procedure TForm1.FormShow(Sender: TObject);
    begin
      TestForceQueue;
    end;
    
    procedure TForm1.MyLog(AMessage : String);
    Var ATime : String;
        LMessage : String;
    begin
      DateTimeToString(ATime, 'dd.mm.yyyy hh.nn.ss.zzz', Now);
      LMessage:=ATime + ' ' + AMessage;
      TThread.Synchronize(Nil,
        procedure
        begin
          Memo.Lines.Add(LMessage);
        end);
    end;
    
    end.

    В Windows все работает как ожидается:

    Цитата

    13.04.2017 16.08.17.028 In main thread start
    13.04.2017 16.08.17.028 In main thread stop
    13.04.2017 16.08.17.028 In ForceQueue start
    13.04.2017 16.08.19.029 In ForceQueue stop

    В андроиде ситуация следующая:

    Цитата

    13.04.2017 16.06.58.554 In main thread start
    13.04.2017 16.06.58.580 In ForceQueue start
    13.04.2017 16.07.00.586 In ForceQueue stop
    13.04.2017 16.07.00.770 In main thread stop

    Т.е. нифига не работает.

    Тестовый проект прилагаю.

    test094 ForceQueue test.7z

  7. Обнаружил очередной глюк Tokyo - сломали Text в Android. А именно порушили раскраску символов Юникода.

    Воспроизводится просто :

    procedure TFormMain.FormCreate(Sender: TObject);
    Var Text1: TText;
    begin
      Text1:=TText.Create(Self);
      Text1.Text:='|' + Char($2713) + '|';
      Text1.Font.Size:=48;
      Text1.Color:=TAlphaColorRec.Red;
      Text1.Align:=TAlignLayout.Client;
      Text1.TextSettings.HorzAlign:=TTextAlign.Center;
      Text1.TextSettings.VertAlign:=TTextAlign.Center;
      FormMain.AddObject(Text1);
    end;

    На первом скриншоте этот код выполнен в Berlin, все выглядит как задуманно. На втором скриншоте этот же код в Tokyo.

    Screenshot_2017-04-11-16-45-35.png

    Screenshot_2017-04-11-16-48-25.png

  8. 17 часов назад, Kitty сказал:

    Я пытаюсь адаптировать статью этого топика. Т.е в статье присутствует .pas файл с нужным функционалом. Как этот файл будут выглядеть в окончательном виде с THTTPClient?

    Вы про global.pas? Если про него, то как то так :

    unit global;
    
    interface
    
    uses
      System.Classes, {IdHTTP,}System.Net.HTTPClient, SysUtils, FMX.Notification;
    
    ///  <summary>
    ///  Процедура регистрации устройства.
    ///  </summary>
    ///  <param name="DeviceID">
    ///  ID регистрируемого устройства
    ///  </param>
    ///  <param name="DeviceToken">
    ///  Токен регистрируемого устройства
    ///  </param>
    procedure RegisterDevice(DeviceID : string; DeviceToken : string);
    
    ///  <summary>
    ///  Процедура отправки Push сообщения на сервер.
    ///  </summary>
    ///  <param name="MessageText">
    ///  Текст отправляемого сообщения
    ///  </param>
    procedure SendPush(MessageText : string);
    
    ///  <summary>
    ///  Процедура вывода сообщения из приложения.
    ///  </summary>
    ///  <param name="MessageText">
    ///  Текст выводимого сообщения
    ///  </param>
    ///  <param name="BadgeNumber">
    ///  Число выводимое на иконку приложения
    ///  </param>
    procedure ShowNotification(MessageText : string; BadgeNumber : integer);
    
    const
      // Доменное имя сайта
      DOMAIN: string = 'http://example.ru/';
    
    implementation
    
    
    procedure RegisterDevice(DeviceID : string; DeviceToken : string);
    var
      // Подключение для передачи данных
      httpconnect : THTTPClient;
      AQuery : String;
    begin
      try
        // Создаём подключение
        httpconnect := THTTPClient.Create;
        // Указываем данные для отправки
        AQuery:='?action=register-device&did=' + DeviceID + '&token=' + DeviceToken;
        {$ifdef ANDROID}
          AQuery:=AQuery + '&platform=android';
        {$else}
          AQuery:=AQuery + '&platform=ios';
        {$endif}
        // Отправляем запрос
        httpconnect.Get(DOMAIN + 'push.php' + AQuery);
      finally
        // Отключаемся и освобождаем память
        httpconnect.free
      end;
    end;
    
    procedure SendPush(MessageText : string);
    var
      // Подключение для передачи данных
      httpconnect : THTTPClient;
      AQuery : String;
    begin
      try
        // Создаём подключение
        httpconnect := THTTPClient.Create;
        // Указываем данные для отправки
        AQuery:='?action=send-push&text=' + MessageText;
        // Отправляем запрос
        httpconnect.Get(DOMAIN + 'push.php' + AQuery);
      finally
        // Отключаемся и освобождаем память
        httpconnect.Free;
      end;
    end;
    
    procedure ShowNotification(MessageText : string; BadgeNumber : integer);
    var
      NotificationC: TNotificationCenter;
      Notification: TNotification;
    begin
    
      // Создаём центр уведомлений и уведомление для отправки
      NotificationC := TNotificationCenter.Create(nil);
      Notification := NotificationC.CreateNotification;
    
      try
        // Если центр уведомлений поддерживается системой
        if NotificationC.Supported then
        begin
          // Устанавливаем текст сообщения
          Notification.AlertBody := MessageText;
          // Включаем звук при выводе сообщение
          Notification.EnableSound := true;
          // Устанавливаем цифру на иконке приложения
          Notification.Number := BadgeNumber;
          NotificationC.ApplicationIconBadgeNumber := BadgeNumber;
          // Выводим сообщение из приложения
          NotificationC.PresentNotification(Notification);
        end;
      finally
        // Очищаем переменные
        Notification.DisposeOf;
        NotificationC.Free;
        NotificationC.DisposeOf;
      end;
    end;
    
    end.

     

  9. В 28.03.2017 в 18:30, Равиль Зарипов (ZuBy) сказал:

    в статье описано как нужно настраивать проект

    Отличная статья! Но добавлю один нюанс - функция function pushSend($title, $text, $tokens, $server_key) реализована не до конца, дело в том что у FCM есть одно ограничение - отправка не больше 1000 токенов за раз. Сам на это напоролся и не мог понять почему части пользователей рассылки не приходят (рассылка велась по регионам России, общее количество около 100 тысяч).

    Пришлось накидать промежуточную функцию для разбивки на пакеты по 1000 штук:

    function SendGCMMessagesPacket($apiKey, $DevicesTokenArray, $message, $title, $DBLink, $TableName, $MyLog_GCM_file) {
    	if (count($DevicesTokenArray)==0) {
    		MyLog($MyLog_GCM_file, "Token Array is 0, skip sending");
    		return(0);
    	}
    	$Count_Success = 0;
    	$DeviceCountMax = 1000;
    	$DeviceCountIndex = 0; 
    	$DevicesTokenPacketArray = array();
    	$gcpm = new GCMPushMessage($apiKey);
    	while ($DeviceCountIndex<=count($DevicesTokenArray)) {
    		$DevicesTokenPacketArray = array_slice($DevicesTokenArray, $DeviceCountIndex, $DeviceCountMax);
    		MyLog($MyLog_GCM_file, "Packet send: start index $DeviceCountIndex,  count ".count($DevicesTokenPacketArray));
    		$gcpm->setDevices($DevicesTokenPacketArray);
    		$ResponceJSON = $gcpm->send($message, array('title' => $title));
    		$Count_Success = $Count_Success + AnalyzeResponse($DevicesTokenPacketArray, $ResponceJSON, $DBLink, $TableName, $MyLog_GCM_file);
    		MyLog($MyLog_GCM_file, $ResponceJSON);
    		$DeviceCountIndex = $DeviceCountIndex + $DeviceCountMax;			
    	}
    	return($Count_Success);	
    }

    Функция AnalyzeResponse анализирует ответ и помечает в базе не зарегистрированные токены как неактивные

    function AnalyzeResponse($DevicesTokenArray, $ResponceJSON, $DBLink, $TableName, $MyLog_GCM_file) {
    	$Count_Success = 0;
    	$ResponceArray = json_decode($ResponceJSON, true);
    	if (isset($ResponceArray['results'])) {
    		$Index = 0;
    		foreach ($ResponceArray['results'] as $key => $value){ 
    			if (isset($value['error'])) {
    				if (isset($DevicesTokenArray[$Index])) {
    					MyLog($MyLog_GCM_file, $DevicesTokenArray[$Index].' : '.$value['error']);
    					$query = "UPDATE $TableName SET Active = 0 WHERE DeviceToken = '$DevicesTokenArray[$Index]'";
    					$mysql_result = mysqli_query($DBLink, $query);
    				}
    			} else {
    				$Count_Success = $Count_Success + 1;
    			}
    			$Index = $Index + 1;
    		}
    	}
    	return($Count_Success);
    }

     

  10. Не используйте TIdHTTP, с ним будут проблемы. Post тоже не обязательно, вот простой работающий код :

    Var AHTTPClient : THTTPClient;
    	HTTPQuery : String;
    begin
    	HTTPQuery:=APIURL+'?DeviceID='+HDevicePushParams.DeviceID+'&DeviceToken='+HDevicePushParams.DeviceToken;
    	AHTTPClient:=THTTPClient.Create;
    	AHTTPClient.Get(HTTPQuery);
    	AHTTPClient.Free;
    end;
    	

    Вместо AHTTPClient.Get(HTTPQuery), можно использовать асинхронный запрос AHTTPClient.BeginGet(HTTPQuery), тогда приложение не будет записать при недоступности сервера или проблемах с связью.

  11. Блин! У меня нет слов! Проблема решилась многочасовым гугленьем. Самое смешное  - решение нашел на этом форуме в сообщении http://fire-monkey.ru/topic/3014-ne-otobrazhaetsya-tlistitemimage/?do=findComment&comment=18113 , спасибо огромное @DimArt за решение!

    Вся проблема была в недокументированном свойстве OwnsBitmap, достаточно после загрузки изображения в ListItemImage.Bitmap добавить строчку ListItemImage.OwnsBitmap:=True; И все начинает отлично работать под Android.

    Документация ембаркадеро говорит нам о этом свойстве следущее "Embarcadero Technologies does not currently have any additional information." (http://docwiki.embarcadero.com/Libraries/Tokyo/en/FMX.ListView.Types.TListItemImage.OwnsBitmap). Б*%дь, ну как так то? У меня одни маты, два дня просраны вхолостую...

    Итоговый, работоспособный код функции SetupImageObject ниже

      function SetupImageObject(const AName : String; AWidth, AHeight, X , Y : Single;
          AAlign, AVertAlign: TListItemAlign) : TListItemImage;
      Var AImageURL : String;
      begin
        Result:=TListItemImage(AItem.View.FindDrawable(AName));
        if Result=Nil then
        begin
          Result:=TListItemImage.Create(AItem);
          AImageURL:=AItem.Data['ImageURL'].AsString;
          Result.Bitmap:=LoadImageFromURL(AImageURL);
          Result.OwnsBitmap:=True;
        end;
        Result.Name:=AName;
        Result.Width:=AWidth;
        Result.Height:=AHeight;
        Result.PlaceOffset.X:=X;
        Result.PlaceOffset.Y:=Y;
        Result.Align:=AAlign;
        Result.VertAlign:=AVertAlign;
        Result.ScalingMode:=TImageScalingMode.StretchWithAspect;
      end;

     

  12. Господа и товарищи, помогите тупому мне! Столкнулся с странным. Под windows все отлично работает, а под android не могу добиться загрузки картинок. Мозг уже сломал.

    Собрал тестовый проект - в ListView (DynamicAppearance) добавляем 4 ListViewItem, в ListViewUpdatingObjects все создаем и грузим картинки из инета (потоки и прочее убрал для упрощения). Картанка слева, текст (URL) справа, проще некуда. Прилагаю к сообщению архив проекта и код.

    unit Unit1;
    
    interface
    
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
      FMX.ListView.Types, FMX.ListView.Appearances, FMX.ListView.Adapters.Base,
      FMX.ListView, System.Net.HTTPClient, FMX.Objects;
    
    type
      TFormMain = class(TForm)
        ListView: TListView;
        procedure ListViewUpdatingObjects(const Sender: TObject;
          const AItem: TListViewItem; var AHandled: Boolean);
        procedure FormShow(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        ListViewUpdate : Boolean;    
        procedure MyListViewUpdateObjects(const AListView: TListView; const AItem: TListViewItem);
        procedure InitListView(AListView : TListView);
        function LoadImageFromURL(AURL : String) : TBitmap;
      end;
    
    var
      FormMain: TFormMain;
    
    implementation
    
    {$R *.fmx}
    
    procedure TFormMain.FormCreate(Sender: TObject);
    begin
      ListViewUpdate:=False;  
    end;
    
    procedure TFormMain.FormShow(Sender: TObject);
    begin
      InitListView(ListView);
    end;
    
    procedure TFormMain.InitListView(AListView : TListView);
    Var AListViewItem : TListViewItem;
        AImageURL : String;
    begin
      AImageURL:='http://kayfolom.ru/images/test/';
    
      ListViewUpdate:=True;
      AListViewItem:=AListView.Items.Add;
      AListViewItem.Data['ImageURL']:=AImageURL + 'logo.png';
      ListViewUpdate:=False;
      AListViewItem.Adapter.ResetView(AListViewItem);
    
      ListViewUpdate:=True;
      AListViewItem:=AListView.Items.Add;
      AListViewItem.Data['ImageURL']:=AImageURL + '000487806d3a2ab98aeb2c47b810fc8b.jpg';
      ListViewUpdate:=False;
      AListViewItem.Adapter.ResetView(AListViewItem);
    
      ListViewUpdate:=True;
      AListViewItem:=AListView.Items.Add;
      AListViewItem.Data['ImageURL']:=AImageURL + '0012ef6cb42e95268a4cd1d832a2b93a.jpg';
      ListViewUpdate:=False;
      AListViewItem.Adapter.ResetView(AListViewItem);
    
      ListViewUpdate:=True;
      AListViewItem:=AListView.Items.Add;
      AListViewItem.Data['ImageURL']:=AImageURL + '0022454ccb4f81a701cb3a3c89d52d2f.jpg';
      ListViewUpdate:=False;
      AListViewItem.Adapter.ResetView(AListViewItem);
    end;
    
    procedure TFormMain.ListViewUpdatingObjects(const Sender: TObject;
      const AItem: TListViewItem; var AHandled: Boolean);
    begin
      if Not ListViewUpdate then
      begin
        MyListViewUpdateObjects(Sender as TListView, AItem);
        AHandled:=True;
      end;
    end;
    
    procedure TFormMain.MyListViewUpdateObjects(const AListView: TListView; const AItem: TListViewItem);
    Var AName : TListItemText;
        AImage : TListItemImage;
        AvailableWidth, ImageWidth, ImageHeight : single;
      function SetupTextObject(const AName, AText : String; AFontSize : Single; AFontStyles : TFontStyles;
      AWidth, AHeight, X , Y : Single;
          AAlign, AVertAlign: TListItemAlign; ATextAlign, ATextVertAlign: TTextAlign) : TListItemText;
      begin
        Result:=TListItemText(AItem.View.FindDrawable(AName));
        if Result=Nil then
          Result:=TListItemText.Create(AItem);
        Result.Name:=AName;
        Result.Width:=AWidth;
        Result.WordWrap:=True;
        Result.Font.Size:=AFontSize;
        Result.Font.Style:=Result.Font.Style + AFontStyles;
        Result.Trimming:=TTextTrimming.None;
        Result.Text:=AText;
        Result.PlaceOffset.X:=X;
        Result.PlaceOffset.Y:=Y;
        Result.Align:=AAlign;
        Result.VertAlign:=AVertAlign;
        Result.TextAlign:=ATextAlign;
        Result.TextVertAlign:=ATextVertAlign;
        Result.Height:=AHeight;
      end;
      function SetupImageObject(const AName : String; AWidth, AHeight, X , Y : Single;
          AAlign, AVertAlign: TListItemAlign) : TListItemImage;
      Var AImageURL : String;
      begin
        Result:=TListItemImage(AItem.View.FindDrawable(AName));
        if Result=Nil then
        begin
          Result:=TListItemImage.Create(AItem);
          AImageURL:=AItem.Data['ImageURL'].AsString;
          Result.Bitmap:=LoadImageFromURL(AImageURL);
        end;
        Result.Name:=AName;
        Result.Width:=AWidth;
        Result.Height:=AHeight;
        Result.PlaceOffset.X:=X;
        Result.PlaceOffset.Y:=Y;
        Result.Align:=AAlign;
        Result.VertAlign:=AVertAlign;
        Result.ScalingMode:=TImageScalingMode.StretchWithAspect;
      end;
    begin
      AvailableWidth:=AListView.Width - AListView.ItemSpaces.Left - AListView.ItemSpaces.Right;
    
      // Изображение размещаем слева
      ImageWidth:=AvailableWidth / 3;
      ImageHeight:=AvailableWidth / 3;
      AImage:=SetupImageObject('Image', ImageWidth, ImageHeight, 0, 0,
        TListItemAlign.Leading, TListItemAlign.Leading);
    
      // Текст справа
      AName:=SetupTextObject('Name', AItem.Data['ImageURL'].AsString, 14, [],
        AvailableWidth - ImageWidth, ImageHeight,
        ImageWidth, 0,
        TListItemAlign.Leading, TListItemAlign.Leading, TTextAlign.Center, TTextAlign.Center);
    
      AItem.Height:=Round(ImageHeight + AListView.ItemSpaces.Top + AListView.ItemSpaces.Bottom);
    end;
    
    function TFormMain.LoadImageFromURL(AURL : String) : TBitmap;
    Var AHTTPClient : THTTPClient;
        AStream : TMemoryStream;
        HTTPResponse : IHTTPResponse;
    begin
      Result:=Nil;
      AHTTPClient:=THTTPClient.Create;
      AStream:=TMemoryStream.Create;
      try
        HTTPResponse:=AHTTPClient.Get(AURL, AStream);
      finally
        if HTTPResponse.StatusCode=200 then
          Result:=TBitmap.CreateFromStream(AStream);
      end;
    end;
    
    end.

     

    test092 ListView with Image.7z

  13. 23 часа назад, FeLDMARShaL сказал:

    надо будет посмотреть, но сначала придется сделать переход на фсм. если получится обязательно отпишусь

    Вы уже перешли на FCM, просто не знаете об этом. GCM давно уже нет и пуши работают через FCM.

  14. Покажите скриншот из консоли разработчика, вот как у меня, тогда будет проще понять. И файл манифеста из деплоя. Так же обратите внимание - если у вас, в консоли разработчика, в описании приложения, не загружен скриншот для планшетных ПК, то гугль может все планшеты отнести к не поддерживаемым устройствам.

    Снимок.PNG

  15. Вроде это возможно при использовании XMPP Protocol, сам не пробовал. Подробнее тут https://firebase.google.com/docs/cloud-messaging/xmpp-server-ref

    Если получится разобраться, поделитесь решением с сообществом.

    P.S. Вот есть хорошая штука для этого https://github.com/sourc7/FCMStream

    Цитата

    FCMStream

    FCMStream является сервер приложений для отправки и получения сообщений от Firebase Cloud Messaging (ТСМ) с использованием XMPP протокола.

    Применение

    FCMStream будет течь сервер Firebase Облака сообщений (ТСМ) через протокол XMPP для входящих сообщений и регистрирует функцию обратного вызова для обработки сообщений и подтверждений, когда сообщения прибывают.

    вопросы

    Сервер Firebase Cloud Messaging иногда задерживала вопрос о доставки сообщений на сервер приложений или клиентских приложений, так что сообщения будут получены на конечного пользователя после того, как в среднем 2 минуты.

     

  16. 1 час назад, Antonyan сказал:

       Try
         FDConnection1.Params.Database:=Pchar(Extractfilepath(paramstr(0))+'TEST.FDB');
         FDConnection1.Connected:=true;
       except

          Showmessage('Error');

          Exit;

       end;

          If  FDConnection1.Connected then

               Temp.Open('Select Field1 from TableName')   - вот здесь возникает непостоянная ошибка, о чем и писал выше

          else Showmessage('No Connected');

     

    Благодарю всех откликнувшихся

     

     

     

    А какая у вас версия Firebird? Тут http://tracker.firebirdsql.org/browse/CORE-982 таже проблема, но пишут что она решена "Fixed in both 2.0.1 and HEAD"

  17. Статья странная... Он каким то кодом как то протестировал парсинг. Что именно делалось не понятно. В разных библиотеках парсинг трактуется по разному, это может быть вообще проверка на валидность JSON (подсчет скобочек и двоеточий), а может быть полный разбор содержимого и загрузка в память.

  18. 2 часа назад, Kitty сказал:

    Просьба проголосовать, может эмбакадеро предложит фикс: https://quality.embarcadero.com/plugins/servlet/mobile#issue/RSP-17714

    Спасибо.

    У них для дельфи issue месяцами игнорятся, для билдера наверное вообще никто не смотрит. Но проголосовал.

×
×
  • Создать...