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

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

По всем вопросам обращаться к @itereznikov
Download Telegram
Подробно об акторах в Swift

Акторы в Swift 5.5 предназначены для безопасной обработки общего изменяемого состояния и предотвращения гонок данных при работе с многопоточностью.

В Swift акторами гарантируется изоляция данных: все изменяемые свойства и функции в акторе изолированы от прямого доступа извне.

В статье автор приводит примеры работы с акторами, подсвечивает основные моменты при работе с ними, а так же описывает процесс перехода на них.
👍7🔥3
if and switch expressions

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


let bullet: String
if isRoot && (count == 0 || !willExpand) { bullet = "" }
else if count == 0 { bullet = "- " }
else if maxDepth <= 0 { bullet = "▹ " }
else { bullet = "▿ " }


можно заменить на:

let bullet = if isRoot && (count == 0 || !willExpand) { "" }
else if count == 0 { "- " }
else if maxDepth <= 0 { "▹ " }
else { "▿ " }


Кстати, а в котлине это уже давно есть 🥲
🔥11
Access-level modifiers on import declarations

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

С приходом Swift 6 станет возможным добавлять к импортам зависимостей модификаторы уровня доступа, а именно:
public, package, internal, fileprivate и private.


public import PublicDependency


По умолчанию, в Swift 5 все зависимости публичные, однако в Swift 6 станут с модификатором internal.

Чтобы потестить эти модификаторы на Swift 5.9 нужно добавить флаг:
-enable-experimental-feature AccessLevelOnImport


А чтобы проверить, что будет если все импорты станут internal как в Swift 6, то нужно включить еще один флаг:
-enable-experimental-feature InternalImportsByDefault


Это достаточно серьезные изменения, которые могут сломать обратную совместимость для библиотек. Поэтому советую заранее подготовиться 😉
👍63🤔2
🔤🔤🔤🔤2️⃣4️⃣

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

Что меня порадовало:
- отдельный менеджер паролей: давно пора, но искренне жаль сторонние сервисы, им точно станет не легко
- Game Porting Toolkit 2 и игровой режим – опять большой упор в игры, и кажется, Apple хочет повторить свой успех Apple Music и Apple TV, но тягаться с Гейбом будет не просто
- калькулятор на iPad – теперь хотя бы понятно, почему они так долго его не выпускали 😬
- watchOS 11 и Vitals – надеюсь, что это новый виток развития приложения «Здоровье» и задел на сентябрскую презентацию с измерениями большего числа показателей организма
- Apple Intelligence – тут и комментировать не нужно, это , но хочется дождаться техно сессий и более детально погрузиться. Обидно, что доступно в этом году только в US, но будем ждать и на нашей улице праздник. Еще обидно, что с iPhone 15 Pro и M1 девайсов, но хотя бы понятно, что спустя пару лет это перестанет быть проблемой
- сотрудничество с OpenAI – это еще более крутая и понятная история, но если будет доступно только в Siri, нативных приложениях и там где есть UITextView, то уже не так радостно и круто

Что было очень не очень и даже обидным:
- visionOS 2 – что вообще поменялось, кроме как 8 стран добавили?
- iOS 18 / iPadOS / tvOS 18 – тут и комментировать нечего: кастомное расположение приложений и возможность их скрывать на рабочем столе, настраиваемый пункт управления и вырвиглазные иконки в темной теме. Просто amazing, который мы все заслужили 🥲
- Tap to Сash: «оплата через AirDrop» – очень крутая фича, но естественно, доступно лишь избранным странам и банкам. Никаких открытых API мы скорее всего не увидим
- Xcode Copilot – я даже засек: уделили ровно 14 секунд нашему главному инструменту. Спасибо, конечно, что рассказали про новый эмоджи генератор, но на главной презентации для разработчиков хотелось бы послушать чуть больше про Xcode.

На самом деле я думаю, что часть из пунктов выше раскроют на предстоящих сессиях и мы увидим еще много нового и интересного.
Stay tuned!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍6💯4👎21🤬1
Swift Testing

Apple представила новый фреймворк для тестирования, который:
- поддерживает Swift Concurrency
- по дефолту запускает тесты параллельно
- заменяет XCTAssertTrue, XCTAssertEqual и другие на достаточно умный макрос #expect()
- позволяет запускать тесты с заранее определенным наборам данных
- более информативно сообщает в случае падения теста
- разработан как open source и он кроссплатформен

Вот пример, как теперь будут выглядеть тесты:

@Test("Check video metadata",
.tags(.metadata))
func videoMetadata() {
let video = Video(fileName: "By the Lake.mov")
let expectedMetadata = Metadata(duration: .seconds(90))
#expect(video.metadata == expectedMetadata)
}


Попробовать можно сейчас с XCode 16 beta. Более подробно можно посмотреть в видео с WWDC.
👍161
Run, Break, Inspect: Explore effective debugging in LLDB

Познавательная сессия про отладку и поиск проблем в кодовой базе с помощью LLDB и:
- крашлогов
- обратных вызовов (backtraces)
- брейкпоинтов с действиями и сложными условиями остановки
- "p" команды

Из нового: добавили новый макрос @DebugDescription, который может заменить протокол CustomDebugStringConvertible. Пример:


@DebugDescription
struct WatchLaterItem {
let video: Video
let name: String
let addedOn: Date

var debugDescription: String {
"\(name) - \(addedOn)"
}
}
👍7
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