переключить тип приложения с серверное на библиотечное

2147221005(0x800401F3): Недопустимая строка с указанием класса — что делать – Comp-Web-Pro

Как правило, сообщение возникает при фоновом обмене данными между системами или запуске синхронизации вручную. Что делать при появлении этой ошибки и куда смотреть. Причина связана с незарегистрированными в системе компонентами — comcntr.dll, ошибками доступа (недостаточно прав).

Причина

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

Причина связана с незарегистрированными в системе компонентами — comcntr.dll, ошибками доступа (недостаточно прав).

1. Проверьте, что обмен запускается в сеансе учетной записи, имеющей достаточные права на уровне 1С и ОС Windows.

В частном случае, если служба Агента сервера 1С работает под технологической записью, а для обмена требуется доступ к файловой ИБ — добавьте NTFS-разрешения на каталог для этого пользователя (права «Изменение»).

2. Зарегистрируйте в системе компоненту comcntr.dll, выполнив операцию в командной строке от имени администратора:

Для x64-систем может потребоваться запуск с расположения %SystemRoot%SysWOW64, по умолчанию — %SystemRoot%system32

Примеры

Ошибка регистрации comcntr.dll

Указанная ошибка « Модуль comcntr.dll загружен, но не удалось выполнить DllRegisterServer, код ошибки: 0x80070005 » при выполнении команды означает, что недостаточно прав — запустите командную строку от имени администратора и повторите операцию.

Успешная регистрация компоненты

ВАЖНО : в редких случаях требуется сначала выполнить удаление регистрации comcntr.dll с помощью ключа «/u» (DllUnregisterServer), а только потом — повторную регистрацию.

Например, если ранее у вас была установлена другая платформа или некорректно прошла регистрация компоненты из нового релиза.

Последовательно выполняем две команды:

regsvr32 /u “%Program Files%1cv88.3.xx.xxxxbincomcntr.dll”

regsvr32 “%Program Files%1cv88.3.xx.xxxxbincomcntr.dll”

Как создать коннектор с помощью оснастки «Службы компонентов»

1. Открываем «Панель управления — Администрирование — Службы компонентов»

2. В окне консоли переходим к разделу « Службы компонентов — Компьютеры — Приложения COM+ », далее через правую кнопку мыши « Создать — Приложение ».

Приложения COM+ — Создать — Приложение

3. Следуем указаниям Мастера и выбираем «Создать новое приложение».

Создать новое приложение

4. Указываем имя приложения ( V83COMConnector ) и способ активации ( Серверное приложение ).

Вводим имя приложения V83COMConnector

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

По умолчанию — « Текущий (вошедший в систему) пользователь », но для фоновой работы обмена рекомендуется указать отдельную учетную запись («Указанный пользователь») — здесь выбираете сами.

Выбор учетной записи

6. На этапах «Добавление ролей приложения» и «Добавление пользователей для ролей» особой настройки не требуется — нажимаем «Далее — Далее — Готово».

Добавление ролей приложения

7. В созданном приложении открываем «Компоненты» и выбираем команду «Создать — Компонент»

V83COMConnector — Компоненты — Создать — Компонент

8. Следуем Мастеру установки и выбираем пункт « Установка новых компонентов ».

Установка новых компонентов

9. В открывшемся диалоге указываем расположение файла comcntr.dll, нажав на кнопку «Открыть». Потом «Далее» и «Готово».

Установка компонента comcntr.dll

Класс V83COMConnector успешно зарегистрирован и может использоваться для подключения к информационным базам.

Прочие возможные причины (опционально, требуют дополнительной проверки)

Если ошибка появляется снова:

Надеемся, что эти рекомендации помогут вам исправить ошибку «-2147221005(0x800401F3): Недопустимая строка с указанием класса».

⚡ Подписывайтесь на канал или задавайте вопрос на сайте — постараемся помочь всеми техническими силами. Безопасной и производительной работы в 1С.

Суть и причины дисфункции

Данная ошибка относится к регулярно встречающимся ошибкам 1С, и фиксируется у многих пользователей. Единственного и эффективного рецепта её решения не существует, так как она может иметь уникальную основу, и вызывается особенностями программного кода в конкретной системе.

Тем не менее к числу наиболее популярных причин ошибки 2147221005 относятся следующие:

Давайте разберёмся, как исправить ошибку 2147221005 «Недопустимая строка с указанием класса» в вашей системе 1С.

Это интересно: ошибка 2147221164 (0x80040154) при регистрации класса.

StartManager 1.4 – Развитие альтернативного стартера Промо

Стартеры 1С v7.7 v8 Абонемент ($m)

