История одного «разработчика» или как новичку написать приложение для iOS

oebpos7zdtlt8gx_bn3xaeeqct0.png

Итак май 2018 года. Предпринято 7 попыток за 7 лет начать программировать что-то под iOS. И каждый раз одно и тоже: то Objective-C что-то страшное и не понятное, то нету идеи. И дальше Hello World, раз в год, вообщем дело не заходило…

В этот раз новый Xcode и новый для меня язык Swift… И новая идея, хочу пуш уведомления для своего Zabbix сервера т.к. официального приклада нету, да и клиентов на тот момент не было…

До этого пуши присылал телеграмм бот, но он стал барахлить и тут же Роскомнадзор подоспел… Блокировка телеги особой роли не играет, т.к. есть микротик и это сразу было «исправлено».

Решено писать Zabbix уведомлялку, которая потом будет не только для уведомлений.
Как оказалось просто так кидать уведомления не получится. Нужно написать приложение, поставить его, взять из него токен, поднять свой сервер отправки push уведомлений…

Опыт программирования был только на PHP. Swift это другое, но на вид на тот момент выглядел не так пугающе как Objective-C. И сам Xcode хорош как IDE который конвертит код из старого в новый, делает подсказки.

Первым делом обучающие видео, изучение API самого Zabbix. По потом одна статья за другой, как работает NSURLSession, какие фреймворки бывают.

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

Дальше остановлюсь на некоторых моментах с которыми я столкнулся при написании приложения.

Фреймворки


Фреймворки не зашли. Они «клевые», удобные, но чинить потом проект из-за того что что-то поменялось не хочется. А такое уже было. Для себя решил не использовать их, и лучше изобрести свой велосипед чтобы понять как все устроено. Для JSON запросов есть Alamofire, но я использую встроенный NSURLSession т.к. его вполне на все хватает.

Тесты


На тот момент прошло уже больше года, когда я решил добавить тесты :)
Думал что это увлекательная штука спасет мир… Но… Написал несколько разных тестов, потыкал туда сюда… И наступила лень. Не вижу пока задачи в таком не большом проекте выделять столько времени на тесты… И это только время на тесты кода, не говоря о UI тестах.

image

Шифрование


С шифрованием было связано несколько моментов.

Apple по их мануалам хочет чтобы все запросы шифровались. И это правильно. Но как показала практика не все хотели делать https для своего Zabbix. В начале у меня не было включено опции (App Transport Security Settings) разрешающей чистый http трафик, за что в отзывах в AppStore меня хорошо распинали) Потом я его включил не без приключений т.к. Xcode не воспринимал мою строку, пока я просто не пересоздал весь файл Info.plist.

Так же Apple все хочет знать о вашем приложении, обычных https трафик под это не попадает. Но если вы хотите шифровать что-то «по-хитрому», будьте любезны предоставьте отчет в органы USA.

image

При общении с одним из пользователей приложения, был запрос на шифрование PUSH сообщений End-to-End. Сообщение должно быть зашифровано на Zabbix сервере, и расшифровано только на телефоне. Для такой штуки у Apple есть «изменяемые» уведомления. Т.е. если прилетел «mutable-content» то в пришедшем пуше нужно что-то изменить согласно тому что ты напишешь. У меня это было расшифровывание сообщения.

Политика Apple тут не против если использовать стандартные типы шифрования. Хочешь чего то свое, как писал выше, подай бумажку и может покажи ключ? …

Я использовал встроенную либу CommonCrypto, поэтому это считается стандартным типом шифрования. С кодом пришлось поморочится, т.к. большинство примеров либо сильно устарело, либо Xcode кричал что это не безопасно, не чего работать с байтами и данными напрямую, либо начитались приколы с IV OpenSSL-a, то смещение не то, то еще что-то не то и так. В итоге удалось сделать не ругающийся код, и правильно работающий со связкой OpenSSL при шифровании сообщения.

Замыкания


