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

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

#ios #mobile #swift
加入频道
Использование кортежей в Swift на примере switch/case

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

Каждый элемент кортежа может проверяться на разное значение или интервал значений.

В качестве альтернативы можно использовать символ подчеркивания (_) для поиска любого возможного значения.

В приведенном ниже примере берется точка (x, y), выраженная как простой кортеж типа (Int, Int), и классифицируется на графике, который следует за примером.

let somePoint = (1, 1)
switch somePoint {
case (0, 0):
print("\(somePoint) в начале координат")
case (_, 0):
print("\(somePoint) на оси x")
case (0, _):
print("\(somePoint) на оси y")
case (-2...2, -2...2):
print("\(somePoint) внутри рамки")
default:
print("\(somePoint) за пределами рамки")
}
// Выведется "(1, 1) внутри рамки"

Оператор switch определит, находится ли точка в начале координат (0, 0), на красной оси x, на зеленой оси y, внутри синей рамки 4 на 4 с центром в начале координат или за ее пределами.

😉 В отличие от языка C, Swift позволяет в switch/case рассматривать одно и то же значение или интервал значений.

Фактически, точка (0, 0) может соответствовать всем четырем вариантам в этом примере.

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

@iOS Dev
👍21👏7🔥5🤯1
Продвинутые координаторы в iOS

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

Как и когда использовать дочерние координаторы?

Как быть с навигацией «Назад»?

Как передавать данные между контроллерами?

Как работать с координаторами при наличии таббара?

Как работать с segues?

Как вместо этого использовать протоколы или замыкания?

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

@iOS Dev
👍22🔥3🤩1🙏1
🎉 В iOS 16 появилось API для обновления текущей ориентации интерфейса!

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

Для этого достаточно будет использовать новый метод:

requestGeometryUpdate(.iOS(interfaceOrientations: .portrait))

👨‍💻 Обратил внимание на это Simon B. Støvring.

@iOS Dev
👍26🔥5🎉2👏1
Что нового в MapKit в iOS 16?

MapKit — это фреймворк для отображения Apple Maps в вашем приложении. Это помогает разработчикам обеспечить поддержку навигации и многое другое.

Что же поменялось?

Новый UI — это совершенно точно изменит пользовательский опыт с 3D: не только зданиями, но и картой в целом.

Конфигурация карты. Теперь нужно использовать MKStandardMapConfiguration, MKHybridMapConfiguration или MKImageryMapConfiguration.

Улучшили оверлэй. В iOS 16 оверлеи теперь также будут отображать 3D-здания, при этом они будут скрыты при просмотре в 2D.

Режимы наложения. Вы можете затемнить остальную часть карты, чтобы сфокусироваться на нужном участке.

Look Around. Наконец-то Apple предоставила свой Look Around API для использования в наших приложениях. С ним доступен MKLookAroundSceneRequest, который принимает координаты для поиска участка LookAround. Когда он будет создан, вы можете инициализировать MKLookAroundViewController с указанием местоположения.

Что можно прочесть на эту тему?

📖 Описание фреймворка на сайте Apple.
📖 Статья с разбором фич.

🛠 Пример демо-приложения.

@iOS Dev
👏12👍8🤩2❤‍🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
😲 Посмотрите, какую красоту можно сделать с помощью эффекта увеличения в SwiftUI!

@iOS Dev
🤩90🔥26😍8👍7❤‍🔥4🎉2👏1
This media is not supported in your browser
VIEW IN TELEGRAM
Как добавить фото или видео на симулятор?

Есть два способа добавить мультимедиа в системное приложение Photos.

1️⃣ Если вам просто нужно быстро добавить медиафайлы в симулятор, вы можете просто перетащить медиафайл из любого места на вашем Mac в симулятор.

2️⃣ Воспользуйтесь командой xcrun simctl addmedia SIMULATOR_UUID|booted ~/path/to/file/test.jpg

Здесь path это путь к вашему файлу, а test.jpg это его название.

@iOS Dev
🔥21👍111❤‍🔥1👏1
Простой способ понять код ошибки от сервера при выполнении запроса

😎 Для этого можно воспользоваться HTTPURLResponse.

Это подкласс URLResponse, который предоставляет методы для доступа к информации, относящейся к ответам протокола HTTP.

Всякий раз, когда вы отправляете HTTP-запросы, любые объекты ответа, которые вы возвращаете из URLSession, NSURLConnection или NSURLDownload, будут экземплярами класса HTTPURLResponse.

В свою очередь, у него есть нужный нам метод.

localizedString(forStatusCode:)

Текст кода ошибки будет соответствовать стандарту RFC 2616.

@iOS Dev
🔥21👍10❤‍🔥3👏2
Более короткий синтаксис для работы с опциональными строками

Опциональные строки очень часто встречаются в коде Swift, например, многие объекты из UIKit отображают текст как «String?»

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

Хотя оператор nil-coalescing (например, ??) является отличным способом достижения этой цели, определение переменной типа orEmpty может значительно помочь в том, чтобы сделать наш код чище.
🔥34👍8❤‍🔥3🤔3😱3👏1
Какой алгоритм использует Swift для sort()?

💡 Этот вопрос из тех, которые вряд ли вы себе могли бы задать в пятницу, но если вам интересно, то внутри реализации алгоритма используется следующее:

1️⃣ Если менее, чем 20 элементов, то применяется сортировка вставками (insertion sort). В комментариях в коде уточняется, что именно этот тип лучше подходит для небольших областей.

2️⃣ Интроспективная сортировка (Introsort), включающая в себя быструю сортировку до определённой глубины рекурсии 2*floor(log(N)).

3️⃣ И переключается на пирамидальную сортировку (она же heapsort или сортировка кучей), когда глубина рекурсии превысит заранее установленный уровень.

Больше деталей в коде swift.

@iOS Dev — теперь вы, возможно, знаете больше😅
❤‍🔥42👍135👏3🤯2
Упрощение внедрения зависимостей с помощью паттерна «Фасад» в iOS

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

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

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

📖 Эта статья предлагает отличную комбинацию двух паттернов проектирования (Facade и Dependency Injection).

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

@iOS Dev
👍19🔥5
Chisel — набор команд LLDB для помощи в отладке iOS-приложений

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

Для LLDB есть возможность импортировать подключаемые модули, что может значительно расширить возможности отладки. Chisel, инструмент, который содержит множество плагинов lldb — например, команду border, которая добавляет яркую рамку к UIView, чтобы вы могли быстро найти его на экране, и все эти плагины работают благодаря умному использованию команд e/po.

Несколько примеров команд, кроме border:

🟢 pviews — рекурсивно просматривает и выводит описание для key window.

🟢 visualize — можно открыть UIImage, CGImageRef, UIView, CALayer, NSData (для картинки), UIColor, CIColor, или CGColorRef в Preview.app на вашем маке.

🟢 fv — ищет вьюху в иерархии, чьё имя класса соответствует заданной регулярке.

🟢 presponder — выводит всю responder chain, начиная с данного объекта.

🟢 и много чего ещё.

Кстати, ещё с помощью Chisel можно пилить собственные команды и использовать их для отладки.

🛠 Ссылка на #opensource проект: Github.

Делюсь также и двумя крутейшими статьями про LLDB, благодаря одной из которых я и узнал об этом инструменте:

📖 Расширенные приемы lldb для Swift — внедрение и изменение кода на лету.

📖 Танец в отладчике - вальс с LLDB. Пусть материал вышел и давно, но всё ещё может быть нам полезен.

👍 Рекомендую прочесть и сохранить себе в избранное.

@iOS Dev
👍34🔥7❤‍🔥31
Посетитель или же Visitor — это один из паттернов, описанных в учебнике «Банды четырех», под названием «Design Patterns: Elements of Reusable Object-Oriented Software».

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

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

📖 Данный материал предназначен для знакомства с этим приемом. Автор подчёркивает, что знает о недостатках кода и возможностях его улучшения.

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

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

@iOS Dev
👍19🔥3👏21
Создание переиспользуемой системы для сложных URL-запросов с помощью Swift

