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

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

#ios #mobile #swift
加入频道
This media is not supported in your browser
VIEW IN TELEGRAM
Когда скопировал два решения со StackOverflow

На самом деле это решение от изобретателя с ником The Q (подозреваю, тут есть связь с Джеймсом Бондом).

По легенде, автор сломал колесо своего обычного байка. А после этого решил не выбрасывать его и распилил на две равные половины, после чего и собрал новую версию транспорта — «по формуле 1+0,5+0,5=2».

😅 Иногда хочется поделиться не только серьёзными вещами.

@iOS Dev
PhotosPicker: инструмент выбора фотографий с помощью SwiftUI и Transferable

📖 В этой статье рассказывается, как использовать новый SwiftUI PhotosPicker API, о котором было объявлено на одной из сессий #WWDC.

Новый SwiftUI PhotosPicker API доступен на всех платформах:

iOS (16.0+)
iPadOS (16.0+)
macOS (13.0+)
watchOS (9.0+)

Больше не нужно использовать UIViewControllerRepresentable для обертывания PHPickerViewController или его старой версии UIImagePickerController.

Также приложению не нужно запрашивать доступ к библиотеке, чтобы использовать его.

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

Для внедрения нужны два шага:

1️⃣ Использовать PhotosPicker для получения одного или нескольких экземпляров PhotosPickerItem.
2️⃣ Загрузить данные об объекте с помощью PhotosPickerItem.loadTransferable.

@iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
Использование StoreKit для продвижения ваших приложений

💡Поделюсь советом для тех, у кого есть несколько пет-проектов или для компаний, которые интересуются возможностью кросс-промо😉.

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

Есть целый ряд опций, как это сделать — получить список продуктов, кастомный лейаут для каждого, вбить название и добавить кнопку со ссылкой, например. Можно сделать проще со StoreKit, а точнее, с SKOverlay.

Ниже пример (можете написать свой):

func displayOverlay() {
guard let scene = view.window?.windowScene else { return }

let config = SKOverlay.AppConfiguration(appIdentifier: "APP_ID", position: .bottom)
let overlay = SKOverlay(configuration: config)
config.userDismissible = false
overlay.present(in: scene)
}


В этом коде APP_ID — числовой идентификатор в аппстор.

One more thing, если баннер не должен скрываться по свайпу:

config.userDismissible = false

Специально для @iOS Dev.
Продолжаю делиться находками с #WWDC и iOS 16

🙁 Раньше, чтобы получить путь к файлу в папке приложения, приходилось использовать API FileManager, что выглядело довольно громоздко.

🙂 Теперь мы можем получать пути к системным папкам непосредственно из свойств URL.

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

@iOS Dev
Семантика версионирования для Swift Package и не только

Представьте, что мы используем библиотеку из популярного пакета Swift. Что случится, если выпустят новую версию с огромными изменениями в ее публичном API? Наш код может сломаться. Чтобы избежать этой проблемы, мы могли бы полагаться на единственную версию. Хуже, если каждый владелец пакета имеет свой способ работы с версиями. Такие сценарии называются адом зависимостей (dependency hell).

Семантическое версионирование - это спецификация, призванная положить конец аду зависимостей. Она разделяет версии на три числа: major, minor и patch (например, 1.5.8). Вот что означает каждый номер:

🔵 Major — публичный API изменился, что требует обновления нашего кода.
🔵 Minor — в общедоступный API был добавлен новый код, который не нарушает существующие интеграции (обратная совместимость).
🔵 Patch — были исправлены ошибки без изменения публичного API.

📖 Здесь понятно объясняется, почему нужно делать именно так на примерах.

@iOS Dev
Как отменить асинхронную задачу в Swift?

💡Один из возможных способов — использование DispatchWorkItem.

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

@iOS Dev
‼️ Сегодня 30 июня, а значит, что пора наконец уже реализовать в ваших приложениях удаление профиля, если вы этого ещё не сделали.

В целом, ситуация не выглядит сложной, если вы используете решения, в которых нет Sign In от Apple или же у вас собственный сервер для этого 😅.

