Fedor K

Пользователи
  • Публикации

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

  • Посещение

  • Days Won

    13

Fedor K last won the day on 17 ноября

Fedor K had the most liked content!

О Fedor K

  • Звание
    Продвинутый пользователь

Посетители профиля

343 просмотра профиля
  1. Посмотрел ваш пример, все зависания и вылеты с ошибками связаны с обращением к пустым объектам, попыткой обработать все в одном обработчике. Исправить клиент дело не благодарное, поэтому сделал пример по работе с TCP сокетом с возможностью автоподключения (тык). Проверил на нескольких устройствах, полет нормальный. Основные замечания: Не используйте FormActivate событие, тем более на мобильной платформе. Его обработка замораживает приложение. В примере посмотрите вариант обхода. TIniFile нет смысла использовать каждый раз для считывания настроек. 1 раз считали при старте приложения и больше к файлу не обращаемся. Хранить настройки в компонентах (edSettingHost.Text и т.п.). Создание свойства отнимет максимум минуту, а выгоду даст существенную. TCP сокет соединения следуют принимать как асинхронные, а не как запрос-ответ. Это предусматривает получение команды сервером, какое-то выполнение и лишь потом отправка на клиент. Поэтому попробуйте отказаться от использования GetFromServer. Сервер только запускал для проверки клиента, пару раз ловил outofmemory и access violation, закрыться тоже не захотел по-хорошему. Поэтому желательно его тоже довести до ума.
  2. Можете мне сделать тестовый сервер и клиент, чтобы я смог у себя проверить? Тогда мой ответ будет более детальным. А пока: Какой вы объем данных шлете по соединению? Чем вызвана потребность использовать именно сокеты? TimeOut никогда не ставьте большими. Indy работает по принципу блокировки сокета и всего потока в целом. Поэтому большое значение = зависание всего приложения = нежелательные результаты и зависание. Я ставил 100 мс для работы с маленькими пакетами. С такой задержкой доп. поток не обязателен. Если значения более 500 мс - нужно создавать отдельный поток и работать с сокетами в ней + синхронизация при обработке / отправке данных. TIdTCPClient на Andoid любит спать и не проверять входящий буфер. Поэтому вручную нужно вызывать по таймеру проверку типа: procedure T<какое-то имя класа>.Read; var sz : integer; lMsg : string; begin try TMonitor.Enter(Self); try if not Assigned(Client.IOHandler) then Exit; //Client = TIdTCPClient if Client.IOHandler.InputBufferIsEmpty then begin if not Client.IOHandler.CheckForDataOnSource() then exit; end; sz := Client.IOHandler.InputBuffer.Size; if sz <= 0 then exit; lMsg := Client.IOHandler.InputBuffer.ExtractToString(-1, IndyTextEncoding_UTF8); Client.IOHandler.InputBuffer.Clear; <какой-то обработчик входящего сообщения>; except on e : Exception do <какой-то обработчик ошибки>; end; finally TMonitor.Exit(Self); end; end; AntiFreeze - это мягко говоря "костыль" от Indy, использование его плохая практика. На мобильной платформе вряд ли он появится, хотя и реализуется не сложно.
  3. Если я правильно понимаю, это запись значения в справочник. Для работы с этим хранилищем есть такой враппер: https://www.dropbox.com/s/5q17zki83t1ivjq/AppProperties.pas?dl=0 Попробуйте сделать так: TAppProperties.SaveStr(['UserAgent'], ['My User Agent 1.0']);
  4. Не совсем верно. При использовании Indy нужно к проекту подключать библиотеки (libcrypto.so, libssl.so) для Android и (libcrypto.a, libssl.a)iOS. Пример для A есть на форуме. Для iOS такие же телодвижения, библиотеки например здесь. После всего это приложения прекрасно проходят проверки маркетов. Но все это добавляют лишнее телодвижения, размер приложения раздувается. И я бы рекомендовал использовать нативные компоненты, где это возможно.
  5. Objective-C конечно весьма специфический... Попробовал несколько методов, но решение действительно очень простое: 1. Меняем iOSapi.Foundation.pas: unit iOSapi.Foundation; //~3855 строка, добавляем 2 метода NSURLRequestClass = interface(NSObjectClass) ['{A93A4D14-529E-41F0-86EC-B570715512BB}'] {class} function requestWithURL(URL: NSURL): Pointer; cdecl; overload; {class} function requestWithURL(URL: NSURL; cachePolicy: NSURLRequestCachePolicy; timeoutInterval: NSTimeInterval): Pointer; cdecl; overload; //метод раз {class} function allowsAnyHTTPSCertificateForHost(host: NSString): Boolean; cdecl; overload; //метод два {class} procedure setAllowsAnyHTTPSCertificate(allow: Boolean; forHost: NSString); cdecl; overload; end; 2. В своем коде для требуемых сайтов пишем следующее: TNSURLRequest.OCClass.setAllowsAnyHTTPSCertificate(true, StrToNSStr(<требуемый сайт>)); Проверял на сайте expired.badssl.com, XCode 7 + SDK 9.3, Simulator, также на реальном устройстве с iOS 11. п.с. Если нужно доверять абсолютно всем сайтам, думаю можно п. 2 вставить в FMX.WebBrowser.Cocoa.pas в методе: procedure TCommonWebBrowserService.DoNavigate(const URL: string);
  6. Я проверю свою догадку и отпишусь чуть позже. Есть шанс, что все также легко.
  7. Ошибка возникает из-за того, что элемент pipelines является TJSONObject (фигурные скобки «{ }»), а не TJSONArray (квадратные скобки «[ ]»). Как я понял из вашего примера, обращаться к id значению не требуется, т.к. элементы объекта pipelines являются исходными номерами. Для этого можно использовать следующий код: function GetIds(const AIn, APath: string): TArray<Integer>; var jIn, jIds: TJSONObject; jEnum: TJSONPairEnumerator; lCount, i: Integer; begin Result := []; jIn := TJSONObject.ParseJSONValue(AIn) as TJSONObject; if not (Assigned(jIn) and jIn.TryGetValue<TJSONObject>(APath, jIds)) then Exit; lCount := jIds.Count; SetLength(Result, lCount); for i := 0 to lCount - 1 do Result[i] := jIds.Pairs[i].JsonString.GetValue<Integer>('', -1); end; //вызывать так: GetIds(<json string>, 'response.pipelines'); Это легкий формат, посмотрите используемые типы на любом ресурсе (случайная ссылка, еще одна случайная ссылка) и дальше просто смотрите примеры работы. В Delphi лучше использовать сторонние библиотеки для работы с этим форматом, т.к. они выигрывают в производительности и легче в использовании: x-superobject, JsonDataObjects, и др.
  8. Думаю вполне реально. Пример обхода этой проблемы есть ссылка #1 и ссылка #2. Методика следующая: Добавляем в .plist из комментария разрешения. Открываем FMX.WebBrowser.Delegate.iOS и правим TWebViewDelegate.shouldStartLoadWithRequest, запрещая загрузку при получении invalid сертификата. Создаем экземпляр NSURLConnection и выполняем тот же запрос. В методе didReceiveAuthenticationChallenge доверяем сертификату. Выполняем загрузку страницы в webView заново. Is the issue still actual? If yes, please send to me the fmx.jar file (by default path: "C:\Program Files (x86)\Embarcadero\Studio\18.0\lib\android\release"). Thanks.
  9. Таким образом получал access_token лишь из Facebook, остальные приложения не требовались. Пример написан в далеком 2015 году, сейчас возможно нужны небольшие доработки. Насколько я помню, у приложения VK тоже была похожая активность для авторизации, как и у Facebook: FacebookAppName = 'com.facebook.katana'; FacebookActivityName = 'com.facebook.katana.ProxyAuth'; Схема следующая: Сканируем установленное приложение и находим активность для авторизации. Из своего приложения запускаем эту активность и передаем требуемые данные. Получаем ответ от приложения и вытаскиваем access_token. Делаем HTTP запрос к API и получаем требуемую информацию о пользователе.
  10. Небольшое уточнение: они не удаляются только на мобильных платформах, т.к. идет вызов DisposeOf: //смотрим код в unit FMX.Types; procedure TFmxObject.DoDeleteChildren; ... Child := FChildren[I]; FChildren.Delete(I); Child.FParent := nil; Child.SetRoot(nil); Child.DisposeOf; // вот причина ошибки с именем на мобильных платформ, удалене контрола идет не сразу, а при обнулении ссылок ... Для RunTime компонентов лучше в качестве Owner указывать nil и задавать лишь Parent, чтобы уменьшить кол-во ссылок и путаницы.
  11. Как вариант в стиле вынести картинку с текстом в отдельный TLayout и добавить TFloatAnimation с триггером на IsSelected на свойство Opacity :
  12. Из приведенного выше кода ничего вручную удалять не нужно, кроме самого TListBoxItem, как и выполняется в примере выше (listbox1.Items.Delete(indexclick) или Form1.listbox1.Items.Delete(0)) . Все создаваемые дополнительные контролы (TGridPanelLayout, TRectangle, TText) создаются здесь с AOwner = TListBoxItem + задается Parent, который мы и удаляем, а при удалении родительского все дочерние удаляются вместе с ним. Можете убедиться в этом проверив утечку памяти: ReportMemoryLeaksOnShutdown := True; Sashar333 не используйте никогда .Name в качестве хранилища или идентификатора, это плохая практика. Для этих целей отлично подходят тэги (TagString или TagFloat), которые имеют все TFmxObject.
  13. elxanders скиньте пожалуйста пример своего проекта, я посмотрю в чем дело.
  14. Пожалуйста, внимательно посмотрите пример выше: cbbFiles: TComboBox; TComboBox содержит внутри себя TComboListBox с элементами списка, которые у вас автопереводятся. При помощи предоставленного выше примера автоперевод отключается. Если у Вас множество TComboBox, которым нужно запретить перевод, то можно воспользоваться таким способом: //Создаем helper для TComboBox type TComboBoxHelper = class helper for TComboBox public procedure SetAutoTranslate(AEnabled: Boolean = false); end; ... implementation ... { TComboBoxHelper } //Согласно примеру выше procedure TComboBoxHelper.SetAutoTranslate(AEnabled: Boolean); var i, count : integer; begin count := Self.Count - 1; for i := 0 to count do Self.ListBox.ListItems[i].AutoTranslate := AEnabled; end; ... //Пример использования helper в Вашем коде <Ваш TComboBox 1>.SetAutoTranslate; ... <Ваш TComboBox N>.SetAutoTranslate;
  15. Да, любой сертификат.