📖 В статье описывается, как обрабатывать элементы запроса, HTTP-заголовки, тело запроса и многое другое простым декларативным способом.

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

Foundation имеет встроенный механизм для этого — URLComponents с его свойством queryItems, но может оказаться довольно хлопотно каждый раз настраивать это для каждого запроса.

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

@iOS Dev
👏14👍10❤‍🔥2🎉1🤩1
😁16👍10🔥3🤯3❤‍🔥2🙏2
iOS Dev
Photo
Каким будет результат выполнения со скриншота выше?
Anonymous Quiz
1%
3
55%
2
18%
1
1%
0
2%
nil
13%
Код не скомпилируется
10%
Будет ошибка Index out of bounds
🤔37🔥9👍8🤯4😱4❤‍🔥2😁1🤩1
iOS Dev
Каким будет результат выполнения со скриншота выше?
Вопрос со скриншота не такой простой на первый взгляд, как кажется

😉Но и для этого есть объяснение, всё дело в том, что:

После dropFirst() у нас будет не Array, а ArraySlice. Тип ArraySlice позволяет быстро и эффективно выполнять операции над разделами большего (исходного) массива.

Вместо копирования элементов среза в новое хранилище, экземпляр ArraySlice представляет собой вид на хранилище исходного массива.

А поскольку ArraySlice представляет тот же интерфейс, что и Array, вы можете выполнять над срезом те же операции, что и над исходным массивом.

Это означает, что элемент по индексу 0 в ArraySlice — это тот же элемент по индексу 0 из исходного массива.

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

Это происходит потому, что ArraySlice не содержит элемента с индексом 0 исходного массива, а только элементы с индексами 1 и 2.

Если мы хотим получить первый или последний индекс получившегося фрагмента безопасным способом, мы должны использовать startIndex и endIndex. Ну, ещё можно использовать Array для доступа к нужному элементу (кому как больше нравится).

📖
Кстати, есть отличная статья, в которой рассматривается больше деталей.

@iOS Dev
👍74🔥15🤯14👏2
Два способа сохранить картинку в галерею на устройстве

🟢 Первый способ — используем метод времён Objective-C.

UIImageWriteToSavedPhotosAlbum(image: UIImage, completionTarget: Any?, completionSelector: Selector?, contextInfo: UnsafeMutableRawPointer?)

🟢 Второй способ связан с использованием PHPhotoLibrary.

Добавьте ключ NSPhotoLibraryAddUsageDescription (нужен для записи в галерею, не для чтения или изменения) в Info.plist и воспользуйтесь creationRequestForAsset для вашего UIImage:

PHPhotoLibrary.shared().performChanges {
_ = PHAssetChangeRequest.creationRequestForAsset(from: image)

} completionHandler: { (success, error) in

}


Если у вас есть доступ к URL-адресу, то можно использовать creationRequestForAssetFromImage(atFileURL: imageUrl), где imageURL - адрес нашего изображения.

А если нужно сохранить видео, то используйте creationRequestForAssetFromVideo(atFileURL: videoUrl)

@iOS Dev
👍22🔥5❤‍🔥3👏2
👍 Apple анонсировали серию презентаций с вопросами и ответами на тему App Store

Обещают рассказать, как максимально эффективно использовать функции App Store.

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

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

Требование: наличие девелоперской учетки.

Узнать больше: тут.

Зарегистрироваться: здесь.

Будет точно полезно инди-разработчикам и маркетологам.

@iOS Dev
🔥9👍7❤‍🔥2👏1
NSPredicate в Swift: определение, примеры и один интересный факт

Предикаты используются при построении поискового запроса или для фильтрации в памяти с помощью определения логических условий.

Хотя предикаты принято создавать непосредственно из экземпляров NSComparisonPredicate, NSCompoundPredicate и NSExpression, часто предикаты создаются с помощью обычных (форматных) строк.

Рассмотрим некоторые способы задания предикатов.

Простые сравнения. Пример: jobTitle == "Team Lead" или channelName == "iOS Dev".