Например, в одном из моих приложений используется как раз связка Sign In + Firebase, и, как оказывается, разработчики ещё не реализовали отзыв токена. К слову, iOS тоже такого инструмента не предоставляет, нужно генерить JWT и отзывать его только с помощью сервера.

Вероятно, в будущем или Google, или Apple уже упростят нам жизнь. А пока что можно воспользоваться решением из треда Firebase, или же от Ивана:

👏 Вот пост, который может пригодиться (как минимум, натолкнёт на правильный ход мыслей).

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

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

❤️ Слежу за развитием событий, ваш @iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
RoomPlan в iOS 16 — 3D-планы этажей в ваших приложениях

Это новый API Swift, работающий на базе ARKit, использует камеру и сканер LiDAR на iPhone и iPad. Теперь ваши приложения могут создавать трехмерные планы этажей, включая ключевые характеристики, такие как размеры и типы мебели.

Фреймворк использует датчики устройства, ML-модели и RealityKit для захвата физического окружения. Например, фреймворк просматривает записи с камеры устройства и показания LiDAR и определяет стены, окна, проемы и двери. RoomPlan распознает особенности помещения, мебель и технику, например, камин, кровать или холодильник, и передаёт данные в приложение.

Для захвата используется RoomCaptureView. Есть виртуальные подсказки по мере перемещения по комнате:

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

Если фреймворк требует определенного вида движения или ракурса, UI покажет инструкции, как расположить устройство.

🛠 Пример кода (нужен Xcode 14).

@iOS Dev
Полное руководство по использованию таймеров в Swift
О создании, повторениях и не только.

Класс Timer в Swift - это гибкий способ планирования будущих задач, как однократно, так и многократно.

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

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

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

@iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
2 000 iOS-разработчиков в канале

Невероятно, amazing, как это вообще возможно?!

🛠 Поделюсь своим рецептом: 400 постов, 15 публикаций на хабре, 12 статей в телеграфе, одна проведённая трансляция #WWDC и время, потраченное на разборы новинок и не только.

Но всё это не имеет значения, если бы вы не читали этот канал. Поэтому — спасибо, коллеги! ❤️

Наш путь продолжается, туториалы, хаки, фишки Xcode и не только — в канале @iOS Dev

👍❤️🔥👏🎉 - вы знаете, что с этим делать😅

Чуть не забыл, помните небольшую традицию в этом канале? Гифка, как обычно, использует какой-то не совсем обычный компонент, на этот раз вы можете посмотреть реализацию здесь.
This media is not supported in your browser
VIEW IN TELEGRAM
Построение 3D-диаграмм с помощью SceneKit и SwiftUI

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

Автор же этого материала пошёл дальше, и уделил своё внимание построению 3D круговых диаграмм с помощью SceneKit.

Это еще и хороший повод взглянуть на несколько других аспектов фреймворка.

📖 Даже абстрагируясь от SwiftUI, в статье можно прочесть про использование математики для построения путей и расширить свои знания о применении UIBezierPath.

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

Пол Хадсон — создатель книги «Hacking with Swift». Он также является редактором Swift Developer News, сопровождающим Swift Knowledge Base и выступает на Swift-мероприятиях по всему миру.

1️⃣ Технологии будут меняться, поэтому не зацикливайтесь на одном языке или фреймворке.
2️⃣ Вы не сможете запомнить все, что узнаете, или даже 10% от этого.
3️⃣ Вам не нужна степень в области компьютерных наук, но фундаментальные знания необходимы.
4️⃣ Вы всегда будете учиться, и если вы примете это, то станете счастливее.
5️⃣ Вы должны учиться эффективно.
6️⃣ Немного математики не помешает.
7️⃣ Вам нужна стойкость, чтобы бороться с проблемами, с которыми вы столкнетесь.
8️⃣ Наша работа — это не только код.

@iOS Dev
В Swift 5.7 (и iOS 16) появились новые API для взаимодействия со временем, состоящие из трех основных компонентов: clock, instant и duration.

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

В примере на скриншоте мы используем свойство .now для получения текущего момента времени и добавляем duration для откладывания задачи на 10 секунд. Также можно указать tolerance, что позволит основным механизмам планирования слегка скорректировать время, если это необходимо для более энергоэффективного выполнения. Мы можем указать свойство часов одним из двух вариантов continuous или suspending.

