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

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

По всем вопросам обращаться к @itereznikov
Download Telegram
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)
}
👍5🤯1🤬1
Секретная акция, или Как выйти за пределы UICollectionView

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

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

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

Очень подробно все описано 😍
🔥115
How to use the rethrows keyword in Swift?

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

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

Использование rethrows упрощает обработку ошибок в функциях высшего порядка, таких как map, позволяя избежать необходимости всегда использовать try или do-catch блоки.
👍7
Mastering the ‘Final’ Keyword in Swift: A Comprehensive Guide for Optimized Coding

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

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

👉Рекомендуется использовать final для методов и свойств, которые должны оставаться неизменными, но следует учитывать баланс между безопасностью и гибкостью кода.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
URLSession: Common pitfalls with background download & upload tasks

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

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

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

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

👉Для тестирования фоновых задач рекомендуется использовать реальное устройство, так как симуляторы могут не поддерживать фоновую загрузку должным образом.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
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
}
}
🔥7👎1
⚡️ Наш дебют! ⚡️

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

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

С вас лайк, репост, подписка 😊
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9
How to bundle assets in an iOS app?

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

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

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

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

⚠️ Тестирование фреймворка требует отправки приложения на проверку.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
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")
}
}


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

Также автор разбирает возможную причину такого поведения и вариант обхода такой проблемы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Static, Dynamic, Mergeable, oh, my!

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

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

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

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

✔️Понимание работы линковщика позволяет оптимизировать размер приложения, упростить граф зависимостей и улучшить время сборки.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
Core Location Modern API Tips

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

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

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

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

👉Для симуляции перемещения можно использовать GPX файлы, однако могут возникнуть проблемы с выбором файлов в Xcode, которые можно решить, изменив настройки системы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
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)")
}
}
👍3
XCTest Meets @MainActor: How to Fix Strict Concurrency Warnings

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

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

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

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

➡️ Альтернативно - старайтесь избегать использования setUp и tearDown, создавая объекты непосредственно в тестах, или перейти на Swift Testing для лучшей совместимости с актерами.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥42
Model Inheritance in Core Data

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

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

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

📌 Рекомендуется осторожно использовать модель наследования и рассмотреть возможность ручной реализации аналогичных эффектов для лучшей совместимости с SwiftData.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Getting started with Core Image

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

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

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

⚙️ Фреймворк использует аппаратное ускорение через GPU для высокопроизводительных задач, что позволяет обрабатывать изображения быстро и эффективно, особенно в приложениях, требующих реального времени.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
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 на массиве строк предлагает более лаконичный способ форматирования списков с дополнительными параметрами, такими как тип соединения (например, 'или' или 'и').
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Network Link Conditioner: Simulating Slow Networking

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

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

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

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

➡️ Тестирование приложений в условиях медленной сети критически важно для обеспечения хорошего пользовательского опыта, особенно для пользователей с низкой скоростью интернета.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Потоки под капотом: как работают многопоточность и синхронизация в iOS

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

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

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

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

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

📊 Закон Амдала описывает, что ускорение программы, достигнутое за счет параллельной обработки, ограничено последовательными участками кода, которые не могут быть распараллелены.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
How to create and upload high-quality App Store assets with RocketSim and Helm

👀 Недавно вспоминали RocketSim. Держите статью, про упрощение создания качественных изображений для AppeSrore.

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

⭐️ Helm автоматизирует загрузку скриншотов, позволяя перетаскивать их из Finder и автоматически сортируя по устройствам и языкам.

➡️ Поддержка загрузки видео-превью в Helm запланирована на будущее.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4