Why Can't You Loop Over Ranges of Characters in Swift
Если пробовали вывести count у множества из символов в Swift и получали ошибку, то эта статья для вас 😅
Символы Юникода могут иметь разные порядки сортировки в зависимости от локали, что делает итерацию по диапазонам символов проблематичной. Еще некоторые символы, такие как эмодзи, могут состоять из нескольких кодовых блоков, что усложняет создание и итерацию по диапазонам.
Если пробовали вывести count у множества из символов в Swift и получали ошибку, то эта статья для вас 😅
Символы Юникода могут иметь разные порядки сортировки в зависимости от локали, что делает итерацию по диапазонам символов проблематичной. Еще некоторые символы, такие как эмодзи, могут состоять из нескольких кодовых блоков, что усложняет создание и итерацию по диапазонам.
🔥7
The power and expressiveness of Swift ranges
В Swift существуют различные типы диапазонов: ClosedRange, Range, PartialRangeThrough, PartialRangeFrom и PartialRangeUpTo, каждый из которых имеет свои уникальные характеристики и ограничения.
Если хотели разобраться с особенностями их применения - это хорошая обзорная статья.
Для примера:
В 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]"
🔥6
Use cases for self, Self and Self.self in Swift
В Swift мы можем применять self, Self и Self.self. Как понять когда - поможет статья, в которой разбираются особенности применения на примерах.
• self используется для доступа к свойствам и методам экземпляра внутри его собственных методов.
• Self с заглавной буквы обозначает тип, который соответствует протоколу, позволяя реализовать полиморфное поведение.
• Self.self используется для обращения к метатипу, что позволяет выполнять операции на уровне типа.
В 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()
🔥10❤3
Secure your URLSession network requests using Certificate Pinning
SSL Pining необходим не только для защиты от MITM атак, но и для обхода ограничений доверенных сертификатов при обращении на бэкэнд.
В данной статье автор рассказывает, как получить сертификат и какую обвязку нужно написать для того, чтобы запросы работали с SSL Pining.
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.
}
}
🔥5❤2
BDUI — это спасение от релизов: «Какие ваши доказательства?»
BDUI (Backend Driven User Interface) позволяет делегировать построение интерфейса серверу, что снижает количество релизов и затраты на разработку новых функций.
Ключевые преимущества BDUI включают консистентность интерфейсов, единую базу конфигураций и отсутствие необходимости в релизах для добавления новых функций.
Основные недостатки BDUI включают ограничения в дизайне, необходимость релизов для новых компонентов и длительное время разработки на старте.
Использование BDUI значительно улучшает время от идеи до реализации (TTM), позволяя быстрее вносить изменения через редактирование JSON-конфигураций.
BDUI (Backend Driven User Interface) позволяет делегировать построение интерфейса серверу, что снижает количество релизов и затраты на разработку новых функций.
Ключевые преимущества BDUI включают консистентность интерфейсов, единую базу конфигураций и отсутствие необходимости в релизах для добавления новых функций.
Основные недостатки BDUI включают ограничения в дизайне, необходимость релизов для новых компонентов и длительное время разработки на старте.
Использование BDUI значительно улучшает время от идеи до реализации (TTM), позволяя быстрее вносить изменения через редактирование JSON-конфигураций.
👍4❤🔥2🔥2🤬1
Finding unused code with Periphery
Periphery — это command-line инструмент для поиска неиспользуемого кода в проектах на Swift, который помогает поддерживать чистоту кода без значительных затрат времени.
Автор приводит в пример свою работу с приложением Muse, в котором больше 350 000 строк кода на Swift.
В общем, если хотели почистить свою кодовую базу, самое время это сделать 🫡
Periphery — это command-line инструмент для поиска неиспользуемого кода в проектах на Swift, который помогает поддерживать чистоту кода без значительных затрат времени.
Автор приводит в пример свою работу с приложением Muse, в котором больше 350 000 строк кода на Swift.
В общем, если хотели почистить свою кодовую базу, самое время это сделать 🫡
🔥4👍2
Swift Language focus areas heading into 2025
Не так давно LSG - Language Steering Group - анонсировала основные фокусные направления на 2025 год:
👉 Несмотря на сильную основу Swift Concurrency в версии 6.0, многие разработчики испытывают трудности с его внедрением, и группа по управлению языком рассматривает идеи для упрощения этого процесса.
👉 Работа над типами Span позволит безопасно читать и записывать массивы объектов в памяти без необходимости управления памятью, что улучшит производительность и безопасность кода.
👉 Swift будет улучшать взаимодействие с C++ через поддержку некопируемых и неуходящих типов, а также разрабатывается библиотечное решение для прямого взаимодействия с Java.
Не так давно LSG - Language Steering Group - анонсировала основные фокусные направления на 2025 год:
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
What are Sendable and @Sendable closures in Swift?
Протокол Sendable и аннотация @Sendable помогают компилятору проверять, может ли объект безопасно передаваться через границы конкурентности, предотвращая состояния гонки.
Структуры и акторы в Swift являются Sendable по умолчанию, если все их члены также соответствуют требованиям Sendable, в то время как классы требуют явного соответствия.
Для классов, которые не могут быть помечены как Sendable, можно использовать @unchecked Sendable, но это требует осторожности, так как это может привести к проблемам с безопасностью потоков.
Протокол 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"
}
👍4
Sending vs Sendable in Swift
Swift 6 вводит новый ключевое слово
В статье приведены примеры кода, показывающие, как использовать
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 месяцев, включая согласование с дизайнерами и тестирование, что сделало процесс интересным и насыщенным.
Очень подробно все описано 😍
Крутая статья про внедрение классной фичи: ребята из Додо сделали Секретную акцию с интересной анимацией.
После ее внедрения, применения выросли на 26%, выручка на 0,6%, а заказы на 0,9%. 54% пользователей на iOS и 69% на Android успешно вытянули акцию.
Разработка фичи заняла около 3 месяцев, включая согласование с дизайнерами и тестирование, что сделало процесс интересным и насыщенным.
Очень подробно все описано 😍
🔥11❤5
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 представил некопируемые типы, которые предотвращают дублирование значений, обеспечивая уникальную собственность и снижая риск ошибок. Это применимо к структурам.
При передаче некопируемых типов в функции необходимо указывать модель владения:
Некопируемые структуры могут иметь деинициализаторы, а оператор
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 представила фреймворк
👉 Фреймворк позволяет обновлять игры и ресурсы без повторной отправки приложения на проверку, а также устраняет ограничения по размеру, ранее установленные для
👉 Разработчики должны определить необходимые файлы, добавить ключи в
❗️ Необходимо быть осторожным с выбором файлов для загрузки, так как их URL могут быть подделаны, что может привести к утечкам данных.
⚠️ Тестирование фреймворка требует отправки приложения на проверку.
С iOS 16 Apple представила фреймворк
Background Assets
, который позволяет разработчикам хранить и автоматически загружать ресурсы приложений вне App Store, улучшая время загрузки и уменьшая размер приложения.On-Demand Resources
.info.plist
и создать манифест для управления загрузками, чтобы обеспечить корректную работу фреймворка.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
objc async selectors
Если вдруг вы захотите сделать objc метод для селектора async - не стоит❌
Автор разбирает похожую ситуацию, где он пометил похожий метод как async:
Также автор разбирает возможную причину такого поведения и вариант обхода такой проблемы.
Если вдруг вы захотите сделать 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
Пару советов по работе с👉 Рекомендуется использовать
👉 Для приложений с целевой версией iOS 18.0 и выше предпочтительно использовать
👉 Для работы в фоновом режиме необходимо добавить соответствующие ключи в настройки приложения и использовать
👉 Для симуляции перемещения можно использовать GPX файлы, однако могут возникнуть проблемы с выбором файлов в Xcode, которые можно решить, изменив настройки системы.
Пару советов по работе с
Core Location:
CLLocationManager
вместо CLMonitor
и CLLocationUpdate
, так как он предлагает больше возможностей и меньше проблем с совместимостью.CLServiceSession
, так как он упрощает управление разрешениями на использование местоположения.CLBackgroundActivitySession
для получения обновлений местоположения.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 для более точного контроля над тестами.
Тестирование функций 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