ℹ️ Разница между continuous и suspending в том, что в первом случае часы непрерывны, а во втором приостановлены, пока система спит.

@iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
Повторение функциональности вкладки поиска в App Store

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

Можно дополнить свою базу знаний ещё одним примером использования UISearchController и UISearchResultUpdating.

🛠 Код из примера здесь. Предлагаемые результаты поиска будут работать только для одного приложения, но для понимания концепции этого должно хватить😎.

@iOS Dev
This media is not supported in your browser
VIEW IN TELEGRAM
Интерактивные анимации как в Spotify

Анимация — неотъемлемая часть современных мобильных приложений. Они дают пользователям обратную связь об их действиях и уведомляют о том, что происходит в приложении. Кроме того, анимации придают приложению более качественный вид и ощущение.

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

🛠 Пример тестового приложения на Github.

@iOS Dev
Помните серию реклам Mac против PC?

😅 Оказывается, что Apple продолжает шутить над Microsoft даже спустя столько лет.

Сегодня по случайному совпадению в стандартных SF Symbols наткнулся на забавную вещь. Факт заключается в том, что PC представлен именно так, как на скриншоте. Это не что иное, как стандартный синий экран, он же экран смерти на компах под управлением Windows 😉.

Если не верите, попробуйте вбить в поиск в SF Symbols запрос PC и получите именно такой результат!

@iOS Dev
Дженерики в Swift на примерах: что это и как использовать

💡 Дженерики в Swift позволяют писать обобщенный и многократно используемый код, избегая дублирования.

Вы, вероятно, уже пользовались их реализацией, поскольку они повсюду в стандартной библиотеке Swift.

⭐️ Вот несколько причин добавить этот пост в избранное:

Объяснение, что такое generics в Swift.

Примеры создания.

Ответ на вопрос, когда их лучше использовать.

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

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

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

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

@iOS Dev
Три способа добавить блюр-эффект на ваши изображения: хороший, плохой, злой
На самом деле второй тоже хороший

Первый способUIBlurEffect

Возможно, это самый стандартный из всех.

let view = UIView()
let blurEffect = UIBlurEffect(style: .light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
view.addSubview(blurEffectView)


Нужно помнить, что UIBlurEffect не является фильтром, из названия следует, что это всё-таки эффект, и может быть применён по факту к любой картинке (и любому UIView).

Второй способCIFilter

Apple предоставляет целый набор инструментов под названием CIFilter. Среди них есть CGaussianBlur, который отлично подходит для достижения задачи. Как часть UIKit, его также просто внедрить.

func addBlurTo(_ image: UIImage) -> UIImage? {
if let ciImg = CIImage(image: image) {
ciImg.applyingFilter("CIGaussianBlur")
return UIImage(ciImage: ciImg)
}
return nil
}


Третий способ — Гауссово сглаживание с ядрами.

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

Этот метод вызывает низкоуровневые техники, такие как свертка — например, vImageConvolve_ARGB8888.
В чем преимущество злого способа (злой - метафора, конечно)? Если вкратце, использование свертки и высокоскоростных ядер экономит время.
Много времени.


😉Ах да, кстати, разобрался с оплатой премиума в Телеге и теперь посты даже с картинками будут насыщеннее (не всегда). А ещё вы сможете поставить новые эмодзи (если у вас есть премиум).

@iOS Dev
Загрузка файлов в фоновом режиме с помощью URLSessionDownloadTask

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

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

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

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

Если приложение будет приостановлено (процесс приложения будет завершен) во время загрузки, а затем снова запущено, если загрузка все еще активна, вы сможете обратиться к URLSession с тем же идентификатором, и снова будут поступать уведомления о ходе загрузки.

Но если задача завершена, а приложение не запущено, система запустит приложение в фоновом режиме и вызовет метод AppDelegate handleEventsForBackgroundURLSession.

Это единственный способ получить уведомление о такой загрузке:

class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
os_log("handleEventsForBackgroundURLSession for %@", type: .info, identifier)
completionHandler()
}
}


💡 Это сложно дебажить, но можно подключиться через Debug > Attach to Process by PID or Name. Тогда ситуация с отладкой станет проще.

@iOS Dev