А самая захватывающая для меня тема… Я не мог написать асинхронный код…. Пока хотя бы не много не понял как работают эти замыкания.

image

По умолчанию NSURLSession как раз таки асинхронный и как с ним потом работать не мог понять… Я использовал семафоры (DispatchSemaphore) чтобы сделать код синхронным… Естественно было кучу жалоб от пользователей что зависает и вылетает…

Потом все таки до меня дошло что и как в замыкании работает, какой таймаут в NSURLSession и что к чему. Код был весь заменен на нормальный, добавлены обработчики ошибок. И жить стало лучше, жить стало веселей.

Макет


7tmyfzxt8je0azn4ygnesshmf0g.png

Да, у меня все в одном Storyboard. Знаю что это не очень, но пока экранов мало. Может позже вынесу в xib-ы.

iOS 13 принесла изменения в показ экранов. Раньше все новые экраны показывались как PUSH т.е. на весь экран. Теперь же этот экран можно потянуть вниз и он закроется.

Вообщем возник баг если нажать LogOut и можно просто свернуть обратно форму логина. Это происходит только если собирать последним Xcode 11. Правится элементарно, выставлением опции на view показ только в фулскрин.

Так же в iOS 13 появился SwiftUI, но если сейчас на него переделать приложение то значит забыть о тех кто пользуется приложением на старых девайсах со старыми прошивками…

Выкладка в AppStore


Хоть я и писал приложение для себя, потом все таки решил выложить в AppStore. Тут все просто плати $100 в год и выкладывай. Правда еще проверка приложения, объяснить зачем это приложение т.д.

Т.к. приложение для Zabbix, на логотипе хотел использовать что-то что говорит о Zabbix. Но не тут то было. Написал письмо в Zabbix с просьбой что можно ли очертания буквы Z использовать… Но нет. Поэтому нарисовал свою иконку, кривую косую, но свою)

Финансы


Приложению почти 2 года. Потрачено $200 только за то чтобы приложение было в AppStore. Не считая разработки и push сервера.

image
В приложении есть рекламка от гугла… Которая принесла…… 5$
Отключение рекламы принесло 88$… Но порог вывода от 150$.
Потом буду удалять рекламу вообще как только достигнет порога вывода.

Push сервер


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

Имеется 2 сервера, Москва и Нидерланды по 2 руб/сутки. DNS балансировка, Nginx c Let’s Encrypt, PHP скрипт для приема и отправки.

Изначально был фри сервер на Амазоне (15 гиг трафика…), но как начал подходить его срок купил VPS-ку чтобы туда съехать. И застал момент что шел DDOS на хостинг провайдера и vps была 12 часов не доступна… 2 рубля чего хотеть больше. Хорошо я еще был на Амазоне и меня это еще не зааффектило. Поэтому потом взят еще один за 2 рубля в сутки, но в другой локации. Хоть какая-то отказоусточивость и трафика на 15 гиг… Основные опасения за Амазон трафик, микро ddos и ты попал на деньги.

Хотел как балансер использовать Cloudflare, но они хотят делегацию всего домена к ним, а не под домена.

Немного статистики


Всего почти 6 тысяч скачиваний. И Бразилия в топе… кто бы мог подумать)

image

Выводы


  • Swift ничего так)
  • Обилие статей и удобство IDE в современном мире, позволяет очень быстро сделать первый старт.
  • Приложение писалось изначально для себя, но получился хороший опыт и с разработкой и с выкладыванием в AppStore с позитивными и негативными отзывами.
  • Разработка хорошо прочищает мозги.
  • Нужно лучше читать доки и не делать из асинхронного кода синхронный :)
  • Вообщем пишите, копируйте, изучайте. Только так можно на практике понять что и к чему.
  • * Больше общайтесь с пользователями, они точно скажут зачем им это и как они хотят это видеть. Треть функционала в приложении я добавил именно по желаниям пользователей.

© Habrahabr.ru