Очередная редакция альтернативного стартера, являющегося продолжением StartManager 1.3. Спасибо всем, кто присылал свои замечания и пожелания, и тем, кто перечислял финансы на поддержку проекта. С учетом накопленного опыта, стартер был достаточно сильно переработан в плане архитектуры. В основном сделан упор на масштабируемость, для способности программы быстро адаптироваться к расширению предъявляемых требований (т.к. довольно часто просят добавить ту или иную хотелку). Было пересмотрено внешнее оформление, переработан существующий и добавлен новый функционал. В общем можно сказать, что стартер эволюционировал, по сравнению с предыдущей редакцией. Однако пока не всё реализовано, что планировалось, поэтому еще есть куда развиваться в плане функциональности.

23.04.2014 140666 1752 Alexoniq 1571

Обновите вашу конфигурацию 1С до актуальной версии

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

переключить тип приложения с серверное на библиотечное. new. переключить тип приложения с серверное на библиотечное фото. переключить тип приложения с серверное на библиотечное-new. картинка переключить тип приложения с серверное на библиотечное. картинка new.Используйте свежую версию 1С

Запускайте 1С с правами админа

Убедитесь, что вы запускаете систему под учётной записью администратора, а не ограниченного в правах «Гостя» или аналога.

Проверьте наличие установленного в системе Excel

Используйте специализированные форумы 1С

Если не один из указанных советов вам не помог, обратитесь к помощи форумов, которые посещают множество программистов и специалистов 1С. В частности, рекомендуем такие форумы как forum.infostart.ru, cyberforum.ru/1c-standard, is.ideasoft.in.ua где вам могут помочь в решении возникшей дисфункции.

Читайте также: 1С нарушение целостности системы – как решить.

Источник

Начинающему сетевому программисту

В общем, посмотрев на всё это, я решил написать базовую статью по созданию простейшего клиент-сервер приложения на С++ под Windows с детальным описанием всех используемых функций. Это приложение будет использовать Win32API и делать незамысловатую вещь, а именно: передавать сообщения от клиента к серверу и обратно, или, иначе говоря – напишем программу по реализации чата для двух пользователей.

Сразу оговорюсь, что статья рассчитана на начинающих программистов, которые только входят в сетевое программирование под Windows. Необходимые навыки – базовое знание С++, а также теоретическая подготовка по теме сетевых сокетов и стека технологии TCP/IP.

Теория сокетов за 30 секунд для «dummies»

Начну всё-таки немного с теории в стиле «for dummies». В любой современной операционной системе, все процессы инкапсулируются, т.е. скрываются друг от друга, и не имеют доступа к ресурсам друг друга. Однако существуют специальные разрешенные способы взаимодействия процессов между собой. Все эти способы взаимодействия процессов можно разделить на 3 группы: (1) сигнальные, (2) канальные и (3) разделяемая память.

Для того, чтобы сокеты заработали под Windows, необходимо при написании программы пройти следующие Этапы:

Инициализация сокетных интерфейсов Win32API.

Инициализация сокета, т.е. создание специальной структуры данных и её инициализация вызовом функции.

«Привязка» созданного сокета к конкретной паре IP-адрес/Порт – с этого момента данный сокет (его имя) будет ассоциироваться с конкретным процессом, который «висит» по указанному адресу и порту.

Для серверной части приложения: запуск процедуры «прослушки» подключений на привязанный сокет.

Для клиентской части приложения: запуск процедуры подключения к серверному сокету (должны знать его IP-адрес/Порт).

Акцепт / Подтверждение подключения (обычно на стороне сервера).

Обмен данными между процессами через установленное сокетное соединение.

Закрытие сокетного соединения.

Итак, попытаемся реализовать последовательность Этапов, указанных выше, для организации простейшего чата между клиентом и сервером. Запускаем Visual Studio, выбираем создание консольного проекта на С++ и поехали.

Этап 0: Подключение всех необходимых библиотек Win32API для работы с сокетами

Сокеты не являются «стандартными» инструментами разработки, поэтому для их активизации необходимо подключить ряд библиотек через заголовочные файлы, а именно:

WinSock2.h – заголовочный файл, содержащий актуальные реализации функций для работы с сокетами.

WS2tcpip.h – заголовочный файл, который содержит различные программные интерфейсы, связанные с работой протокола TCP/IP (переводы различных данных в формат, понимаемый протоколом и т.д.).

Также нам потребуется прилинковать к приложению динамическую библиотеку ядра ОС: ws2_32.dll. Делаем это через директиву компилятору: #pragma comment(lib, “ws2_32.lib”)

Ну и в конце Этапа 0 подключаем стандартные заголовочные файлы iostream и stdio.h

