Как решить проблему с обновлением реквизитов и дублированием сообщений в мобильном приложении 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке мобильных приложений на платформе 1С разработчики часто сталкиваются с неочевидным поведением интерфейса, которое кардинально отличается от работы в настольной версии платформы (в тонком или толстом клиентах). В этой статье мы подробно разберем две популярные проблемы: почему платформа "не видит" только что введенный текст в поле ввода, и почему системные сообщения могут выводиться по 5-10 раз одновременно. Проанализируем ситуацию по шагам и выясним причину каждого из багов.

Проблема 1: Мобильная платформа не видит введенный текст до смены фокуса

Рассмотрим классическую ситуацию: на управляемой форме есть строковый реквизит и привязанное к нему поле ввода. Пользователь вводит текст (например, тему письма) и сразу же, не скрывая клавиатуру, нажимает кнопку отправки. В обработчике кнопки написан следующий код:


Если ТекстПисьма = "" Тогда    
    Сообщить("Заполните текст письма!");    
ИначеЕсли ТемаПисьма = "" Тогда    
    Сообщить("Заполните тему письма!");
Иначе 
    // тут делаем отправку письма
КонецЕсли;

При тестировании на компьютере этот код отрабатывает идеально. Однако на мобильном устройстве (Android или iOS) проверка выдает ошибку, сообщая, что реквизит не заполнен, хотя текст визуально находится в поле. Если же перед нажатием кнопки тапнуть в другое поле, текст успешно считывается.

Выясним причину такого поведения. В мобильной платформе 1С передача введенного текста из элемента интерфейса (поля) в сам реквизит формы происходит только в момент потери фокуса. Обычное нажатие на экранную кнопку формы в мобильном интерфейсе не перехватывает фокус у поля ввода. Если пользователь не нажал кнопку Готово (или Enter/Done) на самой виртуальной клавиатуре устройства, фокус остается в поле, и значение не фиксируется в реквизите до начала выполнения программного кода кнопки.

Способы решения проблемы с фокусом в мобильной 1С

Чтобы обойти этот архитектурный нюанс мобильной платформы, разберем несколько проверенных способов решения.

Способ 1: Принудительная программная смена фокуса

Самый надежный метод — заставить платформу принудительно завершить редактирование поля. Для этого в самом начале процедуры, привязанной к нажатию кнопки, мы программно переводим фокус на саму кнопку (или любой другой нейтральный элемент формы). Посмотрим на пример реализации:


&НаКлиенте
Процедура ОтправитьПисьмо(Команда)
    
    // Принудительно забираем фокус у поля ввода
    ЭтаФорма.ТекущийЭлемент = Элементы.КнопкаОтправить;
    
    Если ТекстПисьма = "" Тогда    
        Сообщить("Заполните текст письма!"); 
        Возврат;
    КонецЕсли;
    
    // Дальнейшая логика...
КонецПроцедуры

Благодаря строке с обращением к ТекущийЭлемент, платформа понимает, что ввод в предыдущее поле завершен, и моментально обновляет связанный реквизит.

Способ 2: Изменение свойства обновления текста

Рассмотрим альтернативный вариант решения через свойства самого элемента формы. В палитре свойств поля ввода найдите параметр ОбновлениеТекстаРедактирования и установите его значение в ПриВводе. В этом случае платформа будет пытаться синхронизировать текст с реквизитом по мере набора каждого отдельного символа. Однако стоит учитывать, что на слабых мобильных устройствах или при сложной логике формы это может вызывать подтормаживания интерфейса.

Проблема 2: Хаотичное дублирование системных сообщений

Вторая проблема, с которой сталкиваются мобильные разработчики — это неадекватное поведение функции Сообщить(). Иногда при вызове оповещения платформа выдает сразу по 5-10 абсолютно одинаковых сообщений за раз. Разберем по шагам, откуда берутся эти дубли.

Мобильное приложение 1С по своей внутренней архитектуре является файловой базой данных. В файловых базах существует известный баг работы с памятью и контекстом форм. Если при открытии формы (например, в обработчиках ПриСозданииНаСервере или ПриОткрытии) вы используете конструкцию Отказ = Истина, форма визуально не открывается для пользователя. Однако она не уничтожается из памяти!

Ее контекст остается «висеть» в скрытом кэше приложения. Если пользователь несколько раз попытается открыть такую форму (и каждый раз будет срабатывать отказ), в памяти накопится десяток невидимых копий этой формы. При глобальном вызове обработки оповещения, платформа транслирует команду Сообщить() на каждую из зависших форм, что и приводит к дублированию.

Как правильно закрывать формы и выводить сообщения

Проанализируем методы исправления этой ситуации, чтобы ваше мобильное приложение работало стабильно и не засоряло оперативную память устройства.

  1. Откажитесь от конструкции Отказ = Истина. Вместо этого позвольте форме инициализироваться и открыться, а затем программно закройте её. Вы можете вынести проверки в отдельную логику до открытия формы, либо вызывать метод ЭтаФорма.Закрыть() сразу после открытия, если условия не соблюдены.
  2. Используйте современные асинхронные методы интерфейса. В мобильных клиентах (и в современной разработке на управляемых формах в целом) рекомендуется отказаться от устаревшей функции Сообщить().

Рассмотрим методы, которые следует применять для взаимодействия с пользователем:


&НаКлиенте
Процедура ВывестиУведомление()
    // Вместо Сообщить() используем:
    ПоказатьПредупреждение(Неопределено, "Пожалуйста, заполните все обязательные поля!");
    
    // Или более мягкий вариант:
    ПоказатьОповещениеПользователя("Внимание", , "Данные успешно сохранены.");
КонецПроцедуры

Методы ПоказатьПредупреждение() и ПоказатьОповещениеПользователя() отрабатывают глобально поверх текущего активного окна и не привязываются к накопившимся в фоне скрытым контекстам форм. Это полностью исключает риск дублирования текста на экране устройства и делает интерфейс мобильного приложения гораздо более отзывчивым и профессиональным.

← На главную