Swift программа что это
Учебник Swift — разработка приложения для iOS8 [Часть 1, Hello World!]
Предисловие
Недавно Apple представила общественности достаточно важное изменение в разработке iOS приложений, анонсировав новый язык программирования Swift. Я принял решение: изучая этот язык пошагово, я буду в своих статьях рассказывать обо всём, что мне удалось найти. Это лишь первый пост из многих на эту тему, но я надеюсь, что вы решите изучать язык вместе со мной!
Весьма вероятно, что многие примеры кода, представленные в постах, будут позже изменены. Это отчасти потому, что мой стиль программирования – написать сейчас, чтобы проверить идею, а потом заняться рефакторингом, а также отчасти это потому, что для меня (как и для многих других) Swift – абсолютно новый язык программирования. Так что, скорее всего, как только я узнаю что-нибудь новое, ход этих уроков будет меняться.
Итак, я собираюсь начать с довольно простого приложения. Также я буду объяснять, как работает код. Готовы? Поехали…
UPD: Статья написана в соответствии с изменениями в XСode 6 Beta 5
Основы
в Swift будет заменена на эту
Для объявления констант используется ключевое слово let
В данном случае kSomeConstant неявно определяется как целое число. Если же вы хотите конкретизировать тип, то вы можете это сделать так:
Автор перевода рекомендует пользоваться вторым примером объявления констант. Довольно показательный пример описан в официальной документации:
В этом автор перевода солидарен с Helecta (см. соответствующий пост)
И массивы, и словари описываются с помощью []
Это ещё далеко не всё, однако я считаю, что эти основы достаточно важны для дальнейшего чтения учебника. Итак, давайте перейдём к Hello, World!
Hello, World!
В первую очередь, мы напишем самое простое приложение, которое только можно представить, чтобы начать работу — Hello, World!
Наше приложение будет делать только одно: печатать фразу «Hello, World!» в консоль. Для этого нам потребуется установленная IDE XCode, для скачивания которой необходима учётная запись разработчика. Если у вас есть аккаунт, то смело качайте с официального сайта XCode 6 beta 4, желательно это сделать до прочтения ниже описанного.
Итак, вы установили свою копию IDE. Теперь давайте выведем «Hello, World!» на консоль.Этот пример не только демонстрирует простейшее приложение, которое можно написать, но и, что немаловажно, показывает, что среда разработки настроена правильно.
В XCode создайте проект с помощью шаблона приложения с одним видом («Single View Application»).
Убедитесь, что вы выбрали Swift в качестве языка приложения.
Теперь вы должны найти файл AppDelegate.swift в иерархии проекта. Внутри найдите следующую строку:
Замените эту строку на наш изумительный код:
Добавление Table View
Примечание:Я получил целую тонну вопросов о вышесказанном, т.к. многие люди сообщают о том, что у них не устанавливается табличный вид. Поэтому, я записал видео, поясняющее как работает подключение объектов Storyboard в коде. Для просмотра перейдите в полноэкранный режим и выберите опцию 720p, чтобы вы могли заметить всё, что вас интересует. Это будет немного отличаться от интерфейса XCode, но функционально всё работает также.
А теперь давайте углубимся в методы протоколов для табличного представления. Из-за использования UITableViewDataSource и UITableViewDelegate мы должны изменить определение класса.
Откройте файл и замените строку
Если вы нажмёте клавишу «Command» и кликните на один из этих протоколов, то увидите «обязательные» функции. Для табличного представления необходимы как минимум эти две:
Изменим наш класс View Controller путём добавления этих двух функций:
Первый метод возвращает количество строк в разделе. В нашем примере используется «магическое» число 10, однако вместо него, как правило, должна использоваться длинна контроллера массива. Наш же код умышленно упрощён.
При запуске приложения вы увидите восхитительный список ячеек с заголовками и подзаголовками, показывающие номера их строк. Это один из наиболее распространённых способов отображения данных в iOS, вы убедитесь, он вам ещё не раз пригодится. Увидеть полный текст кода вы можете на github.
В следующем посте мы исследуем использование API поиска iTunes для создания приложения, способного искать и отображать альбомы внутри iTunes Store.
Swift. Язык программирования с открытым кодом. Мощь, простота и потрясающие приложения.
Swift — это надёжный и интуитивно понятный язык программирования от Apple, при помощи которого можно создавать приложения для iOS, Mac, Apple TV и Apple Watch. Он предоставляет разработчикам небывалую свободу творчества. Благодаря этому простому и удобному языку с открытым кодом вам достаточно просто интересной идеи, чтобы создать нечто невероятное.
Разработчики уже пользуются
удивительными возможностями Swift.
Swift — это быстрый и эффективный язык программирования с откликом в реальном времени, который легко можно вставить в готовый код Objective-C. Теперь разработчики могут не только писать более надёжные и безопасные коды, но также экономить время и создавать приложения с расширенными возможностями.
Прекрасное приложение в Swift. Простота использования и отклик в реальном времени — вот почему VSCO выбрали Swift, чтобы создать новую версию своего фотоприложения для iOS.
Превосходные приложения,
разработанные на языке Swift.
Всё больше разработчиков встраивают код Swift в свои приложения. А некоторые даже создают в Swift совершенно новые приложения.
Производительность выше. Приложения лучше.
Приложения Swift превосходят ожидания. Например, обычный алгоритм поиска выполняется в Swift гораздо быстрее.
В графе с использованием алгоритма поиска в глубину найдено 10 000 целых чисел*
Язык Swift добавлен
в учебную программу.
Потенциал Swift оценили учебные заведения по всему миру. Они используют Swift и Xcode на Mac для обучения, обеспечивая своих студентов лучшими инструментами для создания приложений. А с бесплатной учебной программой от Apple «Разработка на языке Swift» даже новички легко переходят от основ программирования к профессиональной разработке.
Университеты, включившие язык Swift в учебную программу
Swift повсюду.
И теперь открыт для всех.
Swift бесплатно доступен для использования разработчиками, преподавателями и студентами по лицензии на распространение ПО с открытым исходным кодом Apache 2.0. Мы предоставляем двоичные файлы для OS X и Linux, которые позволяют компилировать код для iOS, OS X, watchOS, tvOS и Linux. А чтобы ускорить развитие и превращение Swift в ещё более мощный язык, мы создали новое сообщество, где пользователи могут напрямую вносить свой вклад в исходный код Swift.
Познакомьтесь со Swift.
Главная книга
Загрузите учебник Язык программирования Swift из Apple Books Store бесплатно. Узнайте, как благодаря Swift процесс программирования становится более удобным, гибким и увлекательным.
Xcode
Xcode — это приложение для Mac, предназначенное для разработки других приложений для Mac и iOS. В Xcode есть все инструменты, необходимые для создания потрясающих приложений. Его можно загрузить бесплатно из Mac App Store.
Веб-сайт для разработчиков
Получите подробную техническую информацию и ознакомьтесь с полным обзором языка Swift. Посмотрите блог для разработчиков, чтобы быть в курсе последних новостей. У вас также есть бесплатный доступ к отличным ресурсам: руководствам, видео и примерам кода.
Swift Часть 1: Быстрый старт
Swift Часть 1: Быстрый старт
Эта статья будет полезна как новичкам, так и опытным программистам. Если вы новичок, то Swift отлично подходит на роль первого ЯП, а если вы гуру, то никогда не бывает лишним закрепить свои знания. Здесь каждый найдет для себя, что-то полезное.
Хотя этот туториал и не займет много времени, в нем вы познакомитесь со всем самым необходимым: переменными, управлением потока, классами, лучшими практиками и многим другим. Также, в конце обучения, мы попробуем написать наше первое (а для кого-то нет) приложение.
Для того чтобы благополучно пройти этот туториал, вам понадобится версия Xcode не ниже 6.1.1 (версия Xcode на время написания статьи).
Привет, Playground!
При запуске Xcode 6 мы увидим вот что:
Нажимаем на Get started with playground, даем свое имя и жмем Далее (вариант выбора платформы на данном этапе нас не интересует). Сохраняем наш playground в удобном для вас месте и приступаем.
Мы создали новый тип Playground файла, который позволяет нам тестировать Swift-код и моментально видеть результат. К примеру, попробуйте добавить следующие строчки кода в ваш Playground:
Спорим, что как только вы написали эти три строчки, вы сразу увидели результат работы в правой части? Это очень удобно, не так ли?
Заметка
Перенесите файл SwiftPlaygorund.playground на панель быстрого запуска. Таким образом, вы всегда сможете быстро его открыть для тестирования вашего кода на Swift.
Переменные и константы в Swift
Попробуйте добавить следующую строку в конец вашего кода в Playground:
Явная и неявная типизация
Таким образом мы не указываем явно типы для этих констант и переменных, потому что компилятор имеет достаточно информации для того, чтобы эти типы вывести автоматически.
Вообще, вы можете указать тип явно, если хотите. Попробуйте заменить строку объявления tutorialTeam на следующую:
Мы выяснили, что в данном случае лучшей практикой для нас будет указывать тип переменной лишь при необходимости, поэтому, удаляем Int :
Базовые типы и управление потоком в Swift
Float и Double
Давайте попробуем вставить еще пару строк в конец нашей игровой площадки и познакомимся с базовыми типами Float и Double :
Есть два типа для работы с числами с плавающей точкой: Float и Double :
Вписываем себе пример констант логического типа Bool :
String
Подобрались к строковым значениям:
Обратите внимание, что больше мы не используем символ @ как в Objective-C.
Конструкции If и интерполяция строк
Условное выражение выглядит очень похоже на любой другой язык. Круглые скобки вокруг условия опциональны, а вот фигурные скобки обязательны даже в тех случаях, когда вам нужно исполнить всего одну строку кода!
Вы можете наблюдать работу функции print() в боковой панели, но это может быть проблематично, если ваша строка длинная. Для того, чтобы увидеть результат полностью вам нужно нажать на пиктограмму глаза, в правой части playground’а, который появится при наведении на строку результата:
Есть и другой способ посмотреть длинное значение выражения. Вам нужно пройти в главное меню Xcode (то, что наверху) View\Assistant Editor\Show Assistant Editor.
Assistant Editor покажет вам результат работы функции print() без наведения на строку результата, что согласитесь, само по себе проще. Если вы что-то не поняли, то можете скачать наш файл playground’а со всем кодом что был написан выше.
Классы и Методы
Далее, мы создадим класс, который поможет нам, допустим, посчитать количество чаевых, которые мы должны оставить в ресторане.
Если вы создаете субкласс, то после имени субкласса, вам нужно поставить двоеточие и имя суперкласса. В отличии от Objective-C в Swift вам не нужно постоянно писать суперкласс NSObject или что-то другое. Добавьте в фигурные скобки следующее:
После того, как вы добавите этот код, вы получите несколько ошибок, не переживайте, мы скоро их исправим.
Обратите внимание, что вы обязаны указывать начальное значение для свойств при их объявлении, также, вы можете указать их в инициализаторе. Но мы не сделали ни того, ни другого, поэтому получаем ошибки. Если нет желания указывать начальное или исходное значение, то необходимо объявить свойства как опционалы, но это совсем другая история, то есть туториал.
Теперь добавьте следующий блок в фигурные скобки:
Тут мы создали инициализатор для класса, который принимает два параметра. Инициализатор всегда называется ключевым словом init в Swift. Вы можете создать несколько инициализаторов, если вам так угодно, вот только они должны принимать разные параметры.
Теперь, у нас нет никакого конфликта имен для свойства subtotal, так что нам больше не нужно добавлять self, потому что компилятор уже автоматически выводит его, когда это нужно. Для тех, кому не все равно откуда взялось subtotal = total / ( taxPct + 1) поясним:
Теперь, добавьте следующий блок кода в фигурные скобки (после предыдущего в фигурных скобках):
Эта функция определяет размер налога, путем перемножения процента на общую сумму.
Теперь, добавляем следующий блок и снова в самый конец фигурных скобок:
Вот этот блок, когда представляет из себя новый метод, который выводит на экран три возможных варианта чаевых. Когда вы вызываете метод класса, то первый параметр необязательно должен иметь имя, но остальные должны.
Теперь, давайте добавим последний кусок кода в самый конец, после фигурных скобок:
Наконец-то, мы создали подобие калькулятора для чаевых Вот, что в итоге у нас должно было получиться в нашей «игровой площадке»:
Проверьте ваш Assistant Editor на наличие результата:
Массивы и цикл For
В данный момент у нас есть некоторое дублирование кода, потому что мы вызываем метод calcTipWithTipPct несколько раз, с различным процентом чаевых. Вы можете уменьшить дублирование кода, используя массив.
Замените содержимое printPossibleTips вот это:
Теперь, добавим эти строки ниже:
Вы можете написать альтернативный вариант вот в такой форме:
Словари
Давайте сделаем еще одно небольшое изменение в нашем чудо-калькуляторе чаевых. Вместо того, чтобы просто выводить значение чаевых, мы вернем словарь значений. Такой подход позволит упростить отображение результатов в некоторых интерфейсах.
Удаляем метод printPossibleTips и вместо него пишем:
Вылезла ошибка, но не бойтесь, она поправима. Начнем сверху нашего кода и пройдемся от секции к секции:
Наконец, осталось изменить последнюю строку нашей игровой площадки. Собственно, именно она и исправит ошибку.
После того как произойдут некоторые вычисления, вы увидите в инспекторе результат в виде словаря (нажмите на глаз для расширенного вида):
Примите наши поздравления! Вы сделали свой первый калькулятор чаевых на Swift! Конечный вариант нашего playground.
Что делать дальше? Продолжайте читать туториалы и перевод книги по Swift. Надеемся, данная статья была для вас полезной. До встречи в следующем уроке!
Язык программирования Swift. Русская версия
Привет, Хабр! 2 июня все мы воочию могли наблюдать, как компания Apple начала творить революцию в стане Objective-C разработчиков, представив миру свой новый язык программирования – Swift. Вместе с этим, она выложила в открытый доступ небольшую документацию по языку, которую мы решили перевести, если на то будет спрос. Предлагаем вашему вниманию перевод первой главы. Если тема будет интересна, то мы продолжим публиковать перевод каждую неделю.
Оглавление
Добро пожаловать в Swift
О Swift
Введение в Swift
Language guide
The Basics
Basic Operators
String and Characters
Collection Types
Control Flow
Functions
Closures
Enumerations
Classes and Structures
Properties
Methods
Subscripts
Inheritance
Initialization
Deinitialization
Automatic Reference Counting
Optional Chaining
Type Casting
Nested Types
Extensions
Protocols
Generics
Advanced Operators
Language Reference
About the Language Reference
Lexical Structure
Types
Expressions
Statements
Declarations
Attributes
Patterns
Generic Parameters and Arguments
Summary of the Grammar
Trademarks
Добро пожаловать в Swift
О языке Swift
Swift – это новый язык программирования для разработки iOS и OS X приложений, который сочетает в себе все лучшее от C и Objective-C, но лишен ограничений, накладываемых в угоду совместимости с C. В Swift используются паттерны безопасного программирования и добавлены современные функции, превращающие создание приложения в простой, более гибкий и увлекательный процесс. Swift, созданый нами с чистого листа, – это возможность заново представить себе, как разрабатываются приложения.
Swift разрабатывался нами несколько лет. Основой нового языка программирования послужили существующие компилятор, отладчик и фреймворки. Мы упростили процесс управления памятью с помощью механизма автоматического подсчета ссылок – Automatic Reference Counting (ARC). Наши фреймворки также подверглись серьезной модернизации. Objective-C начал поддерживать блоки, литералы и модули – все это создало благоприятные условия для внедрения современных технологий. Именно эта подготовительная работа послужила фундаментом для нового языка программирования, который будет применяться для разработки будущих программных продуктов для Apple.
Разработчикам Objective-C Swift покажется знакомым. Он сочетает в себе читабельность именованных параметров и мощь динамической объектной модели Objective-C. Он открывает доступ к уже существующим фреймворкам Cocoa и совместим с кодом, написанным на Objective-C. Построенный на этой общей основе язык предлагает множество новых возможностей и унифицирует процедурные и объектно-ориентированные аспекты языка программирования.
Swift не отпугнет и начинающих программистов. Это первый мощный язык программирования, такой же понятный и увлекательный, как скриптовый язык. Он поддерживает так называемые playground-ы, которые позволяют программистам экспериментировать с кодом, видя результат в режиме реального времени без необходимости компилировать и запускать приложение.
Swift вобрал в себя все лучшее от современных языков и разработан с учетом обширного опыта компании Apple. Наш компилятор – синоним производительности, наш язык оптимизирован для разработки без оглядки на компромиссы. Он спроектирован таким образом, чтобы вы смогли легко разработать и ваше первое приложение «hello, world!», и даже целую операционную систему. Все это делает Swift важным инструментом для разработчиков и для самой компании Apple.
Swift – это новый фантастический способ создавать приложения для iOS и OS X, и мы продолжим развивать его, добавляя новый функционал и представляя новые возможности. Наша цель – амбициозна. И мы с нетерпением ждем, чтобы увидеть, что вы сумеете создать при помощи него.
Введение в Swift
Если вы когда-нибудь разрабатывали на C или Objective-C этот синтаксис должен казаться вам до боли знакомым – в Swift эта строчка кода является законченной программой. Вам больше не нужно импортировать отдельные библиотеки для обеспечения базового функционала вроде ввода/вывода в консоль или работы со строками. Код, написанный в глобальной области видимости, является точкой входа в программу, таким образом функция main больше не нужна. Также обратите внимание на отсутствие точки с запятой в конце каждой строки.
Это введение содержит достаточно информации, чтобы начать писать код на Swift. Не переживайте, если вам будет что-то непонятно – мы все детально объясним в последующих главах.
Замечание
Для лучшего понимания материала мы рекомендуем использовать режим playground в Xcode. Playground позволяет вам видеть результат сразу в процессе редактирования кода без необходимости компилировать и запускать приложение.
Простые типы данных
Используйте let для создания константы и var для создания переменной. Тип константы указывать не нужно, вы можете присвоить ей значение лишь единожды.
Типы константы и переменной должны совпадать с типами присваиваемых им соответствующих значений. Однако это не означает, что вы должны напрямую указывать их тип. Компилятор автоматически определит тип константы и переменной при присваивании им значения. Так, в приведенном примере компилятор определит, что myVariable имеет целочисленный тип.
Если же инициализатор отсутствует или не предоставляет достаточной информации, вы можете указать тип самостоятельно после переменной, разделив название и тип двоеточием:
Давайте поэкспериментируем
Создайте константу с типом Float и проинициализируйте ее числом 4.
Значения никогда не конвертируются в другой тип неявно. Если вам необходимо конвертировать значение в другой тип, делайте это явно:
Давайте поэкспериментируем
Попробуйте удалить явное преобразование к типу String в последней строке. Какую ошибку вы получите?
Имеется более простой способ включения значений в строки: для этого заключите выражение в скобки и поставьте перед ними обратный слэш ( \ ). Пример:
Давайте поэкспериментируем
Попробуйте использовать конструкцию \() и выведите на экран строку, включающую результат суммы двух целочисленных переменных и чье-нибудь имя.
При работе с массивами и ассоциативными массивами (словарями, dictionary) используются квадратные скобки ( [] ):
Чтобы создать пустой массив или dictionary, используйте следующий синтаксис:
Для создания пустых массивов и словарей используйте [] и [:] соответственно, – например, когда вы присваиваете новое значение переменной или передаете аргумент в функцию.
Условия и циклы
Условие внутри оператора if должно быть логическим, это в частности означает, что выражение if score <…>является ошибочным, поскольку здесь нет явного сравнения (например, с нулем).
Оператор множественного выбора switch поддерживает внутри себя множество других операторов сравнения и не ограничен лишь простыми сравнениями:
Давайте поэкспериментируем
Попробуйте удалить условие по умолчанию. Какую ошибку вы получите?
Для перебирания элементов ассоциативного массива используйте оператор for-in совместно с указанием пары имен для каждой пары ключ-значение.
Давайте поэкспериментируем
Добавьте еще одну переменную, которая позволит выяснить, к какому из трех типов относится найденное максимальное число.
Оператор цикла while позволяет выполнять блок кода внутри него до тех пор, пока условие не станет ложным. Условие также может быть указано после блока, который в таком случае будет выполнен по крайней мере один раз.
Функции и замыкания.
Давайте поэкспериментируем
Удалите параметр day. Вместо него добавьте переменную, обозначающую наименование подаваемого на обед блюда.
Если функция возвращает множество значений, следует использовать кортеж:
Функции также могут иметь неопределенное число аргументов:
Давайте поэкспериментируем
Напишите функцию, позволяющую находить среднее арифметическое произвольного числа своих аргументов.
Функции могут вкладываться друг в друга. Вложенная функция может обращаться к переменным, объявленным во внешней функции. Используйте вложенные функции, чтобы привести в порядок код сложной или большой функции.
Функции являются объектами первого класса (first-class type), иными словами, функция в качестве свого результата может возвращать другую функцию.
Функция также может принимать другую функцию в качестве одного из аргументов.
Давайте поэкспериментируем
Перепишите замыкание таким образом, чтобы оно возвращало ноль для всех лишних чисел.
Существует несколько техник, позволяющих делать замыкания более лаконичными. Если тип замыкания априори известен (например, это callback делегата), можно опустить указание типа его параметров и/или типа возвращаемого значения. Замыкания, состоящие из единственного выражения, неявно возвращают результат этого выражения.
В замыкании вместо указания имени переменной, вы можете использовать ее порядковый номер – это особенно полезно при написании коротких замыканий. Замыкание, являющееся последним аргументом функции, может быть передано в нее сразу после круглых скобок с перечнем остальных параметров.
Объекты и классы
Давайте поэкспериментируем
Добавьте константу-член класса и метод класса, принимающую ее в качестве своего аргумента.
Чтобы создать экземпляр (объект) класса, достаточно добавить круглые скобки после названия класса. Доступ к методам и членам класса осуществляется через точку.
Чтобы наследовать класс от уже существующего класса, после указания имени дочернего класса следует поставить двоеточие и указать название родительского. В Swift нет никаких ограничений по обязательному наследованию какого-либо стандартного класса.
У методов классов имеется одно важное отличие от функций. Названия аргументов функции используются только в пределах этой функции, тогда как в методе класса параметры также используются при вызове этого метода (кроме первого параметра). По умолчанию метод класса имеет одинаковые названия параметров как при вызове, так и внутри себя. Однако вы можете указать другое название (в примере ниже – times ), которое будет использовано только внутри этого метода. При этом для вызова этого метода необходимо использовать первое название ( numberOfTimes ).
Перечисления и Структуры
Давайте поэкспериментируем
Напишите функцию, которая сравнивает 2 перечисления типа Rank по их значениям.
В вышеприведенном примере элементы перечисления первоначально имеют целочисленный тип, и вам достаточно указать значение только первого элемента – значения остальных элементов будут определены в соответствии с порядком их следования. В качестве исходного типа (raw value) значений элементов вы также можете выбрать строковый или вещественные типы.
Отметим, что значения элементов перечисления являются фактическими, а не просто иной записью своих исходных значений. Вообще говоря, вы можете и не указывать их исходные значения.
Давайте поэкспериментируем
Добавьте в структуру Card метод, который создает полную колоду карт.
Экземпляр члена перечисления может иметь собственные значения и они могут быть разными. Вы присваиваете эти значения при создании экземпляра перечисления (константа success в примере). Связанные и исходные значения это разные вещи: исходное значение члена перечисления всегда постоянно для всех экземпляров перечисления и указывается при его объявлении.
Рассмотрим пример получения с сервера времени восхода и заката Солнца. Сервер отправляет в ответ либо соответствующую информацию, либо сообщение об ошибке.
Давайте поэкспериментируем
Добавьте третий вариант в оператор множественного выбора switch
Обратите внимание, каким образом из объекта ServerResponse “вытаскиваются” время восхода и заката.
Протоколы и Расширения.
Протоколы могут поддерживаться классами, перечислениями и структурами.
Давайте поэкспериментируем
Создайте перечисление, которое будет реализовывать этот протокол.
Вы можете использовать название протокола как и любой другой тип – например, чтобы создать массив объектов разного типа, но реализующих общий протокол. Заметьте, что при работе с объектами такого типа методы, объявленные вне протокола, будут недоступны.
Обобщенные типы (generics)
Для создания обобщенного типа, заключите имя в угловые скобки ( <> ).
Создавайте обобщенные функции, классы, перечисления и структуры.
Давайте поэкспериментируем
Измените функцию anyCommonElements таким образом, чтобы она возвращала массив общих элементов.
Хотите внедрить подписки в iOS-приложение за 10 минут? Интегрируйте Apphud и:
— оформляйте покупки с помощью лишь одного метода;
— автоматически отслеживайте состояние подписки каждого пользователя;
— легко интегрируйте Subscription Offers;
— отправляйте события о подписках в Amplitude, Mixpanel, Slack и Telegram с учетом локальной валюты пользователя;
— уменьшайте Churn rate в приложениях и возвращайте отписавшихся пользователей.