Итого по завершению Этапа 0 в Серверной и Клиентской частях приложения имеем:

Обратите внимание: имя системной библиотеки ws2_32.lib именно такое, как это указано выше. В Сети есть различные варианты написания имени данной библиотеки, что, возможно, связано иным написанием в более ранних версиях ОС Windows. Если вы используете Windows 10, то данная библиотека называется именно ws2_32.lib и находится в стандартной папке ОС: C:/Windows/System32 (проверьте наличие библиотеки у себя, заменив расширение с “lib” на “dll”).

Этап 1: Инициализация сокетных интерфейсов Win32API

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

Нужно определить с какой версией сокетов мы работаем (какую версию понимает наша ОС) и

Запустить программный интерфейс сокетов в Win32API. Ну либо расстроить пользователя тем, что ему не удастся поработать с сокетами до обновления системных библиотек

Итого код Этапа 1 следующий:

Да, кода мало, а описания много. Так обычно и бывает, когда хочешь глубоко в чем-то разобраться. Так что на лабе будешь в первых рядах.

Этап 2: Создание сокета и его инициализация

Тип сокета: обычно задается тип транспортного протокола TCP ( SOCK_STREAM ) или UDP ( SOCK_DGRAM ). Но бывают и так называемые «сырые» сокеты, функционал которых сам программист определяет в процессе использования. Тип обозначается SOCK_RAW

Тип протокола: необязательный параметр, если тип сокета указан как TCP или UDP – можно передать значение 0. Тут более детально останавливаться не будем, т.к. в 95% случаев используются типы сокетов TCP/UDP.

При необходимости подробно почитать про функцию socket() можно здесь.

Код Этапа 2 будет выглядеть так:

Этап 3: Привязка сокета к паре IP-адрес/Порт

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

В ней уже более понятные пользователю поля, а именно:

Технический массив на 8 байт ( sin_zero[8] )

Соответственно, ввод данных для структуры типа sockaddr_in выглядит следующим образом:

Создание структуры типа sockaddr_in : sockaddr_in servInfo;

Заполнение полей созданной структуры servInfo

В случае ошибки функция возвращает значение меньше 0.

Соответственно, если мы хотим привязать сокет к локальному серверу, то наш код по преобразованию IPv4 адреса будет выглядеть так:

erStat = inet_pton(AF_INET, “127.0.0.1”, &ip_to_num);

Результат перевода IP-адреса содержится в структуре ip_to_num. И далее мы передаем уже в нашу переменную типа sockaddr_in значение преобразованного адреса:

Этап 4 (для сервера): «Прослушивание» привязанного порта для идентификации подключений

После вызова данной функции исполнение программы приостанавливается до тех пор, пока не будет соединения с Клиентом, либо пока не будет возвращена ошибка прослушивания порта. Код Этапа 4 для Сервера:

Этап 4 (для Клиента). Организация подключения к серверу

Функция возвращает 0 в случае успешного подключения и код ошибки в ином случае.

Этап 5 (только для Сервера). Подтверждение подключения

Всё, соединение между Клиентом и Сервером установлено! Самое время попробовать передать информацию от Клиента к Серверу и обратно. Как мы в начале и договорились, мы будет реализовывать простейший чат между ними.

Этап 6: Передача данных между Клиентом и Сервером

Рассмотрим прототипы функций recv() и send() :

Флаги в большинстве случаев игнорируются – передается значение 0.

Функции возвращают количество переданных/полученных по факту байт.

Как видно из прототипов, по своей структуре и параметрам эти функции совершенно одинаковые. Что важно знать:

и та, и другая функции не гарантируют целостности отправленной/полученной информации. Это значит, что при реализации прикладных задач по взаимодействию Клиента и Сервера с их использованием требуется принимать дополнительные меры для контроля того, что все посланные байты действительно посланы и, что еще более важно, получены в том же объеме на другой стороне

предельно внимательно надо относиться к параметру «размер буфера». Он должен в точности равняться реальному количеству передаваемых байт. Если он будет отличаться, то есть риск потери части информации или «замусориванию» отправляемой порции данных, что ведет к автоматической поломке данных в процессе отправки/приёма. И совсем замечательно будет, если размер буфера по итогу работы функции равен возвращаемому значению функции – размеру принятых/отправленных байт.

В качестве буфера рекомендую использовать не классические массивы в С-стиле, а стандартный класс С++ типа char, т.к. он показал себя как более надежный и гибкий механизм при передаче данных, в особенности при передаче текстовых строк, где важен терминальный символ и «чистота» передаваемого массива.

Процесс непрерывного перехода от send() к recv() и обратно реализуется через бесконечный цикл, из которого совершается выход по вводу особой комбинации клавиш. Пример блока кода для Серверной части:

