iOS Dev
7.66K subscribers
991 photos
79 videos
1 file
1.14K links
🍏Канал об iOS-разработке, необычных подходах и решениях.
👨‍💻Автор: Виктор Грушевский (@Viktorianec)
Темы:
⭐️ Подготовка к собеседованиям.
⭐️ Архитектуры и алгоритмы.
⭐️ Код. Много кода.

⚒️База знаний: https://boosty.to/ios_dev

#ios #mobile #swift
Download Telegram
Corner Radius, Shadow, и Border в Swift: создание, использование и комбинирование

📖 В этой статье на простых примерах объясняется, как скруглить углы, применить тень и границы ко всем видам вьюх, включая UIViews, UIButtons и UIImageViews.

Также рассказывается про решение для одновременного использования shadow и corner radius, что для новичков может оказаться непростой задачей.

@iOS Dev
Простой способ работать с асинхронным кодом в Swift Playground

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

Итак, чтобы ваш код сработал, есть решение в одну строку:

💡 Для этого нужно установить значение needIndefiniteExecution в true.

😎 Не забудьте импортировать PlaygroundSupport.

Кстати, чтобы остановить выполнение, можно воспользоваться следующим методом:

PlaygroundPage.current.finishExecution()

@iOS Dev
Как добавить кастомный шрифт в приложение для iOS?

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

1️⃣ Представим, что у нас есть шрифт, который нужно использовать. Добавьте его как обычный файл в ваш проект.

2️⃣ Откройте ваш Info.plist. Если в вашем проекте его нет, то вкладку Info.

3️⃣ Добавьте ключ Fonts provided by application. Нужный шрифт из первого шага необходимо добавить вместе с его расширением.

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

for family in UIFont.familyNames.sorted() {
let names = UIFont.fontNames(forFamilyName: family)
print("Family: \(family) Font names: \(names)")
}


Бонус: вы также можете найти нужное имя, используя приложение «Шрифты» (можно и вбить Font в Launchpad).

Находите нужный и дальше используете его так, как привыкли:

label.font = UIFont(name: "CUSTOM_FONT_NAME", size: 25)

Интересный факт

📖 Lorem ipsum, который выступает заглушкой во всех (ну ладно, почти во всех) текстах на самом деле не что иное как искажённый отрывок из философского трактата Марка Туллия Цицерона «О пределах добра и зла», написанного в 45 году до н. э. на латинском языке.

@iOS Dev — In iOS Dev verĭtas
Как улучшить читаемость крупных чисел в Swift?

💡 Для этого может пригодиться нижнее подчёркивание или же просто _.

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

Кстати, в Swift нет ограничений на позицию нижнего подчёркивания, так что вы можете использовать и третий вариант. Но, пожалуйста, не делайте так😅

@iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
Интерактивные переходы для UIViewController в Swift: терминология и пример реализации

iOS предоставляет нам несколько красивых переходов для UIViewController, таких, например, как push и pop, но почему бы не сделать и свой собственный.

Кастомные анимации для переходов у UIViewController могут значительно улучшить восприятие пользователей и выделить ваше приложение из общей массы.

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

🟢 Как устроен API переходов.

🟢 Как представлять и удалять UIViewControllers с помощью пользовательских переходов.

🟢 Как создавать интерактивные переходы.

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

Кстати, эту статью можно рассматривать вместе с этим постом.

@iOS Dev
Как диагностировать узкие места при сборке ваших проектов на Swift?

Тайпчекер в Swift (инструмент проверки типов) постоянно улучшается, пусть раньше и был узким местом для производительности при компиляции.

В 2016 году Джордан Роуз добавил флаг компилятора Swift, который выдавал предупреждения в Xcode для функций, которые слишком долго компилировались или, если выразиться точнее, слишком долго проверялись.

А с Xcode 9 появился новый, аналогичный флаг для проверки выражений.

Речь ниже пойдёт о следующих двух флагах

-warn-long-function-bodies

Bryan Irace и Soroush Khanlou изначально описали флаг -warn-long-function-bodies. Вы можете указать порог в миллисекундах, при достижении которого будет выдаваться предупреждение.

Например: -Xfrontend -warn-long-function-bodies=100 будет выдавать предупреждение в Xcode для любой функции, проверка типа которой занимает более 100 мс.