Поиск без учета регистра и диакритических знаков, например, name contains[cd] "Bruce".

💡Интересный факт: здесь c это case-insensitive (без учёта регистра), а d - diacritic insensitive (игнорим диакритический знак, то есть если в поиске будет два символа c и ç, они попадут в условие).

Логические операции, например firstName like "Ivan" или lastName like "Ivanov".
Нельзя не уточнить, что like сработает как == для этого условия.

Ограничения временного диапазона, например, date between {$YESTERDAY, $TOMORROW}.

Относительные условия, например, group.name like "work*".

Агрегатные операции, например @sum.items.price < 1000.

БОНУС

🟢 Ключевое слово MATCHES можно использовать для поиска с помощью регулярки.
Пример: NSPredicate(format: "name MATCHES %@", query).

🟢 А для поиска строк, начинающихся или заканчивающихся заданным условием, пригодятся BEGINSWITH и ENDSWITH.

📖 Полный справочник по синтаксису можно посмотреть в документации.

📖 Вы также можете создавать предикаты, включающие переменные, используя метод evaluate(with:substitutionVariables:), чтобы предварительно определить предикат перед заменой конкретных значений в рантайме.

@iOS Dev
👍28🔥8❤‍🔥4👏1
🎉 Live Activities доступны в iOS 16 beta 4

Live Activities помогают людям следить за тем, что происходит в вашем приложении в режиме реального времени, прямо с экрана блокировки. Теперь вы можете начать работу с Live Activities и новым фреймворком ActivityKit, который достепен в beta 4 iOS 16.

Пример использования

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

‼️ Обратите внимание, что Live Activities и ActivityKit не будут включены в первый публичный релиз iOS 16.

Отправлять приложения, включающие Live Activities, можно будет позже.

@iOS Dev
👍14🔥4🤩21
Как улучшить отклик приложения: 10 советов от инженеров Apple

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

Приложения с зависаниями (задержками отклика) или дёрганым поведением на экране разрушают эту иллюзию.

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

100 мс — это максимальная отсечка для задержек при непосредственном взаимодействии с пользователем. Более короткая задержка редко заметна.

5 мс — это порог для достижения плавного скролла на экране.

Для непрерывного скролла новый фрейм должен быть готов каждый раз при обновлении экрана. На устройствах Apple это может происходить 120 раз в секунду, или каждые 8,3 мс. В зависимости от системных условий и задач в приложении, у вас может не быть полных 8,3 мс для подготовки следующего обновления экрана.

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

1️⃣ Избегайте зависаний, освобождайте основной поток от работы, не связанной с пользовательским интерфейсом.

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

3️⃣ Избегайте слишком большого количества потоков.
Dispatch и OperationQueue поддерживают внутренний пул рабочих потоков, настроенных на емкость и нагрузку устройства. Используйте эти технологии вместо создания собственных фоновых потоков для сохранения баланса.

4️⃣ Избегайте лагов, сводя к минимуму время обновления для view.
Чтобы обеспечить плавную анимацию, которая выглядит как непрерывное движение, устройства Apple обновляют экран до 120 раз в секунду. Когда ваше приложение находится в foreground (на переднем плане, кому как привычнее), код отрисовки в основном потоке должен быть завершен до того, как потребуется следующий фрейм, чтобы избежать пропуска кадров и появления рывков.

5️⃣ Оптимизируйте свое приложение для переменной частоты обновления.
Если ваше приложение напрямую взаимодействует с графической системой, например, когда вы выполняете собственный рендеринг, помните о дисплеях с переменной частотой обновления.

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

7️⃣ Ищите зависания и потенциальные риски, которые могут к этому привести.

8️⃣ Попробуйте найти сами причины зависаний. Обратите внимание на Thread State Trace instrument.

9️⃣ В целом чаще используйте Instruments для обнаружения узких мест приложения.

🔟 Уделяйте внимание метрикам и отчётам непосредственно от приложения.

@iOS Dev — делюсь советами не только для плавного скролла😅
🔥20❤‍🔥7👍6😁1🤯1