Пришло время показать итоговый рабочий код для Сервера и Клиента. Чтобы не загромождать и так большой текст дополнительным кодом, даю ссылки на код на GitHub:

Несколько важных финальных замечаний:

В итоговом коде я не использую проверку на точное получение отосланной информации, т.к. при единичной (не циклической) отсылке небольшого пакета информации накладные расходы на проверку его получения и отправку ответа будут выше, чем выгоды от такой проверки. Иными словами – такие пакеты теряются редко, а проверять их целостность и факт доставки очень долго.

При тестировании примера также видно, что чат рабочий, но очень уж несовершенный. Наиболее проблемное место – невозможность отправить сообщение пока другая сторона не ответила на твоё предыдущее сообщение. Суть проблемы в том, что после отсылки сообщения сторона-отправитель вызывает функцию recv(), которая, как я писал выше, блокирует исполнение последующего кода, в том числе блокирует вызов прерываний для осуществления ввода. Это приводит к тому, что набирать сообщение и что-то отправлять невозможно до тех пор, пока процесс не получит ответ от другой стороны, и вызов функции recv() не будет завершен. Благо введенная информация с клавиатуры не будет потеряна, а, накапливаясь в системном буфере ввода/вывода, будет выведена на экран как только блокировка со стороны recv() будет снята. Таким образом, мы реализовали так называемый прямой полудуплексный канал связи. Сделать его полностью дуплексным в голой сокетной архитектуре достаточно нетривиальная задача, частично решаемая за счет создания нескольких параллельно работающих потоков или нитей (threads) исполнения. Один поток будет принимать информацию, а второй – отправлять.

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

Источник

Архитектура мобильного клиент-серверного приложения

переключить тип приложения с серверное на библиотечное. image loader. переключить тип приложения с серверное на библиотечное фото. переключить тип приложения с серверное на библиотечное-image loader. картинка переключить тип приложения с серверное на библиотечное. картинка image loader.
К добавлению внешнего сервера рано или поздно приходит любой сложный проект. Причины, при этом, бывают совершенно различные. Одни, загружают дополнительные сведения из сети, другие, синхронизируют данные между клиентскими устройствами, третьи- переносят логику выполнения приложения на сторону сервера. Как правило, к последним относятся большинство «деловых» приложений. По мере отхода от парадигмы «песочницы», в которой все действия выполняются только в рамках исходной системы, логика выполнения процессов переплетается, сплетается, завязывается узлами настолько, что становится трудно понять, что является исходной точкой входа в процесс приложения. В этом момент, на первое место выходит уже не функциональные свойства самого приложения, а его архитектура, и, как следствие, возможности к масштабированию.
Заложенный фундамент позволяет либо создать величественный архитектурный ансамбль, либо «накурнож» — избушку на куриных ножках, которая рассыпается от одного толчка «доброго молодца» коих, за время своего существования повидала видимо — невидимо, потому что, глядя на множественные строительные дефекты заказчик склонен менять не исходный проект, а команду строителей.
Планирование — ключ к успеху проекта, но, именно на него выделяется заказчиком минимальный объем времени. Строительные паттерны — туз в рукаве разработчика, который покрывает неблагоприятные комбинации где время — оказывается решающим фактором. Взятые за основу работающие решения позволяют сделать быстрый старт, чтоб перейти к задачам, кажущиеся заказчику наиболее актуальными (как-то покраска дымоходной трубы, на еще не возведенной крыше).
В этой статье я постараюсь изложить принцип построение масштабируемой системы для мобильных устройств, покрывающей 90-95% клиент-серверных приложений, и обеспечивающей максимальное отдаление от сакраментального «накурножа».

