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

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

#ios #mobile #swift
加入频道
Сортировка данных с помощью 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
Реализация чата в реальном времени с помощью Firebase + MessageKit

Cоздание, вёрстка и достижение плавного скролла задача далеко не из самых лёгких и требует целого арсенала навыков.

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

Yusuf Tör, будучи автором, проведёт вас через несколько важных шагов:

Настройка Firebase Account.

Выбор между Firestore и Realtime Database.

Настройка интерфейса.

Создание и отправка сообщений.

Синхронизация (в моём проекте это одна из самых важных задач по очевидным причинам).

@iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
Использование TimelineView для поворота фигур

TimelineView, представленный в iOS 15, можно использовать для изменения объектов с течением времени.

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

Вращение можно комбинировать вместе с изменением размера фигуры и вращением в 3D-пространстве для создания интересных эффектов.

@iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
Поэтапное руководство по кастомным переходам для UIViewController в Swift

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

📖 В этой статье идёт речь о том, как реализовать кастомный переход между двумя ViewController, анимируя CollectionViewCell в ImageView. На гифке пример того, как это выглядит.

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

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

Если вы будете следовать инструкциям шаг за шагом, все должно быть довольно гладко.

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

Автор материала признаётся, что вдохновлялся Airbnb для iOS и в основном пытался сделать ту же анимацию, что и при открытии экрана «Experience» (на вкладке «Explore»).

🛠 Проект с итоговым результатом находится на Github.

@iOS Dev
Лёгкий способ определить доминирующий язык в исходном тексте
Или как подкинуть идею сделать приложение для полиглотов в качестве пет-проекта

Для фреймворка Natural Language эту задачу выполняет NLLanguageRecognizer.

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

💡 Чтобы сгенерировать несколько возможных прогнозов, используйте метод languageHypotheses(withMaximum:).

One more thing

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

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

recognizer.languageConstraints = [.french, .russian, .german, .italian]

recognizer.languageHints = [.french: 0.5, .russian: 0.9, .german: 0.8, .italian: 0.6]

let constrainedHypotheses = recognizer.languageHypotheses(withMaximum: 2)
print(constrainedHypotheses)


@iOS Dev — is it some reebok or some nike?
Реализация и тестирование фичи Shared with You в iOS 16

В iOS 16 появилась функция Shared with You, позволяющая демонстрировать контент, которым поделились в Messages, внутри вашего приложения.

Пользователи смогут найти контент, который они могли бы потерять в длинной переписке. Такие приложения, как Photos, Music и Podcasts, уже реализовали поддержку, теперь пришло время добавить ее в ваши приложения.

Shared with You сопоставляет контент, которым поделились с URL на основе универсальных ссылок.

📖 В статье об этом говорится более подробно, рассматривается реализация, тестирование и то, когда можно ожидать появления общих URL-адресов.

@iOS Dev
Потокобезопасность (Thread Safety) в Swift

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

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

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

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

@iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
Как временно скрыть экран вашего приложения
Научитесь скрывать конфиденциальную информацию при переключении приложений.

📖 В этом коротком руководстве рассматривается, как временно перекрыть весь экран вашего приложения кастомным UIView.

В целом это решение имеет два основных варианта использования:

1️⃣ Затемнение фона для отображения всплывающего контента (речь про pop-over).

2️⃣ Скрытие контента при переключении между приложениями. Может пригодиться, чтобы скрыть потенциально конфиденциальную инфу или просто показать пользователю что-то любопытное.

Оба кейса по факту работают одинаково, но код для отображения и скрытия вьюх отличается.

@iOS Dev
Почему ваша картинка размером в 2 мегабайта может отъедать 80 мб памяти? Сейчас разберёмся.
Или как пофиксить одну из причин out of memory exception

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

Одна из потенциальных сложностей, с которой можно столкнуться при такой задаче — out of memory exception. Так в чём же дело?

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

Главное, что нужно запомнить, использование памяти ≠ размеру файла. И вот почему.

Использование памяти связано с размерами изображения, а не с размером файла (Session 416, WWDC 2018).

Всё дело в том, что для отображения изображения на экране, iOS сначала необходимо декодировать и распаковать изображение. Обычно 1 пиксель декодированного изображения занимает 4 байта памяти — 1 байт для красного, 1 байт для зеленого, 1 байт для синего и 1 байт для альфа-канала (да-да, тот самый RGB с альфой). Например:

(3648 * 5472) * 4 bytes ≈ 80MB

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

Что со всем этим делать?

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

Одно из решений, которым делятся инженеры Apple — юзать даунсэмплинг.

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

Флаги, которые можно использовать

1️⃣ kCGImageSourceShouldCache — когда для этого флага установлено значение false, мы сообщаем основному фреймворку, что нам нужно только создать ссылку на источник изображения и не хотим декодировать изображение сразу при создании объекта CGImageSource.

В ситуации, когда у вас нет доступа к пути к источнику изображения, вы можете создать объект CGImageSource, используя инициализатор CGImageSourceCreateWithData().

2️⃣ kCGImageSourceShouldCacheImmediately — этот флаг указывает, что декодировать изображение нужно именно в тот момент, когда мы запускаем процесс понижения дискретизации.

3️⃣ kCGImageSourceCreateThumbnailWithTransform — установка этого флага в значение true очень важно для сохранения исходной ориентации.

Подводные камни (а как же без них)

Имейте в виду, что даунсэмплинг — это процесс, который потребляет ресурсы процессора. Таким образом, по-прежнему предпочтительнее использовать правильно масштабированный источник изображения, а не понижать дискретизацию HD-изображения. Другими словами, вы должны использовать даунсэмплинг только тогда, когда вам нужно отобразить изображение, размер которого намного превышает требуемый размер на экране.

Важные моменты

Помните, что память — это конечный и общий ресурс.

Используйте встроенный в Xcode мониторинг.

Позвольте iOS выбрать ваши форматы изображений, когда это возможно.

Используйте ImageIO для понижения разрешения изображений (помните про подводные камни).

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

Не игнорируйте графики памяти (memory graphs), чтобы лучше понять, что происходит.

Что почитать ещё?

📖 Deep Dive into iOS Memory.
📖 Reducing Memory Footprint When Using UIImage.
📺 Session 416, WWDC 2018.
🔗 https://developer.apple.com/documentation/imageio/cgimagesource.

@iOS Dev — отвечаем на вопросы.
Background Modes в Swift: терминология, настройка и пример приложения

Apple начала разрешать приложениям выполнять работу в фоновом режиме в далёком 2010 году с выходом iOS 4 и с тех пор развивала и улучшала фоновые режимы.

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

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

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

1️⃣ Воспроизведение аудио.

2️⃣ Получение обновлений местоположения.

3️⃣ Выполнение критических задач фиксированной продолжительности.

4️⃣ Фоновая загрузка: выполнение фоновых обновлений по расписанию, определяемому iOS.

@iOS Dev