SwiftyDev

Обо мнеПортфолио
Пишите на aaisataev@gmail.com

Не могу соединиться с базой данных

Не могу соединиться с базой данных

Не могу соединиться с базой данных

Не могу соединиться с базой данных

Не могу соединиться с базой данных

Как подписать PDF на маке

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

Что делают 99% людей: не получают такой оффер скидывают PDF на флэшку, идут в ближайший копировальный центр, распечатывают документ, подписывают его, делают скан, записывают обратно на флэшку, идут домой, закачивают себе на компьютер этот несчастный PDF с подписью и, наконец, отправляют его обратно.

Что делаем мы:

4 мес   tutorial

SwiftGen. Генерируем код для ресурсов

Что такое SwiftFormat?

SwiftGen — это инструмент для генерирования кода для ресурсов. Проще говоря, он генерирует код для наших картинок, цветов, шрифтов, файлов локализации и т. д.
И вот как он работает:

Для чего он нужен?

  1. Помогает избежать опечаток при работе со строками
  2. Делает невозможным использование несуществующих файлов
  3. Автозаполнение
  4. И все это обеспечивается компилятором

Как его установить?

SwiftGen можно установить через CocoaPods, homebrew, mint, так же его можно вручную добавить в проект. Я считаю, что самый оптимальный способ при работе в команде — это установить SwiftGen через CocoaPods.

Для этого просто нужно добавить следующий под в подфайл:

pod 'SwiftGen', '~> 6.0'

Затем, обновляем поды в директории проекта:

pod update

Далее нужно добавить следующее в run script build phase:

$PODS_ROOT/SwiftGen/bin/swiftgen xcassets -t swift4 -o ${SRCROOT}/Resources/Assets/Assets.swift ${SRCROOT}/Resources/Assets/Assets.xcassets // 1
$PODS_ROOT/SwiftGen/bin/swiftgen fonts -t swift4 -o ${SRCROOT}/Resources/Fonts/Fonts.swift ${SRCROOT}/Resources/Fonts // 2
$PODS_ROOT/SwiftGen/bin/swiftgen colors -t swift4 -o ${SRCROOT}/Resources/Colors/Colors.swift ${SRCROOT}/Resources/Colors/Colors.txt // 3
$PODS_ROOT/SwiftGen/bin/swiftgen strings -t structured-swift4 -o ${SRCROOT}/Resources/Localization/Strings.swift ${SRCROOT}/Resources/Localization/ru.lproj/Localizable.strings // 4
  1. Генерирует код для xcassets. Мы тут указываем, что генерируем код в Assets.swift из Assets.xcassets, указывая их пути.
  2. Таким же образом генерирует код для шрифтов.
  3. Таким же образом генерирует код для цветов.
  4. Таким же образом генерирует код для файлов локализации.

Можно так же генерировать код для Core Data, Interface Builder files, JSON and YAML files, Plists и т. д.

Теперь SwiftGen будет генерировать код для нужных нам ресурсов при каждой сборке проекта. Вот каким образом можно использовать добавленные ресурсы:

let beerIcon = Asset.beer.image
let boozeColor = ColorName.booze.color
let helloText = L10n.hello

Заключение

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

6 мес   tutorial

SwiftFormat. Форматируем код

Что такое SwiftFormat?

SwiftFormat — это инструмент для, не поверишь, форматирования кода.
Вот как он работает:

Для чего он нужен?

Работая в команде, хорошо иметь единый Code Style. И как настоящий тру разработчик, лучше автоматизировать все, что можно автоматизировать. И лучше думать о том, как работает код, нежели о том, как он выглядит.

Как его установить?

Есть несколько способов установить SwiftFormat, я покажу вам пару.

Command-line tool

Открываем терминал и обновляем homebrew:

$ brew update

Устанавливаем SwiftFormat:

$ brew install swiftformat

Далее идем в директорию проекта:

$ cd myProject

И запускаем следующее, чтобы отформатировать все файлы:

$ swiftformat .

Чтобы отформатировать определенный файл, нужно ввести:

$ swiftformat GodClass.swift

Build phase в Xcode

Но запускать его каждый раз вручную как-то не тру. Поэтому мы сделаем так, что при каждом билде проекта, SwiftFormat будет запускаться сам. Для этого так же устанавливаем swiftformat через терминал и добавляем следующее в run script build phase:

if which swiftformat >/dev/null; then
  swiftformat .
else
  echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat"
fi

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

Заключение

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

6 мес   tutorial

Нужно ли писать weak self в Grand Central Dispatch?

Тут у нас возник спор: нужно ли писать [weak self] в GCD?

Один говорит:
— [weak self] нужно писать везде!
Второй говорит:
— Нет, даже если не писать [weak self] внутри DispatchQueue, утечки памяти не будет.

Вместо того, чтобы разбираться, легче написать пару строк. Тяжелее об этом написать пост.

Итак, мы создадим UIViewController, в котором будет вызываться метод в DispatchQueue через пять секунд после viewDidLoad.

Этот ViewController будет пушиться с другого ViewController-а. А сама суть в том, что за эти пять секунд, до вызова нашего метода, мы должны удалить этот ViewController со стэка UINavigationController. То есть просто нажать назад.

После запуска в консоли видим, что после создания нашего ViewController-a вызвался viewDidLoad. Затем после нажатия назад, наш ViewController удалился из памяти и вызвался deinit. А наш метод в DispatchQueue не вызвался с 19-ой строки, потому что в этот момент нашего ViewController-a уже не существует, self равно nil.

Теперь посмотрим, что будет если мы уберем [weak self].

Вызывается viewDidLoad. После пяти секунд исполняется наш метод и только потом ViewController деинитится. То есть после нажатия назад, наш ViewController живет, пока не исполнится метод и только потом освобождается. Но утечки памяти не происходит! Потому что в итоге он удалился.

А что будет, если в DispatchQueue передать какой-нибудь closure. Вот так:

Вызывается viewDidLoad. Затем удаляется ViewController. А после пяти секунд исполняется наш closure. То есть ему не важно жив ViewController или нет. У него нету ссылки на наш ViewController. Он по-любому вызовется.

А как должно быть, чтобы произошла утечка? Нужно, чтобы наш closure вызывал метод ViewController-a, то есть имел на него ссылку.

Вот, в итоге deinit не вызвался и мы получили memory leak. А чтобы избавиться от него, нужно всего лишь в closure написать [weak self].

Итог
Не важно, писать [weak self] в GCD или нет, утечки памяти не будет. Но надо знать, что у них поведение разное. В первом случае, то, что внутри Dispatch-a не исполнится. А во втором — исполнится, но до его исполнения ViewController будет жить.

6 мес  

Booze. Reincarnation

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

Прошел год после того, как мы закрыли Booze.

Я работал на разных проектах, писал код и Unit/UI тесты, фиксил баги, делал код ревью, писал документацию и, в целом, глубоко засел в недрах Xcode-а.

Но за этот год не было и дня, чтобы я не думал о той маленькой, спрятанной папке, где лежали исходники проекта Booze.

И вот, наконец, пришло время его реинкарнировать.

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

И чтобы было интересно, репозиторий проекта я сделаю публичным и буду использовать разные паттерны и разную архитектуру для разных модулей. Так же буду писать тесты, документацию и настрою CI/CD.

Добро пожаловать.

7 мес   booze   portfolio

Meniń atym Asylbek Isataev

В далеком 2017 году наш ноль-первый(в двоичной системе 01) подписал указ о переводе алфавита с кириллицы на латиницу.

Техдиректор Forbes Kazakhstan Дмитрий Майжанов недолго думая открыл сайт и немножечко хайпанул: за пару дней сайт посетили четверть миллиона человек.

Я задумался и придумал: напишу приложение и заработаю на хайпе свой первый миллион.

Открыл xCode, добавил на экран одно поле и одну кнопку. В поле вводится имя, кнопка переводит его в латиницу. Просто, как у ребёнка конфетку отобрать.
Далее добавил рекламу от корпорации добра, а идея о миллионах мне все еще кружила голову. Вся эта канитель заняла пару часов, а принесла чуть менее $100 за все свое существование. А существовало приложение полгода. Убрал я его из AppStore из-за отсутствия дизайна.

Спустя год, сегодня, я решил переписать приложение и переписал. Далее одна картинка, один отзыв и один кусок кода.

Отзыв:

Абсолютно простой, великолепный и изысканный дизайн.
Людвиг Быстроновский. Арт-директор Студии Лебедева

Кусок кода, который переводит слова:

class Alphabet {
    static let alphabet = ["а":"a", "ә":"á", "б":"b", "в":"v", "г":"g", "ғ":"ǵ", "д":"d", "е":"e",
                    "ё":"e", "ж":"j", "з":"z", "и":"ı", "й":"ı", "к":"k", "қ":"q", "л":"l",
                    "м":"m", "н":"n", "ң":"ń", "о":"o", "ө":"ó", "п":"p", "р":"r", "с":"s",
                    "т":"t", "у":"ý", "ұ":"u", "ү":"ú", "ф":"f", "х":"h", "һ":"h", "ц":"ts", "ч":"ch",
                    "ш":"sh", "щ":"sh", "ъ":"", "ы":"y", "і":"i", "ь":"", "э":"іe", "ю":"iý", "я":"ia",
                    " ": " ", ",": ",", ".": ".", "-": "-"]
    
    static func translate(words: String) -> String {
        var translation = String()
        for character in words.lowercased() {
            for letter in alphabet {
                if character == Character(letter.key) {
                    translation += letter.value
                }
            }
        }
        return translation.capitalized
    }
}

class MainViewController: UIViewController {
    
    ......

    @objc private func translateButtonDidPress() {
        guard let text = textField.text else { return }
        let translation = Alphabet.translate(words: text)
        nameLabel.text = translation
    }
}

Спасибо за внимание. Скачивайте приложение, ставьте лайки и подписывайтесь на мой канал.

P.S. Рекламу из приложения убрал, так как на этом *%# заработаешь.

8 мес   portfolio
9 мес   portfolio

Booze. Коротко о

Все началось с ошибки.

Я открыл третью банку Paulaner и сел за iMac. За окном был октябрь и я решил обзавестись домашним проектом.

Сделал довольно-таки хороший глоток, открыл топ-500 стартапов этого года(а это был 17ый) и начал искать вариант, который можно было бы нагло украсть и легко реализовать.

И таки после трех страниц поиска мне приглянулся американский проект под названием Hooch. Приложение, которое дает одну бесплатную выпивку в день за 9$ в месяц.

Hooch в переводе значит выпивка. Значит, что надо.

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

К этому моменту я открыл уже четвертую банку, а модель была гениально придумана за минуту: За 880 тенге наш пользователь получает каждый день одно бесплатное пиво у наших партнеров. Слоган для рекламы: 30 кружек пива за 880 тенге. А партнеры, читай пабы, получают базу целевой аудитории.

Команда была собрана, люди тщательно отобраны: четыре программиста и один крутой продажник.

Через три месяца активной работы у нас было 2 приложения, 75 закрытых веток в GitHub, 5 отзывов в AppStore, полсотни бессонных ночей и множество багов всех сортов и расцветок, а также тысячи выкуренных Winston, 20 пустых ящиков от пива, недопитый Jameson и какой-то ром. Не то чтобы все это было необходимо для разработки домашнего проекта, но раз уж начал делать для себя, то сложно остановиться...

Далее мы запустили рекламу в фейсбуке и инстаграме. Активировали пробный период, который длился месяц. И так за неделю Booze скачали 1000 человек и начали пить с ним на халяву.

Дела шли хорошо, но неизвестно куда.

Параллельно мы улучшали приложение, добавлялись новые пабы. Но наши хмельные пользователи после бесплатного периода не хотели платить 880 тенге в месяц. Даже если бы они получали за эти деньги 30 бутылок пива. Наших не поймешь.

Пришлось изменить бизнес модель. Убрали подписку — теперь пользователи абсолютно бесплатно получали одно бесплатное пиво каждый день. Без подписки, без рекламы. А зарабатывали мы на пабах: за каждого уникального клиента в месяц мы получали условные 200тг.

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

Мы были удивлены, пабы не очень. И очень скоро один за другим все пабы начали отказывать нам в сотрудничестве, даже за бесплатно.

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

Мир остался по-прежнему пьяный, но уже без бесплатного пива.

10 мес   booze   portfolio

Intro

Стив Джобс еще был жив, когда я получил свой первый iPhone. И только умер, когда я купил себе новенький Macbook Pro.

Пару лет спустя, устав играть в Angry Birds, я решил стать iOS разработчиком.

И как это обычно делается, купил аккаунт, прочитал документацию, открыл xCode и начал кодить hello world.

Меня зовут Асылбек Исатаев. Здесь я буду постить свои работы, мысли и все остальное.

Всем здравствуйте.

11 мес