EasySwift iOS🍏 @swift_ioss Channel on Telegram

EasySwift iOS🍏

@swift_ioss


Все самое интересное в мире iOS разработки 🧑🏻‍💻

Предложить статью или новость: @EasySwiftBot

По всем вопросам обращаться к @itereznikov

EasySwift iOS🍏 (Russian)

EasySwift iOS🍏 - это канал, где вы найдете все самое интересное в мире разработки для iOS. Если вы разрабатываете приложения для устройств Apple или интересуетесь этой темой, то этот канал станет вашим незаменимым помощником. Здесь вы найдете актуальные статьи, новости, обзоры и советы от опытных разработчиков

Каждый день мы публикуем свежие материалы, которые помогут вам быть в курсе последних тенденций и новостей в мире iOS. Если у вас есть собственные идеи или хотите предложить статью для публикации, обращайтесь к @EasySwiftBot. Все вопросы также можно адресовать @itereznikov. Присоединяйтесь к нам и узнавайте все об iOS разработке первыми!

EasySwift iOS🍏

14 Feb, 07:01


Потоки под капотом: как работают многопоточность и синхронизация в iOS

Если хотели разобраться в многопоточности - статья для вас - все достаточно хорошо и понятно написано.

Ниже приведу пару тезисов.

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

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

⚙️ iOS предлагает инструменты, такие как GCD и Swift Concurrency, для управления потоками и задачами, обеспечивая оптимальное распределение ресурсов и упрощая разработку многопоточных приложений.

📊 Закон Амдала описывает, что ускорение программы, достигнутое за счет параллельной обработки, ограничено последовательными участками кода, которые не могут быть распараллелены.

EasySwift iOS🍏

12 Feb, 07:03


Network Link Conditioner: Simulating Slow Networking

👀 Если вы не знали как тестировать состояния сетевого соединения, то эта статья для вас.

Network Link Conditioner позволяет тестировать приложения в условиях медленной сети на macOS и iOS, предлагая профили, такие как 3G и Edge.

⚙️ На iOS Network Link Conditioner доступен в разделе инструментов разработчика в настройках, где можно выбрать предустановленный профиль или создать свой.

⚙️ Чтобы установить Network Link Conditioner на macOS, необходимо загрузить дополнительные инструменты для Xcode через меню Xcode и найти его в папке Hardware.

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

EasySwift iOS🍏

10 Feb, 07:04


How combine lists of Strings into natural and localized sentences in Swift

✏️ Класс ListFormatter позволяет объединять списки строк в читаемые предложения, учитывая локализацию пользователя.


// Используя joined
let languages = ["Swift", "Kotlin", "Rust"]

let joinedLanguages = languages.dropLast().joined(separator: ", ")
+ (languages.count > 1 ? " and " : "")
+ (languages.last ?? "")
// "Swift, Kotlin and Rust"

// Используя ListFormatter

let listFormatter = ListFormatter()
// "Swift, Kotlin, and Rust"
listFormatter.string(from: ["Swift", "Kotlin", "Rust"])


💡 Метод string(from:) класса ListFormatter преобразует массив элементов в строку, учитывая локаль, например, 'Swift, Kotlin y Rust' для испанского языка.

let listFormatter = ListFormatter()
listFormatter.locale = Locale(identifier: "es-ES")
// "Swift, Kotlin y Rust"
listFormatter.string(from: ["Swift", "Kotlin", "Rust"])


😮 ListFormatter может работать не только со строками, но и с любыми типами, которые могут быть представлены как строки, при этом пользовательские типы должны соответствовать протоколу CustomStringConvertible.

✔️ Метод formatted на массиве строк предлагает более лаконичный способ форматирования списков с дополнительными параметрами, такими как тип соединения (например, 'или' или 'и').

EasySwift iOS🍏

07 Feb, 07:00


Getting started with Core Image

Core Image — это мощный фреймворк для обработки и анализа изображений, разработанный Apple, который позволяет разработчикам применять фильтры и выполнять сложные манипуляции с изображениями в реальном времени.

➡️ Фреймворк состоит из трех основных компонентов: CIImage (представляет данные изображения), CIFilter (применяет эффекты) и CIContext (управляет рендерингом изображений).

🖥 Core Image предлагает широкий набор встроенных фильтров, которые можно комбинировать для создания сложных эффектов, а также возможность создания пользовательских фильтров с использованием языка Core Image Kernel или Metal.

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

EasySwift iOS🍏

05 Feb, 07:01


Model Inheritance in Core Data

🔗 Core Data позволяет разработчикам использовать модель наследования, что упрощает создание и управление данными, позволяя подчинённым сущностям наследовать свойства родительской сущности.

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

⚠️ Несмотря на преимущества, такая модель может привести к избыточности данных и снижению производительности при работе с большими объемами данных.

📌 Рекомендуется осторожно использовать модель наследования и рассмотреть возможность ручной реализации аналогичных эффектов для лучшей совместимости с SwiftData.

EasySwift iOS🍏

03 Feb, 07:00


XCTest Meets @MainActor: How to Fix Strict Concurrency Warnings

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

Тут есть несколько вариантов решения:

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

⚙️ Можно также попробовать использовать асинхронные версии методов setUp и tearDown, чтобы избежать предупреждений о синхронном контексте.

➡️ Альтернативно - старайтесь избегать использования setUp и tearDown, создавая объекты непосредственно в тестах, или перейти на Swift Testing для лучшей совместимости с актерами.

EasySwift iOS🍏

31 Jan, 07:00


How to unit test async/await functions in Swift

Тестирование функций async/await в Swift стало проще благодаря отсутствию необходимости в XCTestExpectation, достаточно просто пометить тестовую функцию как async и использовать await.

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

func testFibonacciSequenceThrowsError() async throws {
do {
let _ = try await fibonacciSequence(count: -1)
XCTFail("Expected an error for negative count, but no error was thrown")
} catch FibonacciError.invalidCount {
// Success! The expected error was thrown.
} catch {
XCTFail("Unexpected error thrown: \(error)")
}
}

EasySwift iOS🍏

29 Jan, 07:00


Core Location Modern API Tips

Пару советов по работе с Core Location:

👉Рекомендуется использовать CLLocationManager вместо CLMonitor и CLLocationUpdate, так как он предлагает больше возможностей и меньше проблем с совместимостью.

👉Для приложений с целевой версией iOS 18.0 и выше предпочтительно использовать CLServiceSession, так как он упрощает управление разрешениями на использование местоположения.

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

👉Для симуляции перемещения можно использовать GPX файлы, однако могут возникнуть проблемы с выбором файлов в Xcode, которые можно решить, изменив настройки системы.

EasySwift iOS🍏

27 Jan, 07:00


Static, Dynamic, Mergeable, oh, my!

Статья для тех, кто хотел разобраться в разных типах ликовки библиотек. 💡

👉Линковка — это процесс объединения скомпилированных объектных файлов в единое исполняемое приложение, который может происходить статически или динамически. Отсюда два разных типа библиотек: статические и динамические.

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

😮В Xcode 15 появились mergeable библиотеки. Они позволяют динамически линковать библиотеки в отладочных сборках и статически в релизных, что улучшает производительность разработки и запуска.

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

EasySwift iOS🍏

24 Jan, 07:03


objc async selectors

Если вдруг вы захотите сделать objc метод для селектора async - не стоит

Автор разбирает похожую ситуацию, где он пометил похожий метод как async:

let button = UIButton(frame: buttonFrame)
view.addSubview(button)
button.setTitle("This is a button", for: .normal)
button.addTarget(
self,
action: #selector(handleTap),
for: .touchUpInside
)

@objc func handleTap() async {
Task {
debugPrint("handle Tap")
}
}


И в итоге получил краш.

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

EasySwift iOS🍏

22 Jan, 07:04


How to bundle assets in an iOS app?

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

👉 Фреймворк позволяет обновлять игры и ресурсы без повторной отправки приложения на проверку, а также устраняет ограничения по размеру, ранее установленные для On-Demand Resources.

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

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

⚠️ Тестирование фреймворка требует отправки приложения на проверку.

EasySwift iOS🍏

20 Jan, 14:03


⚡️ Наш дебют! ⚡️

Вышла наша статья про то, как мы делали стенд для ИТ Пикника: с on-device распознаванием номеров телефонов. Это было увлекательное путешестевие с безумными ограничениями, как по времени, так и по нефунциональным требованиям, с возможностью затестить разные технологии, фреймворки, но при этом сделать стенд и продукт технологичным и крутым. И мы с этим точно справились: "умная камера" распознавала номера телефонов в среднем в 7,5 раз быстрее человека, который вводил этот номер руками. Вы только навели телефон и уже получаете результат 🔥

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

С вас лайк, репост, подписка 😊

EasySwift iOS🍏

20 Jan, 07:00


Noncopyable types in Swift

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

При передаче некопируемых типов в функции необходимо указывать модель владения: borrowing, inout или consuming, что определяет уровень доступа к значению.

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

struct SingleUseTicket: ~Copyable {
let ticketID: Int

consuming func invalidate() {
print("Ticket \(ticketID) invalidated.")

// cleanup logic

discard self
}

deinit {
print("Ticket deinitialized.")

// cleanup logic
}
}

EasySwift iOS🍏

17 Jan, 07:03


URLSession: Common pitfalls with background download & upload tasks

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

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

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

👉Установка параметра isDiscretionary в true может замедлить загрузку, так как система может отложить выполнение задач до подключения к Wi-Fi и зарядному устройству.

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

EasySwift iOS🍏

15 Jan, 07:00


Mastering the ‘Final’ Keyword in Swift: A Comprehensive Guide for Optimized Coding

👉Ключевое слово final в Swift используется для ограничения переопределения классов, методов и свойств, обеспечивая стабильность и предсказуемость кода.

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

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

EasySwift iOS🍏

13 Jan, 08:30


How to use the rethrows keyword in Swift?

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

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

Использование rethrows упрощает обработку ошибок в функциях высшего порядка, таких как map, позволяя избежать необходимости всегда использовать try или do-catch блоки.

EasySwift iOS🍏

10 Jan, 07:02


Секретная акция, или Как выйти за пределы UICollectionView

Крутая статья про внедрение классной фичи: ребята из Додо сделали Секретную акцию с интересной анимацией.

После ее внедрения, применения выросли на 26%, выручка на 0,6%, а заказы на 0,9%. 54% пользователей на iOS и 69% на Android успешно вытянули акцию.

Разработка фичи заняла около 3 месяцев, включая согласование с дизайнерами и тестирование, что сделало процесс интересным и насыщенным.

Очень подробно все описано 😍

EasySwift iOS🍏

08 Jan, 07:01


Sending vs Sendable in Swift

Swift 6 вводит новый ключевое слово sending, которое заменяет @Sendable для обеспечения безопасности передачи замыканий и значений между контекстами изоляции.

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

В статье приведены примеры кода, показывающие, как использовать sending и @Sendable в Swift 6, а также объясняется, как компилятор обрабатывает ошибки при неправильном использовании.

func exampleFunc() async {
let isNotSendable = MyClass()

// Value of non-Sendable type ... accessed after being transferred;
// later accesses could race
Task {
isNotSendable.count += 1
}

// Access can happen concurrently
print(isNotSendable.count)
}

EasySwift iOS🍏

30 Dec, 07:01


What are Sendable and @Sendable closures in Swift?

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

Структуры и акторы в Swift являются Sendable по умолчанию, если все их члены также соответствуют требованиям Sendable, в то время как классы требуют явного соответствия.

Для классов, которые не могут быть помечены как Sendable, можно использовать @unchecked Sendable, но это требует осторожности, так как это может привести к проблемам с безопасностью потоков.

// This struct is not sendable
struct Movie {
let formatterCache = FormatterCache() // This is class
let releaseDate = Date()
var formattedReleaseDate: String {
let formatter = formatterCache.formatter(for: "YYYY")
return formatter.string(from: releaseDate)
}
}

// This struct is sendable
struct Movie {
var formattedReleaseDate = "2022"
}

EasySwift iOS🍏

27 Dec, 07:01


Swift Language focus areas heading into 2025

Не так давно LSG - Language Steering Group - анонсировала основные фокусные направления на 2025 год:

👉 Несмотря на сильную основу Swift Concurrency в версии 6.0, многие разработчики испытывают трудности с его внедрением, и группа по управлению языком рассматривает идеи для упрощения этого процесса.

👉 Работа над типами Span позволит безопасно читать и записывать массивы объектов в памяти без необходимости управления памятью, что улучшит производительность и безопасность кода.

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

EasySwift iOS🍏

25 Dec, 08:00


Finding unused code with Periphery

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

Автор приводит в пример свою работу с приложением Muse, в котором больше 350 000 строк кода на Swift.

В общем, если хотели почистить свою кодовую базу, самое время это сделать 🫡

EasySwift iOS🍏

23 Dec, 09:02


BDUI — это спасение от релизов: «Какие ваши доказательства?»

BDUI (Backend Driven User Interface) позволяет делегировать построение интерфейса серверу, что снижает количество релизов и затраты на разработку новых функций.

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

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

Использование BDUI значительно улучшает время от идеи до реализации (TTM), позволяя быстрее вносить изменения через редактирование JSON-конфигураций.

EasySwift iOS🍏

20 Dec, 07:00


Secure your URLSession network requests using Certificate Pinning

SSL Pining необходим не только для защиты от MITM атак, но и для обхода ограничений доверенных сертификатов при обращении на бэкэнд.

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

private extension HTTPClient: URLSessionDelegate {
/// Handles server authentication challenges for Certificate Pinning.
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {
// We will write our pinning business logic here.
}
}

EasySwift iOS🍏

18 Dec, 07:01


Use cases for self, Self and Self.self in Swift

В Swift мы можем применять self, Self и Self.self. Как понять когда - поможет статья, в которой разбираются особенности применения на примерах.

self используется для доступа к свойствам и методам экземпляра внутри его собственных методов.
Self с заглавной буквы обозначает тип, который соответствует протоколу, позволяя реализовать полиморфное поведение.
Self.self используется для обращения к метатипу, что позволяет выполнять операции на уровне типа.

protocol Registrable {
static func register()
}

extension Registrable {
static func register() {
print("Registering \(Self.self)")
}
}

class Service: Registrable {}

// Prints `Registering Service`
Service.register()

EasySwift iOS🍏

16 Dec, 07:01


The power and expressiveness of Swift ranges

В Swift существуют различные типы диапазонов: ClosedRange, Range, PartialRangeThrough, PartialRangeFrom и PartialRangeUpTo, каждый из которых имеет свои уникальные характеристики и ограничения.

Если хотели разобраться с особенностями их применения - это хорошая обзорная статья.

Для примера:

let closedRange = Int.min...3
let partialRange = ...3

let numbers = [10, 20, 30, 40, 50, 60, 70]

print(numbers[closedRange]) // 💣💣💣 ERROR: Negative Array index is out of range

let numbers = [10, 20, 30, 40, 50, 60, 70]

print(numbers[partialRange]) // from the first index in the sequence, all the way to index: 3
// Prints "[10, 20, 30, 40]"

EasySwift iOS🍏

13 Dec, 07:01


Why Can't You Loop Over Ranges of Characters in Swift

Если пробовали вывести count у множества из символов в Swift и получали ошибку, то эта статья для вас 😅

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

EasySwift iOS🍏

11 Dec, 06:00


Animate UIKit views with SwiftUI animations in iOS 18

В iOS 18 завезли поддержку анимаций SwiftUI для UIkit.

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

class ViewController: UIViewController {
...

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.startAnimating()
}

private func startAnimating() {
let animation = SwiftUI.Animation
.linear(duration: 1.3)
.repeatForever()

UIView.animate(animation) { [weak self] in
self?.animatingView?.transform = .init(scaleX: 2, y: 2)
}
}
}

Правда одно но: не все могут позволить себе апнуть минимальную поддерживаемую версию до 18 🫠

EasySwift iOS🍏

09 Dec, 06:00


Working with Natural Language framework

Я уже скидывал статью обзора работы с Natural Language. Однако, мимо этой не смог пройти мимо.

Очень крутой пример того, как можно воспользоваться возможностями этого фреймворка в комбинации с MeshGradient, который доступен с 18 iOS, для создания отзывчивого и красивого интерфейса 😲.
Осталось только придумать для чего это нужно 😅

EasySwift iOS🍏

07 Dec, 08:01


Асинхронность в iOS: как ускорить корпоративные приложения и не сломать мозг разработчика

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

Если очень коротко, то всего три:
- GCD (Grand Central Dispatch)
- Operation Queue
- Swift Concurrency

Речь идет про «коробочные решения» без погружения в глубину.
Но, кажется, мы все еще долго будем использовать gcd 🥲

EasySwift iOS🍏

05 Dec, 08:00


Дебаг на максимум: секретные настройки Xcode, которые должен знать каждый разработчик

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

В Xcode доступны настройки, такие как Slow Animations, Graphics Quality Override и Simulate Memory Warning, которые помогают выявить и устранить проблемы с производительностью. Внеэкранная отрисовка может значительно замедлить работу GPU - её стоит избегать, используя кэширование и оптимизацию слоев.

Объемная и полезная статья про оптимизации графики в iOS.

EasySwift iOS🍏

03 Dec, 08:00


Об анатомии крэшей на iOS «по-взрослому»

Большая и подробная Статья про причины и механизмы возникновения крэшей на iOS, включая ошибки в коде и проблемы с памятью (там на самом деле все «по-взрослому» 🫣)
Автор начинает со старта приложения и заканчивает разбором сигналов и исключений.

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

Достаточно серьезное чтиво 🤓

EasySwift iOS🍏

30 Nov, 08:00


MainActor usage in Swift explained to dispatch to the main thread

MainActor — это глобальный актор в Swift 5.5, который выполняет задачи на главном потоке, обеспечивая обновление пользовательского интерфейса без проблем с многопоточностью.

Использование @MainActor упрощает код, устраняя необходимость в множественных вызовах DispatchQueue.main.async и оптимизируя производительность, выполняя задачи на главном потоке только при необходимости.

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

Так, например, функция вида:
func fetchImage(for url: URL, completion: @escaping (Result<UIImage, Error>) -> Void) {
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data, let image = UIImage(data: data) else {
DispatchQueue.main.async {
completion(.failure(ImageFetchingError.imageDecodingFailed))
}
return
}

DispatchQueue.main.async {
completion(.success(image))
}
}.resume()
}


Может превратиться в такую:
@MainActor
func fetchImage(for url: URL) async throws -> UIImage {
let (data, _) = try await URLSession.shared.data(from: url)
guard let image = UIImage(data: data) else {
throw ImageFetchingError.imageDecodingFailed
}
return image
}

EasySwift iOS🍏

28 Nov, 08:01


Integrating Live Activity and Dynamic Island in iOS: A Complete Guide

Большая и подробная статья про использование Live Activities и Dynamic Island.
Такие активити позволяют приложениям отображать актуальную информацию на экране блокировки, а Dynamic Island предоставляет интерактивную область для обновлений в верхней части экрана.

Live Activities могут быть активны до 8 часов, а их размер данных не должен превышать 4 КБ. Важно избегать перегрузки информацией и следовать рекомендациям по дизайну.

Для добавления поддержки Live Activity в приложение iOS необходимо создать расширение виджета и настроить Info.plist, добавив ключ 'Supports Live Activities'.

EasySwift iOS🍏

25 Nov, 08:01


The Case Against [unowned self]

В Swift существуют три типа ссылок: strong, weak и unowned. Сильные ссылки удерживают объект в памяти, слабые ссылки предотвращают циклы удержания, а unowned ссылки предполагают, что объект будет существовать дольше, чем ссылка.

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

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

EasySwift iOS🍏

22 Nov, 08:00


Automatic Trait Tracking

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

Автоматическое отслеживание поддерживается в методах обновления макета, таких как layoutSubviews(), updateViewConstraints() и draw(CGRect) для UIView, а также viewWillLayoutSubviews() и updateConfiguration для UIViewController и других.

Пример кода показывает, как в классе UIView автоматически изменяется размер рисуемого объекта в зависимости от выбранного размера шрифта доступности(dynamic type) без необходимости ручной регистрации изменений.

EasySwift iOS🍏

20 Nov, 08:00


Some vs Any

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

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

В этой статье намеренно не используются такие термины, как opaque, existential, boxed и type erasure, поскольку по мнению автора усложняют понимание сути.

EasySwift iOS🍏

18 Nov, 08:30


How to Use URLSession with Async/Await for Network Requests in Swift

URLSession позволяет выполнять сетевые запросы с использованием async/await, что упрощает процесс получения данных и их декодирования в структуру.

В статье разбираются примеры кода выполнения GET и POST запросов, декодирование JSON ответов, а также работа с типизированными ошибками для проверки различных HTTP кодов.

var urlComponents = URLComponents(string: "https://httpbin.org/get")!

/// Define the parameters.
let parameters: [String: String] = [
"name": "Antoine van der Lee",
"age": "33"
]

/// Add the query parameters to the URL.
urlComponents.queryItems = parameters.map { key, value in
URLQueryItem(name: key, value: value)
}

/// Ensure we have a valid URL and throw a URLError if it fails.
guard let url = urlComponents.url else {
throw URLError(.badURL)
}

/// Use URLSession to fetch the data asynchronously.
let (data, response) = try await URLSession.shared.data(from: url)

EasySwift iOS🍏

17 Nov, 08:01


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

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

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

EasySwift iOS🍏

14 Nov, 09:00


How Do Binaries work together? What breaks ABI?

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

В статье достаточно подробно описан процесс работы ABI/API стабильности и какие изменения не приведут к нарушению.

EasySwift iOS🍏

12 Nov, 08:00


Swift TaskGroup на примерах

Если вы хотели разобраться в особенностях применения TaskGroup и чем она отличается от Task и async let, то эта статья для вас.

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

Также есть примеры работы с AsyncStream.

EasySwift iOS🍏

08 Nov, 08:01


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

Ближайшее мероприятие:

• 30 ноября – 1 декабря — для Android- и iOS-разработчиков, офер за 2 дня в команды Карт и Рекламы.

Зарегистрироваться

EasySwift iOS🍏

07 Nov, 08:01


Why Do View Controllers Need init(coder:)?

Класс UIViewController поддерживает протокол NSCoding, что требует реализации инициализатора init(coder:), даже если он не используется напрямую.

Даже при создании view controllers программно, необходимо использовать UIStoryboards, которые в процессе создания используют NSCoding для воссоздания состояния view controller и его представлений.

EasySwift iOS🍏

05 Nov, 08:01


Азартная разработка iOS приложения игры 2048 с ChatGPT

Объемная и подробная статья про совместную разработку с ChatGPT известной игры 2048.

Также в игру вводится новый элемент: ИИ - алгоритм, который будет автоматически ходить. В качестве примера были взяты два: Monte Carlo и Expectimax

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

EasySwift iOS🍏

03 Nov, 08:00


Beginner’s Guide to Protocol Buffers and gRPC with Swift

Отличная статья про Protocol Buffer или «protobuf», разбираются основные особенности его использования и gRPC.
Также автор описывает подробные шаги по настройке базового сервера gRPC в Swift с использованием библиотек Swift Protobuf и gRPC, включая создание структур данных Swift, создание интерфейса gRPC и внедрение интерфейса на стороне сервера.
Кстати, для сети он использует акторы и async/await.

func completeTodo(
request: ServerRequest<Todos_TodoID>,
context: ServerContext
) async throws -> ServerResponse<Todos_Todo> {
guard
var todo = todos.first(where: { $0.todoID == request.message.todoID })
else {
return .init(
error: RPCError.init(
code: .notFound,
message: "Todo not found."
)
)
}
todo.completed = true
todos = todos.filter { $0.todoID != request.message.todoID }
todos.append(todo)
return .init(message: todo)
}

EasySwift iOS🍏

01 Nov, 08:00


Корзина в Додо Пицце на iOS 14: баг длиной в полгода

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

Сама же проблема была простая: после редизайна приложения Додо Пиццы, кнопка корзины стала невидимой для пользователей на iOS 14, вызывая жалобы и проблемы с отображением стоимости продуктов. И фикс был в пару строк 🫣

EasySwift iOS🍏

31 Oct, 08:00


Faster iOS Networking with Shared Dictionary Compression

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

Что такое shared dictionary compression?

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

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

Однако, стоит понимать, что без доработок со стороны бекэнда данная практика невозможна 🫢

EasySwift iOS🍏

22 Oct, 10:02


Calculating the semantic distance between words with the Natural Language framework

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

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

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


import NaturalLanguage

func getSemanticDistance(for word: String, in language: NLLanguage) {

// 1. Create the embedding for the language the word belongs to
if let embedding = NLEmbedding.wordEmbedding(for: language) {

// 2. Find the neighbors for the word
embedding.enumerateNeighbors(for: word, maximumCount: 10) { neighbor, distance in

// 3. Acces the neighbor distance from the word
print("\(neighbor): \(distance)")

return true
}
}
}

EasySwift iOS🍏

18 Oct, 08:00


The perfect iOS networking layer does not exist - Part 2

Продолжение статьи про написание сетевого слоя.

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

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

EasySwift iOS🍏

16 Oct, 08:02


The perfect iOS networking layer does not exist - Part 1

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

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

EasySwift iOS🍏

14 Oct, 10:00


Beware UserDefaults: a tale of hard to find bugs, and lost data

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

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

EasySwift iOS🍏

11 Oct, 13:02


Как реализовать спойлер-эффект как в Telegram на Swift?

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

Для достижения нужного эффекта автор использует CAEmitterLayer. Однако, помимо лейера тут еще очень много различных тонкостей, которые с первого взгляда не очевидны.

EasySwift iOS🍏

09 Oct, 08:02


Как ускорить запуск iOS-приложения в 2 раза с помощью Network Instrument

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

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

EasySwift iOS🍏

07 Oct, 09:01


UNSAFE SWIFT

Уже не новая, но актуальная статья про использование указателей в Swift.
Автор подробно разбирает выравнивание: для чего это может понадобиться, почему порядок типов в объекте имеет значение и как работать с объектами через один из 4 доступных указателей: UnsafeRawPointer, UnsafeMutableRawPointer, UnsafeRawBufferPointer и UnsafeMutableRawBufferPointer


class Foo {
let a: UInt8
let b: UInt16
}
MemoryLayout<Foo>.size // 8
MemoryLayout<Foo>.alignment // 8
MemoryLayout<Foo>.stride // 8


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

EasySwift iOS🍏

04 Oct, 11:01


Data alignment: Straighten up and fly right

Хорошо проработанная статья на инженерном языке про работу процессора.

Главная мысль – раскрыть концепцию работы процессора: как он обращается к памяти в 2, 4, 8, 16 или 32-байтовых фрагментах, а не в байтовых кусках, как мы привыкли думать.

EasySwift iOS🍏

02 Oct, 09:02


Прокачайте свой код с @dynamicMemberLookup

Атрибут dynamicMemberLookup в Swift позволяет обращаться к свойствам объекта, как если бы они были статически определены, что упрощает работу с динамическими структурами данных и делает API более гибким и расширяемым.


json[0]?["name"]?["first"]?.stringValue

// заменится на

json[0]?.name?.first?.stringValue


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

В статье разбираются основные моменты при работе с данным атрибутом на примере.

EasySwift iOS🍏

30 Sep, 09:01


Как встроить распознавание звуков в ваше iOS приложение на Swift с использованием SoundAnalysis

Если вы хотели попробовать реализовать приложения для распознавания звуков – это статья для вас.
Автор разбирает базовые концепции работы с фреймворком SoundAnalysis. При этом вы можете воспользоваться моделями из коробки, они позволяют распознавать до 300 различных звуков, либо натренировать свою модель через CreateML.

EasySwift iOS🍏

29 Sep, 10:02


Псевдоним типа в Swift

Ключевое слово typealias в Swift позволяет создавать удобный для восприятия код, например:


// Повысить восприятие кода
typealias StringDictionary<T> = Dictionary<String, T>

// Упростить сигнатуры сложных типов и кортежей
typealias CompletionHandler = (Result<String, Error>) -> Void
typealias GridPoint = (x: Int, y: Int)

// Указать ограничения
typealias StringArrayDictionary = Dictionary<String, [String]>



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

EasySwift iOS🍏

25 Sep, 08:01


How to keep Date’s microseconds precision in Swift

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

Автор предлагает использовать расширение ISO8601DateFormatter для ручного извлечения микросекунд из строки даты и добавления их к сконвертированному значению Date.


extension ISO8601DateFormatter {
func microsecondsDate(from dateString: String) -> Date? {
guard let millisecondsDate = date(from: dateString) else { return nil }
guard let fractionIndex = dateString.lastIndex(of: ".") else { return millisecondsDate }
guard let tzIndex = dateString.lastIndex(of: "Z") else { return millisecondsDate }
guard let startIndex = dateString.index(fractionIndex, offsetBy: 4, limitedBy: tzIndex) else { return millisecondsDate }
// Pad the missing zeros at the end and cut off nanoseconds
let microsecondsString = dateString[startIndex..<tzIndex].padding(toLength: 3, withPad: "0", startingAt: 0)
guard let microseconds = TimeInterval(microsecondsString) else { return millisecondsDate }
return Date(timeIntervalSince1970: millisecondsDate.timeIntervalSince1970 + microseconds / 1_000_000.0)
}
}

EasySwift iOS🍏

23 Sep, 09:01


AVAudioSourceNode, AVAudioSinkNode: Low-Level Audio In Swift

AVAudioSourceNode
– узлы AVAudio, предоставляющие способ обработки входных и выходных аудиоданных. Для работы с аудио в режиме реального времени, придется выйти на уровень работы с указателями через UnsafeMutableAudioBufferListPointer и UnsafeMutableBufferPointer. Стоит помнить, что в таком случае управление памятью ложиться на плечи разработчика.

Если вам интересна работа со звуком на низком уровне – эта статья точно для вас.

EasySwift iOS🍏

20 Sep, 09:02


Announcing Swift 6

Анонсировали релиз Swift 6 🥳 и нас ждет очень много изменений, вот небольшой список:
- поддержка 128-битных целых чисел
- новая библиотека синхронизации, которая включает примитивы, такие как mutex
- новый подход к выбрасыванию ошибок
- владение некопируемых типов
- расширение интеропа с C++
- новый макрос для отображения информации в LLDB @DebugDescription
- фреймворк для тестирования Swift Testing

EasySwift iOS🍏

19 Sep, 12:02


The Memory Leak: An Xcode Detective Story

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

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

EasySwift iOS🍏

16 Sep, 09:01


Wrapping async-await with a completion handler in Swift

Статья про то, как обернуть async-await кода в completion handler. Вы столкнетесь с таким, например, если используете сторонние библиотеки, которые принимают только хендлеры, а ваша кодовая база на основе Swift Concurrency.


extension Task {
@discardableResult
init<T>(
priority: TaskPriority? = nil,
operation: @escaping () async throws -> T,
queue: DispatchQueue = .main,
completion: @escaping (Result<T, Failure>) -> Void
) where Success == Void, Failure == any Error {
self.init(priority: priority) {
do {
let value = try await operation()
queue.async {
completion(.success(value))
}
} catch {
queue.async {
completion(.failure(error))
}
}
}
}
}

EasySwift iOS🍏

13 Sep, 08:01


Morphology in Swift

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

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


Text("She will receive ^[\(count) games](inflect: true).")


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

EasySwift iOS🍏

11 Sep, 08:02


Антимат в чате на iOS: как я мешаю пользователям сквернословить

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

Как MVP точно пойдет и не факт, что продуктово имеет смысл делать что-то лучше.

EasySwift iOS🍏

09 Sep, 09:02


Борьба с утечками памяти: от задачи до победы

Классное видео с мобиуса про борьбу с утечками памяти: тут и про работу с Memory Graph, про который не так много документации и примеры про автоматизацию поиска утечек через UI тесты.

EasySwift iOS🍏

06 Sep, 08:02


Benchmark Package

Не так давно был представлен новый пакет Benchmark. Его основная цель – измерение производительности. Количество метрик из коробки большое: 27.
Так же можно добавлять свои метрики.

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

Выглядит круто и работоспособно.