Этот флаг всегда считался экспериментальным, как отметил Джордан в своем оригинальном коммите, но он всё ещё актуален.

-warn-long-expression-type-checking

С Xcode 9 появился новый аналогичный флаг для тайпчекинга выражений, а не только для функций. Однако на этот раз флаг появился в официальных примечаниях к выпуску Xcode 9 GM.

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

💡 Советы по использованию

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

Стоит немного поэкспериментировать со значениями, чтобы найти по-настоящему узкие места. Автор этой статьи предлагает начать с 200, а если ваш проект крупный - с 500, и пытаться уменьшить его с течением времени.

Иначе вы потратите много времени, пытаясь заставить все функции и выражения компилироваться менее чем за 200 мс.

Кроме того, рекомендуется использовать эти флаги только для конфигураций сборки DEBUG.

@iOS Dev
Что использовать вместо //TODO в коде?

Периодически бывает необходимо добавить напоминание или даже вывод ошибки.

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

В таком случае кроме традиционных комментариев на помощь могут прийти #warning и #error.

#warning заставит Xcode выдать предупреждение при сборке проекта, а #error покажет ошибку компиляции, поэтому код не соберётся вообще 😅 (будьте аккуратны!).

Кстати, и #warning, и #error будут корректно работать вместе с директивой #if (конечно, если условие будет истинно). Например, как в коде ниже:

#if os(macOS)
#error("Эта библиотека пока что не поддерживается на маке. Используйте другое решение")
#endif


А пример для #error со скриншота будет актуален если вы раздаёте ключи для вашей библиотеки, без которых она не будет работать.

Например, Firebase вполне мог бы использовать нечто подобное.

@iOS Dev — дополняем ваш инструментарий простыми средствами.
This media is not supported in your browser
VIEW IN TELEGRAM
Эксперимент с Live Activities — велокомпьютер на локскрине

Прошло менее недели с анонса доступности Live Activities для разработчиков в четвёртой бетке iOS 16, а Ole Begemann уже успел попробовать добавить функциональность в своё приложение.

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

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

Уже сейчас автор поднимает ряд важных вопросов:

1️⃣ Для Live Activities не нужно явного одобрения пользователя.

2️⃣ Приложение должно быть на переднем плане.
С другой стороны, это ограничение может не быть проблемой для большинства случаев использования и, вероятно, значительно сократит спам/злоупотребления.

3️⃣ Приложение должно продолжать работать в фоновом режиме, чтобы обновлять активность (или использовать push-уведомления).

4️⃣ Сложности с эстетикой внешнего вида.
Автор пытался найти в API метод для задания цветового стиля, но пока что безуспешно и решил захаркдодить foreground color. Может быть, Apple в будущем расширят возможности.

5️⃣ Анимацию нельзя отключить.
Возможно, полный контроль над анимацией также упрощает для Apple интеграцию Live Activity в постоянно включенный дисплей, который, вероятно появится в следующем айфоне.

6️⃣ Общий код для приложения и виджета.
Live Activity очень похожа на виджет: UI должен находиться в расширении виджета вашего приложения.

7️⃣ Проблема с доступностью виджета на разных осях.
Если у вас есть существующие виджеты и вам пока не требуется iOS 16, обходной путь — добавить вторую цель расширения виджета только для Live Activity.

📖 Более подробно о выводах автора статьи можно прочесть здесь.

@iOS Dev
Алгоритм Дейкстры в Swift, используя GameplayKit. Погодите, что?!

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

Примеры задач, которые можно решить с помощью данного алгоритма:

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

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

📖 Федерико Занетелло в одной из своих статей обратил внимание на то, что иногда для решения сложных задач можно пойти по нестандартному пути (кратчайшему, я бы сказал😅).

Что умеет GameplayKit?

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

Пожалуй, вы уже видите, куда клонит автор?

🛠 С помощью подкласса для GKGraphNode и нескольких строк кода автор покажет, как можно реализовать нахождение кратчайшего пути и использовать в вашем коде.

🛠 Сам проект также опенсорсный и находится здесь.

P.S. Заголовок материала показывает не всю суть, так как GameplayKit внутри может использовать и алгоритм Форда-Беллмана. Спасибо автору, который об этом также указывает.

И ещё один полезный вывод от Федерико заключается в том, что использовать коробочное решение иногда лучше, так как, например, GameplayKit поддерживается инженерами Apple постоянно, а наши с вами ресурсы не бесконечны.

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