Пока занимался доработкой данной статьи, на хабре вышла аналогичная статья (http://habrahabr.ru/company/redmadrobot/blog/246551/). Не со всеми акцентами автора я согласен, но в целом, мое видение не противоречит и не пересекается с материалом изложенным там. Читатель же, сможет определить, какой из подходов более гибкий, и более актуальный.

переключить тип приложения с серверное на библиотечное. image loader. переключить тип приложения с серверное на библиотечное фото. переключить тип приложения с серверное на библиотечное-image loader. картинка переключить тип приложения с серверное на библиотечное. картинка image loader.

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

Следует отметить, что поскольку, некоторые разработчики стремятся избавится от «серверной части» некоторые приложения построены вокруг синхронизации их хранилищ в «облаке». Т. е. фактически, имеют так же, двузвенную систему, но с переносом архитектуры её развертывания на уровень операционной системы. В некоторых случаях такая структура оправдана, но такая система не так легко масштабируется, и её возможности весьма ограничены.

переключить тип приложения с серверное на библиотечное. image loader. переключить тип приложения с серверное на библиотечное фото. переключить тип приложения с серверное на библиотечное-image loader. картинка переключить тип приложения с серверное на библиотечное. картинка image loader.

Общая структура приложения

переключить тип приложения с серверное на библиотечное. image loader. переключить тип приложения с серверное на библиотечное фото. переключить тип приложения с серверное на библиотечное-image loader. картинка переключить тип приложения с серверное на библиотечное. картинка image loader.

Насколько работоспособное данное приложение? Думаю, что ни у кого нет сомнения, что используя Delphi или Visual Studio можно в момент решить эту задачу. Используя Xcode сделать это несколько сложнее, но тоже можно не сильно напрягаясь. Однако, вслед за появлением прототипа, начинают появляться вопросы масштабируемости. Становится очевидным, что для отображения графика необходимо хранить данные за предыдущий период. Не проблема, можно добавить хранилище данных внутрь формы графиков. Однако, данные могут приходить от разных провайдеров и в разных форматах. Кроме того, арифметические операции могут осуществляться с разными валютам, а значит, необходимо обеспечить их выбор. Делать такой выбор на форме графиков — несколько нелогично, хотя и возможно, однако, от таких настроек зависит что именно мы будем отображать на графике. Это означает, что если мы выносим дополнительные параметры в окно настроек, то нам придется как-то их передавать через главную форму в окно графиков. В этом случае логично будет сделать локальную переменную, в которой и хранить передаваемые параметры, и обеспечить доступ из одной форме к другой форме через главную форму. Ну и так далее. Цепочку рассуждений можно строить весьма долго, и сложность взаимодействий будет возрастать.

Конечно, данный подход требует больше усилий по программированию, и соотвественно, изначально предполагает больше времени. Однако, исходя из подзадач ясно, что во-первых, работу над ним легко распараллелить — в то время как один разработчик занят формированием ядра — другой, создает и отлаживает UI. Ядро может благополучно работать в рамках консоли, UI прощелкиваться в девайсе и, ко всему прочему, к обеим частям можно прикрутить независимые юнит-тесты. Другим несомненным достоинством является то, что второй подход значительно более масштабируем. В случае пересмотра функциональности проекта, любые изменения будут вносится многократно быстрее, потому что попросту не существует ограничительных рамок визуальных представлений. Сами визуальные формы (GUI) отображают необходимый минимум основанный на существующих в ядре задачах.

переключить тип приложения с серверное на библиотечное. image loader. переключить тип приложения с серверное на библиотечное фото. переключить тип приложения с серверное на библиотечное-image loader. картинка переключить тип приложения с серверное на библиотечное. картинка image loader.

GitHub содержит множество библиотек, позволяющих использовать REST соединения, для iOS, наиболее востребованной является AFNetworking.

REST опирается на использование GET, POST, PUT, HEAD, PATCH и DELETE запросов. Такой зоопарк называют RESTFul ( habrahabr.ru/post/144011 ) и, как правило, он применяется только тогда, когда пишется универсальный API для работы мобильных приложений, веб-сайтов, десктопов и космических станций в одной связке.
Подавляющее большинство приложений ограничивает систему команд двумя типами, GET и POST, хотя, достаточно только одного — POST.
GET запрос передается в виде строки, которую Вы используете в браузере, а параметры для запроса передаются разделенные знаками ‘&’. POST запрос так же использует «браузерную строку» но, параметры скрывает внутри невидимого тела сообщения. Последние два утверждения повергают в уныние тех, кто с запросами ранее не сталкивался, в действительности же, технология отработана настолько, что она совершенно прозрачна для разработчика, и не приходится вникать в такие нюансы.
Выше, было описано что отправляется серверу. А вот то, что приходит от сервера — куда интересней. Если Вы используете AFNetworking, то со стороны сервера Вы получите Как правило, iOS разработчики называют JSON- оном сериализированный словарь, но это не совсем так. Истинный JSON имеет чуть более сложный формат, но в чистом виде им практически никогда пользоваться не приходится. Однако, о том, что имеется отличие знать нужно — бывают нюансы.
Если Вы работаете с сервисом, установленным на Microsoft Windows Server, то вероятнее всего, там будет использован WCF. Однако, начиная с Windows Framework 4, имеется возможность для клиентов поддерживающих только REST протокол, сделать доступ совершенно прозрачно, декларативным образом. Вы даже сможете не тратить время на получении пояснений об API — документация о системе команд генерируется автоматически IIS (майкрософтовским веб-сервером).

Ниже приводится минимальный код, для реализации Network Layer при помощи AFNetworking 2 на Objective-C.

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

API Layer:
Описывает команды REST и осуществляет выбор хоста. API Layer полностью отделен от знания реализации сетевых протоколов и любых других особенностей функционирования приложения. Технически, он может быть полностью заменен, без каких-либо изменений в остальных частях приложения.

Класс унаследован от ClientBase. Код класса настолько просто, что нет необходимость даже приводить его целиком — он состоит их единообразного описания API:

Как говорится: «Ничего лишнего».

Network Cache Layer:
Данный слой кеширования задействуется для ускорения сетевого обмена между клиентом и сервером на уровне iOS SDK. Выбор ответов осуществляется стороной лежащей за пределами контроля системы, и не гарантирует снижение сетевого трафика, но ускоряет его. Доступа к данным или механизмам реализации нет ни со стороны приложения, ни со стороны системы. При этом используется SQLite хранилище.

Код необходимый для этого слишком прост, чтоб не использовать его в любом проекте, который имеет доступ к сети:

Вызвать нужно из любого места приложения однократно. Например из стартового слоя.

*Время UTC — это время, когда команды была вызвана, а не когда ответ был возвращен серверу. Как правило, они совпадают, но поскольку у приложения может имеется механизм очереди запросов, то теоретически, между вызовом сбойной команды, и регистрацией записи сервером могут проходить месяцы.
Предполагается, что схемы JSON запросов предоставляют серверные разработчики после реализации новых команд API.

Каждая схема, как и каждая команда, обязана удовлетворять определенным оговоренным ранее критериям. В приведенном примере ответ сервера должен содержать два основных и одно опциональное поле.
«status» обязательное. Содержит идентификатор OK или ERROR (или код HTTP типа «200»).
«reason» обязательное Содержит текстовое описание причины ошибки, если она возникла. В противном случае — это поле пустое.
«data» опциональное. Содержит результат выполнения команды. В случае ошибки отсутствует.
Пример схемы:

Благодаря библиотеке разработанной Максимом Луниным сделать это стало очень просто. ( habrahabr.ru/post/180923 )

Код класса валидации приводится ниже

Network Items layer:
Именно на этот слое лежит ответственность за маппинг данных из JSON в десериализированное представление. Данный слой используется для описания классов, осуществляющих объектное или объектно-реляционное преобразование. В сети существует большое количество библиотек, осуществляющих объектно-релационные преобразования. Например JSON Model ( github.com/icanzilb/JSONModel ) или все та же библиотека Максима Лунина. Однако, не все так радужно. От проблем маппинга они не избавляют.

переключить тип приложения с серверное на библиотечное. image loader. переключить тип приложения с серверное на библиотечное фото. переключить тип приложения с серверное на библиотечное-image loader. картинка переключить тип приложения с серверное на библиотечное. картинка image loader.

В классе HttpCache по-мимо методов сохранения результатов запроса имеется еще один, интересный метод:

Он позволяет извлечь из заголовка ответа сервера ключевую информацию о том через сколько секунд истечет время жизни полученного пакета (дата проэкспарится). Используя эту информацию можно записать данные в локальное хранилище, и при повторном аналогичном запросе просто прочесть ранее полученные данные. Если же метод возвращает 0, то такие данные можно не записывать.
Таким образом, на сервере можно регулировать что именно должно быть кешировано на клиенте. Стоит отметить, что используются стандартные поля заголовка. Так что, в плане стандарта велосипед не изобретается.

Путем еще одной небольшой модификации листинга 1 легко решается вопрос с очередями:

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

Проверка подключения к сети осуществляется с помощью классов AFNetworkReachabilityManager или Reachability от Apple ( developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html ) совместно с паттерном наблюдатель. Его устройство слишком примитивно, чтоб описывать в рамках статьи.
Однако, не все запросы должны быть отправлены в очередь. Некоторые из них могут не быть актуальными к моменту появления сети. Решить какие из команд дожны быть записаны в кеш очереди, а каки быть актуальны толко в момент вызова можно как на уровне слоя кеширования, так и на уровне слоя API.

В первом случае, в листинг 9, вместо вызова метода сохранения в очередь, необходимо вставить виртуальный метод, и унаследовать от класса ApiLayer унаследовать классы LocalCacheLayerWithQueue и LocalCacheLayerWithoutQueue. После чего в заданном виртуальном методе класса LocalCacheLayerWithQueue сделать вызов [HttpQueue request: endpoint: method:]

Во втором случае немного изменится вызов запроса из класса ApiLayer

В листинге 9 именно для такого случая предусмотрено условие if(queueAvailable).

Так же, отдельным вопросом является вопрос кеширования изображений. В общем-то, вопрос не сложный, и оттого, имеющий бесконечное количество реализаций. К примеру, библиотека SDWebImage делает это весьма успешно: ( github.com/rs/SDWebImage ).

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

Приведу пример асинхронной загрузки изображения из сети, с коррекцией ошибки MIME (к примеру, Amazon часто отдает неправильный MIME type, в результате чего, их же веб-сервер отправляет изображение, не как двоичный файл с картинкой, а как поток данных).

Метод может казаться весьма избыточным, но легко модифицируемым к конкретным нуждам разработчика. Из важных моментов следует отметить то, что в качестве ключа для кеширования используется хеш URL изображения. Практически невозможно чтоб при таком подходе случилась коллизия в рамках файловой системы устройства.
При каждом чтении файла из кеша, у него модифицируется дата доступа. Файлы которые не перечитываются долгое время можно спокойно удалить еще на старте приложения.

Когда речи идет о чтении файла из бандла приложения, имеется нюанс, который забывают разработчики: iOS SDK предоставляет нам такие методы как [UIImage imageNamed:] и [UIImage imageWithContentsOfFile:]. Использовать первый проще, но он существенно влияет на загруженность памяти — дело в том, что файл загруженный при помощи него, остается в памяти устройства, до тех пор, пока приложение не будет завершено. Если это файл, который имеет большой объем, то это может стать проблемой. Рекомендуется использовать второй метод, как можно чаще. Кроме того, полезно сделать небольшое усовершенствование в метод загрузки:

Теперь Вам не придется задаваться вопросом, в какой резолюции присутствует файл.

Workflows layer:
Все реализованные алгоритмы, которые не относятся к слоям ядра, и не представляют собой GUI должны быть вынесены в классы специфических последовательностей рабочих процессов. Каждый из этих процессов оформляется в своем стиле, и подключается к основной части приложения путем добавления ссылок на экземпляр соответствующего класса в GUI. В подавляющем большинстве случаев, все эти процессы являются не визуальными. Однако имеются некоторые исключения, например, когда необходимо осуществить длинную последовательность предопределенных кадров анимации, с заданными алгоритмами отображения
Вызывающий код должен иметь минимальные знания об этой функциональности. Все настройки flow должны быть инакапсулированы. Google в качестве примера приводит код для уведомления из сервера аналитики, и предлагает включить его в место, где событие возникает.

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

Существуют довольно развитые рабочие процессы, логика функционирования которых зависит от внутренного состояния. Такие процессы должны быть реализованы при помощи паттернов «Стратегия» или «Машина состояний». Как правило, совместно с паттерном «стратегия» используется паттерн «медиатор» который опосредует обращение к тому или иному алгоритму.
Один из часто используемых процессов — процесс авторизации пользователя — очевидный претендент на рефаторинг с использованием паттерна «машины состояний». При этом, именно на этом flow должна лежать ответственность за «автоматическую» авторизацию пользователя, а не рекурсивным образом вызываться из абстрактных слоев (Network Layer, или Validation Items).

Каждый вызов слоев ядра сопровождается передачей объекта обратного вызова (callback), и именно через него должно быть возвращено управление в приложение при успешном выполнении команды или возникновения ошибок. Ни в коем случае не должен допускаться неявный вызов слоев ядра, объектами рабочей последовательности.
Так же, ни в коем случае нельзя допускать, чтоб какие-либо универсальные визуальные контролы зависели бы от состояния рабочих последовательностей. Если это критически необходимо, такие контролы должны быть приватизированы последовательностью. Доступ к состоянию контролов может осуществляться через свойства самих контролов, наследование и переопределение методов, и, в крайнем случае, через реализацию делегатных методов и путем создания категорий. Ключевым в этом витиеватом посыле есть то, что категории — это зло, которого следует избегать. Т. е. я не предлагаю отказываться от категорий, но при прочих равных условиях, код без них легче читается и несомненно более предсказуемый.

Local storage:
Желание разработчиков находится в тренде новых технологий, порой, сталкивается со здравым смыслом, и, последний часто проигрывает. Одно из веяний моды было использование локального хранилища на основе CoreData. Некоторые разработчики настаивали, что его нужно использовать в как можно большем количестве проектов, не смотря на то, что даже сама Apple признавала, что есть определенные трудности.
Существует большое количество способов сохранение временных данных в постоянном хранилище устройства. Использование CoreData оправдано в том случае, когда нам необходимо хранить большое количество редко обновляемых данных. Однако, если в приложении имеется несколько сот записей, и ни постоянно обновляются скопом использование CoreData в этих целях неоправданно дорого. Таким образом, получается, что большую часть времени ресурсов устройство тратит на синхронизацию данных полученных из сети, с теми данными которые уже есть на устройстве, несмотря на то, что весь массив данных, будет обновлён во время следущей сессии.

Использование CoreData ( habrahabr.ru/post/191334 ), кроме того, требует также соблюдение определённых процедур, алгоритмов и архитектурных решений, что ограничивает нас в выборе стратегии разработки, а так же существенно осложняет механизмы отладки нашего приложения.

Как правило использования постоянных хранилищ призвана обеспечить существенное снижение сетевого трафика, за счёт использования уже полученной из сети информации. Однако, в некоторых случаях это не происходит поскольку источником этой информации является сервер, который и принимают решения относительно актуальности данной информации.

Локальное хранилище на основе файловой системы

Средства чтения / записи iOS SDK делает NSDictionary идеальным форматом сохранения относительно небольших короткоживущих данных, поскольку для этого применяются однопроходные алгоритмы.

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

Отрицательной стороной такого подхода считается, что это плохо влияет на производительность устройства, однако, изучение вопроса показывает, что объем таких данных не превышает 5Кбайт, данные загружаются в память мгновенно, единым блоком, и таким же образом освобождаются из памяти, сразу же после того, как в них отпадает необходимость, например, когда ViewController перестает существовать. В то же время чтение данных блоками (построчно) из базы данных SQL порождает большое количество объектов (на уровне выходящем за рамки контроля приложения), которые суммарно превышают указанный объем, к тому же, создают дополнительную нагрузку на процессор. Использование центрального хранилище оправдано тогда, когда данные должны сохраняться долгое время, на протяжении многих сессий работы приложения. При этом, данные из сети загружаются частично.

Локальное хранилище на основе CoreData.

CoreData не предоставляет возможности для использование сериализированных данных. Все данные должны быть подвергнуты объектно-реляционным преобразованиям, до их использования слоем локального хранилища. После получения данных от команды API profile, происходит передача данных в метод категории copyDataFromRemoteJSON, где из словаря извлекаются данные, а затем уже сохраняются в соответствующем управляемом объекте (потомокк класса NSManagedObject).
Вот пример того, как это происходит:

Еще лучшим подходом было бы, если бы callback из API мог бы возвращать валидизированные сериализированные данные, упакованные, к тому же, в управляемый объект.

Преимущества данного подхода:
Гипотетически считается, что ленивая загрузка при помощи NSFetchController позволяет существенно ускорить отображение данных из базы данных, когда их количество составляет несколько тысяч записей. Так же, добавление данных в базу уменьшает количество передаваемой информации по сети. Данные добавляются. Те что есть- показываются пользователю. Пользователь может удалить данные которые ему не нужны. Данные добавляются в те, объекты, которые уже существуют, как элементы их массива.

При использовании библиотеки MagicalRecords возникает ситуация, когда для правильного функционирования приложения табличное представление должно быть частью UITableViewController, иначе становится затруднительным использование NSFetchController лежащий в основе загрузки данных CoreData. Таким образом, существует зависимость в использовании пользовательского интерфейса, от локального хранилища. Т. е. имплементация CoreData ограничивает в разработке UI.

Не смотря на высказанные возражения, использование CoreData может, действительно, потенциально увеличить производительность при возрастании объема данных, в том случае, если воспользоваться следующими альтернативами:

Альтернатива 1
Произвести нормализацию данных API сервера. Сервер должен возвращать не полный иерархический объект, с множеством вложенных сущностей, а множество мелких объектов, которые легко добавляются в базу данных.
В этом случае:
Загружаться будут небольшие порции свежих данных, что уменьши сетевой трафик.
Приложение сможет сделать запрос к серверу с идентификаторами объектов, чтоб сервер вернул список того, что необходимо удалить.
Отпадает необходимость в синхронизации получаемых данных для каждой загружаемой записи.

Заключение:
Статья получилась довольно длинной, и, сомневаюсь, что большинство читателей осилят ее до конца. По этой причине, часть, связанную с GUI я решил отсюда выкинуть. Во-первых, она относилась к построению пользовательского интерфейса через UITabbar, а во-вторых, в одной из скайп групп, состоялась весьма интересная дискуссия относительно использования широко известных паттернов MVC и MVVM. Излагать принципы построения интерфейса не имеет смысл без скурпулезного изложения существущих практик и подходов, которые заводят разработчиков в тупик. Но это тема большой еще одной многостраничной статьи. Здесь же, я постарался рассмотреть лишь вопросы, связанные с функционированием ядра приложения.
Если читатели проявят достаточный интерес к этой тематике, то в ближайшее время постараюсь выложить исходные классы, для использование в качестве шаблона приложения.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *