EasySwift iOS🍏
3.02K subscribers
268 photos
8 videos
393 links
Все самое интересное в мире iOS разработки 🧑🏻‍💻

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

По всем вопросам обращаться к @itereznikov
Download Telegram
Demystify explicitly built modules

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

В XCode 16 добавили опцию в Build Settings проекта: Explicitly Built Modules, которая позволит быстрее найти проблемное место. В логах сборки приложения будет генерироваться Swift modules report, в котором будут указаны все варианты собранных модулей. Так же эта опция позволит сократить время сборки за счет улучшенного планирования стадий сборки и передачи уже собранных модулей дебагеру.

В видео более подробно про то, что происходит после запуска сборки приложения.
👍4
Analyze heap memory

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

Еще в сессии про:
- устройство кучи
- анализ потребления памяти
- инструменты профилирования
- устройство autoreleasepool
- применимость unowned и weak ссылок

Забавно, что в этой сессия не рассматривается устранение проблем при помощи Swift Concurrency, а все "по старинке" 🤔
🔥13
Go small with Embedded Swift

В этой WWDC сессии рассказывается про новую область применения Swift – встраиваемые устройства (Embedded Devices).

Обязательно смотреть, если устали от привычной разработки и хочется чего-нибудь экзотического 😎 Еще интересно тем, что есть достаточно жесткие ограничения по потребляемой памяти и вычислительной мощности. Более того, не все функции языка доступны, поэтому иногда придется искать альтернативные решения.
🔥6
Explore Swift performance

Swift – лаконичный и интуитивно понятный язык программирования. Однако, за этой простотой мы не всегда явно осознаем, как то или иное решение повлияет на производительность. В том же C при вызове malloc мы всегда видим затраты по памяти.

В сессии проходятся по многим аспектам работы языка на низком уровне.
А еще видео содержит ответы на часто задаваемые вопросы по Swift на собеседованиях 🤫
🔥11
Возможно, кто-то уже замечал подобное, но для некоторых это будет открытием.

Объясняется такое просто: в первом случае мы используем реализацию

public func contains<T>(_ other: T) -> Bool where T : StringProtocol


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

А во втором случае мы испльзуем реализацию из стандартной библиотеки.

public func contains(_ other: String) -> Bool


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

P.S. тут даже баг зарепортили, но, кажется, исправлять это не будут 🫢
👍18🤯3
Synchronous Mutual Exclusion Lock

Недавно одобрили предложение по внедрению нового примитива синхронизации в Swift - Mutex.

class FancyManagerOfSorts {
let cache = Mutex<[String: Resource]>([:])

func save(_ resource: Resource, as key: String) {
cache.withLock {
$0[key] = resource
}
}
}


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

В статье говорится, что Mutex похож на lock, но проблема в том, что не описано прямо как он реализован.

Ждем в новых версиях Swift 🤔
🔥10
Warning for Retroactive Conformances of External Types

Ретроактивное соответствие в Swift – это возможность добавить соответствие протокола к типу, который не находится под вашим контролем, как правило, путем определения расширения типа в другом модуле. С одной стороны это удобно, с другой:
• может привести к случайному поведению, если два разных модуля добавляют противоречивые соответствия;
• вводит опасности совместимости источников, так как модуль может добавить соответствие, которое нарушает существующий код;
• нарушение «дружелюбной для библиотеки» истории, так как модуль может добавлять соответствия типам, которыми он не владеет.

Для решения этой проблемы предлагают добавить предупреждение в компиляторе.
Его можно будет заглушить использовав новый атрибут @retroactive

extension Date: @retroactive Identifiable {
// ...
}


Однако в старых версиях Swift его можно будет избежать явно указав источник

extension Foundation.Date: Swift.Identifiable {
// ...
}
👍4
Typed Throws in Swift: Handling Errors Effectively

Статья про концепцию «выбрасывания ошибок» в Swift, которая позволяет более эффектино обрабатывать ошибки. Ключевые моменты:
- Swift позволяет определять пользовательские типы ошибок, создавая перечисление, соответствующее протоколу Error.
- Throwing функции: Функции, которые могут выбрасывать ошибки, помечаюттся ключевым словом throws.
- Ошибки могут обрабатываться в блоке do-catch.
- Типы, выбрасывающие ошибки, могут так же содержать вложенные ошибки.


static func validate(name: String) throws(ValidationError) {
guard !name. isEmpty else {
throw OtherError.validationFailed
}
}
👍81
Изучаем новые структуры данных для iOS разработчика

Статья про редко используемые структуры данных: Deque, Heap, OrderedSet и OrderedDictionary.

Deque предоставляет возможность работать с коллекцией элементов, к которой можно добавлять и удалять элементы как с начала, так и с конца, с амортизированной сложностью О(1).

Heap (куча) - частично-упорядоченное дерево с эффективными операциями вставки и удаления, обладающее сложностью операций вставки O(log n) и получения минимального/максимального элемента O(1).

OrderedSet и OrderedDictionary это коллекции, в которых поддерживается порядок элементов и обеспечивается уникальность ключей.
9🔥3🥰2🎉1
This media is not supported in your browser
VIEW IN TELEGRAM
Enhancing your app with fluid transitions

iOS 18 будет доступен плавный интерактивный зум-переход. Можно использовать как в SwiftUI, так и в UIKit.

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


// Create a detail view controller for the selected item.
let detailViewController = MyDetailViewController(itemID: itemID)


// Set the preferred transition to zoom.
detailViewController.preferredTransition = .zoom { [self] _ in

// Return the thumbnail view for the selected item.
return thumbnail(for: itemID)
}


// Push the detail view controller onto the navigation stack.
navigationController?.pushViewController(detailViewController, animated: true)
👍8🔥4
How to solve problems with bitwise operators in Swift

Бит – это наименьшая часть информации, которая может быть 1 или 0. Swift предлагает операторы для манипуляции битами, такие как OR, AND, LEFT SHIFT и RIGHT SHIFT, которые могут быть использованы для решения задач с битовыми операциями.


0b00000011 | 0b00000101 // The bitwise OR operator produces 0b00000111
0b00000011 & 0b00000101 // The bitwise AND operator produces 0b00000001
0b00000010 << 1 // The bitwise LEFT SHIFT operator << produces 0b0000100
0b00000010 >> 1 // The bitwise RIGHT SHIFT operator >> produces 0b0000001


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


struct WeekdayOptions: OptionSet {
let rawValue: Int

static let sun = WeekdayOptions(rawValue: 1 << 0)
static let sat = WeekdayOptions(rawValue: 1 << 1)
static let fri = WeekdayOptions(rawValue: 1 << 2)
static let thu = WeekdayOptions(rawValue: 1 << 3)
static let wed = WeekdayOptions(rawValue: 1 << 4)
static let tue = WeekdayOptions(rawValue: 1 << 5)
static let mon = WeekdayOptions(rawValue: 1 << 6)
}


P.S. Но я рекомендую много раз подумать, а точно ли вам нужны битовые маски, прежде чем их использовать
👍42
A Beginner’s Guide to Code Signing in iOS Development

Must read статья для понимания процесса подписи приложения и публикации.

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

Автор задается вопросом, после просмотра сессии про управление памятью в Swift, есть ли гарантированный способ определения была ли выделена память на куче? Swift не предоставляет способа узнать, скрывает ли тип значения частные ссылочные типы, но можно использовать функцию _isPOD() в стандартной библиотеке для этой цели:


There's an _isPOD() (Warning: underscored API!) entry point in the stdlib for this purpose:
print(_isPOD(Int.self)) // true
print(_isPOD(Array<Int>.self)) // false


В треде люди делятся другими интересными способами как это определить
🔥5
Async await in Swift: The Full Toolkit

Крутая статья от ребят из Emerge Tools про инструменты Swift Concurrency. Подробно и понятно описаны основные возможности и есть примеры использования таких штук:
async / await и async let
Task и Task group
Actors и MainActor
Sendable
Continuations
AsyncSequence
AsyncStream
Async Algorithms

Статья обязательна к прочтению, особенно если только начинаете использовать Swift Concurrency.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
Скрытая (на виду) сила KeyPath'ов

KeyPath'ы в Swift - это параметризованные типами объекты, позволяющие читать и записывать переменные типа Value в значения типа Root. Они представлены в виде классов и образуют иерархию типов, включая AnyKeyPath, PartialKeyPath, KeyPath, WritableKeyPath и ReferenceWritableKeyPath.

KeyPath'ы могут быть конвертированы в функции, объединяться, предоставлять доступ по индексу и использоваться в качестве токенов. Они также поддерживают Type Inference и атрибут @dynamicMemberLookup.

В самой статье автор рассматривает так же примеры использования KeyPath для создания удобных API.
🔥3
MIT Professor on Data Abstraction & Object-Oriented Programming

Супер классное видео с автором одного из принципов SOLID. В видео затрагивается немного истории, разбирают технические детали самого принципа и отвечают на разные вопросы.

Советуем смотреть всем, оно небольшое.
❤‍🔥3
Non-Sendable types are cool too you know

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

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

Использование параметра isolation(any) в сочетании с новыми функциями Swift 6 позволяет non-Sendable типам участвовать в конкурентности, обеспечивая безопасность и гибкость.
🔥2
iOS App Launch Optimization: How Cityflo Achieved 2.22x Faster Load Times

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

В статье автор поделился опытом ускорения запуска приложения с рассмотрением всех моментов, на которые они сделали упор после анализа времени запуска: оптимизацию библиотек, ленивая инициализация, рефакторинг AppDelegate, удаление избыточной логики и оптимизация последовательности вызовов API.
👍32
Streamlining NotificationCenter Usage in Swift

Автор описывает интересный подход использования NotificationCenter у себя в проекте: создание протокола с расширением, содержащим некоторые реализации функций. Это позволяет поддерживать чистоту в коде, а также дает возможность проводить тестирование такой функциональности.
❤‍🔥2
Как вернуть контроль над состоянием данных с RemoteResult

Автор предлагает расширить Result, чтобы сделать его более удобным и преварить его в:


enum RemoteResult<Success, Failure: Error> {
case idle
case loading
case success(Success)
case failure(Failure)
}


Это позволит лучше управлять состоянием данных и реагирововать на состояние загрузки и «простоя». RemoteResult может быть адаптирован для использования в архитектурах программирования, таких как The Composable Architecture, путем внесения простых изменений для совместимости с логикой сравнения состояний.
3👍1😁1
Recursive enums in Swift

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

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


enum FileSystemItem {
case file(name: String)
case folder(name: String, items: [FileSystemItem])
indirect case alias(name: String, to: FileSystemItem)
}
👍5