@iOS Dev
Традиционное исследование зарплат от Хабр Карьеры

😎 И кто тут у нас лидер?

Краткие выводы исследования

🟢 Архитекторы ПО в среднем зарабатывают больше остальных, 285 000 ₽. А вот мобайл на втором месте, средняя зарплата 171 000 ₽.

🟢 По языкам программирования пальму первенства перехватил Objective-C со средней зп в 250 000 ₽. По Swift динамика не изменилась, согласно исследованию коллеги получают 200 000 ₽.
На Kotlin и Java такого разброса, к слову нет, там 185к и 180к, соответственно.

Самые щедрые на зп среди компаний РФ — SkyEng, Avito, Mail ru group.

Больше всего выросли зарплаты у архитекторов ПО (+13%), а упали в геймдеве (-8%).

Зарплата выросла в большинстве городов. Ощутимый рост был в Красноярске (+33%), Волгограде (+25%) и Перми (+20%). В Питере и Омске зарплаты не изменились😔.

@iOS Dev — о важном
Сортировка данных с помощью KeyPathComparator в iOS 15

😉 Скорее всего, для сортировок вы чаще используете sorted(by:), так как KeyPathComparator был добавлен в Foundation в iOS 15 и macOS 12 (а у кого-то на проекте поддерживается явно больше двух последних версий iOS, и юзать available накладно).

💵 Вдохновившись вчерашним постом, я решил показать пример, в котором мы задействуем KeyPathComparator.

Нам достаточно указать только keyPath, по которому наши значения будут сравниваться с помощью SortComparator.

Используя два компаратора, мы отсортируем разработчиков сначала по их уровню скилла, а затем по зарплате. А .reversed в примере нужен для сортировки по убыванию.

В результате получится следующее:

Senior 350000
Senior 300000
Middle 250000
Middle 220000
Junior 200000
Junior 120000
Junior 100000


🧐 В целом, использование очень похоже на NSSortDescriptor, который использовался для сортировки NSArray и NSMutableArray.

@iOS Dev
Как получить все слова из заданной строки?

Решению этой задачи могут помешать пунктуационные знаки: запятые, точки и не только. И тогда можно воспользоваться расширением выше.

.punctuationCharacters — здесь представлены все непробельные символы, используемые для разделения языковых единиц, таких как точки, тире, круглые скобки и т. д.

@iOS Dev
Подборка материалов для подготовки к собеседованиям

Ключевые темы этого поста: память, ссылки, side table и многое другое.

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

🗒 Для удобства разбил на два блока — русскоязычный и англоязычный, пост планирую расширять и обновлять.


🇷🇺 Материалы на русском языке

🔗 Как устроен счётчик ссылок в Swift?

🔗 Память в Swift от 0 до 1

🔗 Swift 4 - слабые ссылки

🔗 Память в Swift: стек, куча, ARC


🏴󠁧󠁢󠁥󠁮󠁧󠁿 Материалы на английском языке

🔗 Advanced iOS Memory Management with Swift: ARC, Strong, Weak and Unowned Explained

🔗 Value Types and Reference Types in Swift

🔗 ARC and Memory Management in Swift

🔗 Discover Side Tables - Weak Reference Management Concept in Swift

🔗 A deep dive into Swift reference counting

🔗 Weak self, a story about memory management and closure in Swift (резюме по статье - здесь)

🔗 Memory Management in Swift: Understanding Strong, Weak and Unowned References

🔗 О ловушках в замыканиях

🔗 Memory layout in Swift (материал разбит на два блока, резюме — здесь)

🔗 Вам не (всегда) нужно использовать [weak self]

🔗 Погружение в управление памятью в Swift


Способы для поиска утечек памяти и отладки таких моментов

🔗 Простой способ обнаружить retain cycle в UIViewController

🔗 Everything you need to know about Memory Leaks in iOS

🔗 3 Different Techniques to Find Memory Leaks in iOS

Конечно, многие из статей затрагивают общие моменты, но посмотреть на что-то под иным углом не помешает.

Лучшее спасибо — 👍❤️🔥👏🎉❤️‍🔥.

😃 iOS Dev🐱 Доступ к необычным эффектам
Please open Telegram to view this post
VIEW IN TELEGRAM
Разбор принципов RunLoop на примере создания своей собственной командной оболочки для macOS
Отличный материал для чтения в воскресенье того, чтобы отложить до понедельника

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

📖 В этом посте рассматривается, как работает RunLoop и приводится пример создания командной оболочки (он же shell или шелл) для наглядности.

Одним из наиболее распространенных случаев цикла событий является REPL (Read Eval Print Loop). И, вероятно, одним из наиболее часто используемых REPL являются оболочки (bash, zsh, fish, в зависимости от того, что вы предпочитаете).

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

В примере создаётся их аналог, который имеет только одну полезную команду (две, если считать exit), а именно выводит список файлов в текущем каталоге с помощью ls.

В той же macOS мы получаем объект RunLoop с каждым потоком, независимо от того, как поток создается (через pthread или Thread). Кроме того, использование RunLoop не является обязательным, но ваш поток может создать его по запросу, если вам это нужно.

Почему стоит прочесть этот материал?

💡 С помощью наглядного примера объясняется, почему не рекомендуется запускать блокирующие задачи в основном потоке в ваших приложениях (как для macOS, так и для iOS). А ещё вы сможете детальнее изучить преимущества использования RunLoop.

🛠 Код из примера доступен на GitHub.

@iOS Dev
Как показать или скрыть Assistant Editor?

Используйте CTRL+OPTION+CMD вместе c клавишей Enter (кому предпочтительнее, Return).

#xcode #shortcuts

@iOS Devмы ведь используем не только CMD+SHIFT+O 😉
Коллекция простых одноэкранных приложений для демонстрации и обсуждения различных архитектурных подходов в iOS

🛠 В этом репозитории собрано несколько приложений, показывающих, как можно использовать ту или иную архитектуру на простых примерах.

К сожалению, обновлялся репозиторий довольно давно, но хуже он от этого стать не должен.

#opensource

@iOS Dev
🎉В iOS 16 beta 5 появился заряд батареи в процентах!

Невероятно, неужели в Apple наконец решились!

Процент заряда батареи отсутствовал на iPhone с Face ID из-за нехватки места по обе стороны от выемки, в которой находится аппаратное обеспечение камеры TrueDepth.

👏 Инновации, которых мы ждали!

😎 Функция процента заряда батареи, по-видимому, будет доступна на большинстве айфонов с чёлкой, но, похоже, ее нет на iPhone 12/13‌ mini, iPhone 11, ‌iPhone‌ XR и ‌iPhone‌ X, возможно, из-за недостатка пространства (ну могли бы и шрифт поменьше сделать).

@iOS Dev
Преобразование коллекций в Swift

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

При работе с ними очень часто приходится использовать один и тот же набор данных в течение последовательности операций и постоянно преобразовывать его в новые значения.

Например, мы можем загрузить некоторые данные в формате JSON, затем преобразовать их в массив словарей и, наконец, в коллекцию моделей.

📖 В этой статье рассматриваются некоторые стандартные библиотечные API, которые позволяют нам легко и эффективно преобразовывать коллекции.

@iOS Dev
UILabel не так прост, как кажется: разбор свойств, подходов к работе с атрибутами и два бонуса

Установка высоты строки UILabel уже немного сложнее, чем изменение цвета этого лейбла.

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

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

🛠 Код на GitHub.

@iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
Что мы ждём от Apple в скором будущем?

Не секрет, что уже давно ходят слухи про разработки шлема дополненной реальности от яблочной компании, а тот же RoomPlan — лишнее подтверждение.

😳 Небольшой #оффтоп. На видео пример использования Magic Keys — это приложение дополненной/смешанной реальности для Oculus Quest, которое должно научить вас простым фортепианным пьесам и техникам всего за несколько минут.

Благодаря очень доступной системе трехмерной нотации, подобной той, что используется в Guitar Hero, пользователи могут воспроизводить простые пьесы за считанные минуты без необходимости читать ноты.

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

🔗 По ссылке больше примеров использования.

@iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
Воспроизводим поведение battery indicator из беты iOS

📺 Увидел твит, в котором наш коллега реализовал подобное, и что-то знаете, не слишком понравился шрифт, поэтому я решил попытаться воспроизвести такое же поведение уже с более корректным шрифтом.

Для этого использовал связку из двух вьюх (и двух лейблов), автолэйаут + SF-символ батарейки в качестве фона.

Ставьте 👍, если получилось похоже 😅.

@iOS Dev