How to keep Date’s microseconds precision in Swift
DateFormatter в Swift теряет точность микросекунд при конвертации даты и времени, что может привести к потенциальным проблемам, например неправильной сортировке данных.
Автор предлагает использовать расширение ISO8601DateFormatter для ручного извлечения микросекунд из строки даты и добавления их к сконвертированному значению Date.
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)
}
}
⚡2👍2
Псевдоним типа в Swift
Ключевое слово typealias в 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]>
В статье больше примеров с разборами и пояснениями.
🔥11
Как встроить распознавание звуков в ваше iOS приложение на Swift с использованием SoundAnalysis
Если вы хотели попробовать реализовать приложения для распознавания звуков – это статья для вас.
Автор разбирает базовые концепции работы с фреймворком SoundAnalysis. При этом вы можете воспользоваться моделями из коробки, они позволяют распознавать до 300 различных звуков, либо натренировать свою модель через CreateML.
Если вы хотели попробовать реализовать приложения для распознавания звуков – это статья для вас.
Автор разбирает базовые концепции работы с фреймворком SoundAnalysis. При этом вы можете воспользоваться моделями из коробки, они позволяют распознавать до 300 различных звуков, либо натренировать свою модель через CreateML.
Хабр
Как встроить распознавание звуков в ваше iOS приложение на Swift с использованием SoundAnalysis
Введение В мире, где ваш телефон умеет угадывать настроение по плейлисту, почему бы не научить его распознавать звуки вокруг? С помощью фреймворка SoundAnalysis это проще, чем кажется. Мы расскажем,...
🔥5
Прокачайте свой код с @dynamicMemberLookup
Атрибут dynamicMemberLookup в Swift позволяет обращаться к свойствам объекта, как если бы они были статически определены, что упрощает работу с динамическими структурами данных и делает API более гибким и расширяемым.
Но тут есть минус – компилятор не сможет подсказать вам, обращаетесь ли вы к существующему свойству или нет.
В статье разбираются основные моменты при работе с данным атрибутом на примере.
Атрибут dynamicMemberLookup в Swift позволяет обращаться к свойствам объекта, как если бы они были статически определены, что упрощает работу с динамическими структурами данных и делает API более гибким и расширяемым.
json[0]?["name"]?["first"]?.stringValue
// заменится на
json[0]?.name?.first?.stringValue
Но тут есть минус – компилятор не сможет подсказать вам, обращаетесь ли вы к существующему свойству или нет.
В статье разбираются основные моменты при работе с данным атрибутом на примере.
Хабр
Прокачайте свой Swift с @dynamicMemberLookup
Swift — это мощный язык программирования, который сочетает в себе безопасность типов и выразительность. Однако, несмотря на свою строгую типизацию, язык предоставляет разработчикам возможность...
🔥4
Data alignment: Straighten up and fly right
Хорошо проработанная статья на инженерном языке про работу процессора.
Главная мысль – раскрыть концепцию работы процессора: как он обращается к памяти в 2, 4, 8, 16 или 32-байтовых фрагментах, а не в байтовых кусках, как мы привыкли думать.
Хорошо проработанная статья на инженерном языке про работу процессора.
Главная мысль – раскрыть концепцию работы процессора: как он обращается к памяти в 2, 4, 8, 16 или 32-байтовых фрагментах, а не в байтовых кусках, как мы привыкли думать.
⚡3
UNSAFE SWIFT
Уже не новая, но актуальная статья про использование указателей в Swift.
Автор подробно разбирает выравнивание: для чего это может понадобиться, почему порядок типов в объекте имеет значение и как работать с объектами через один из 4 доступных указателей: UnsafeRawPointer, UnsafeMutableRawPointer, UnsafeRawBufferPointer и UnsafeMutableRawBufferPointer
Понимание того, как это работает важно для организации высокопроизводительного кода.
Уже не новая, но актуальная статья про использование указателей в 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
Понимание того, как это работает важно для организации высокопроизводительного кода.
🔥11👀2
Как ускорить запуск iOS-приложения в 2 раза с помощью Network Instrument
Хорошая статья про борьбу с проблемами с сетью в приложениях: изменения порядка запросов, предварительное подключение, устранение редиректов и параллельная загрузка позволили ускорить старт приложения в два раза, сократив время ожидания пользователей.
В статье про использование Network Instrument, который позволяет выявить и решить множество проблем, например, неэффективное использование URLSession, блокирование запросов подключением, долгие редиректы и парсинг больших объемов данных.
Хорошая статья про борьбу с проблемами с сетью в приложениях: изменения порядка запросов, предварительное подключение, устранение редиректов и параллельная загрузка позволили ускорить старт приложения в два раза, сократив время ожидания пользователей.
В статье про использование Network Instrument, который позволяет выявить и решить множество проблем, например, неэффективное использование URLSession, блокирование запросов подключением, долгие редиректы и парсинг больших объемов данных.
Хабр
Как ускорить запуск iOS-приложения в 2 раза с помощью Network Instrument
Приложение — это соединение данных из сети с графическим интерфейсом. Про UI статей много, но про сеть почти никто не вспоминает, а ведь именно она влияет на время ожидания ответа пользователем. При...
🔥5
Как реализовать спойлер-эффект как в Telegram на Swift?
Очень хорошая статья с подробными разборами и комментариями о том, как создать вот такое:спойлер .
Для достижения нужного эффекта автор использует CAEmitterLayer. Однако, помимо лейера тут еще очень много различных тонкостей, которые с первого взгляда не очевидны.
Очень хорошая статья с подробными разборами и комментариями о том, как создать вот такое:
Для достижения нужного эффекта автор использует CAEmitterLayer. Однако, помимо лейера тут еще очень много различных тонкостей, которые с первого взгляда не очевидны.
Хабр
Как реализовать спойлер-эффект как в Telegram на Swift?
Спойлеры стали неотъемлемой частью общения в мессенджерах и социальных сетях. Они позволяют скрывать часть информации до тех пор, пока пользователь не захочет ее увидеть. В Telegram спойлер-эффект...
🔥4❤1
Beware UserDefaults: a tale of hard to find bugs, and lost data
Статья про неочевидные проблемы использования UserDefaults: автор столкнулся с необычным поведением, когда UserDefaults стал помечаться как данные, которые требуют шифрования и не доступны до разблокировки устройства. И пользовательские данные просто терялись.
Автор предлагает несколько решений, включая проверку isProtectedDataAvailable и использование собственной реализации UserDefaults для надежного доступа к данным.
Статья про неочевидные проблемы использования UserDefaults: автор столкнулся с необычным поведением, когда UserDefaults стал помечаться как данные, которые требуют шифрования и не доступны до разблокировки устройства. И пользовательские данные просто терялись.
Автор предлагает несколько решений, включая проверку isProtectedDataAvailable и использование собственной реализации UserDefaults для надежного доступа к данным.
Christianselig
Beware UserDefaults: a tale of hard to find bugs, and lost data
Excuse the alarmist title, but I think it’s justified, as it’s an issue that’s caused me a ton of pain in both support emails and actually tracking it down, so I want to make others aware of it so they don’t similarly burned.
Brief intro
For the uninitiated…
Brief intro
For the uninitiated…
🔥3
The perfect iOS networking layer does not exist - Part 1
Несмотря на название, автор приводит пример написания достаточно универсального и самодостаточного сетевого слоя.
Внутри используется async/await, а также внедряются промежуточные сущности для модификации уже собранных реквестов, например, логированием.
Несмотря на название, автор приводит пример написания достаточно универсального и самодостаточного сетевого слоя.
Внутри используется async/await, а также внедряются промежуточные сущности для модификации уже собранных реквестов, например, логированием.
calin.crist()
The perfect iOS networking layer does not exist - Part 1
Of course not. But there are great starting points to build a modular, extensible, and testable networking layer in iOS using Swift.
🔥5
The perfect iOS networking layer does not exist - Part 2
Продолжение статьи про написание сетевого слоя.
В этой части разбирается подход к тестированию уже написанного ранее слоя. Это часто бывает полезно и удобно, когда сам бекэнд еще не готов, а фронт уходит вперед. Покрытие самого клиента, сервиса запросов, а также middleware сущностей.
Будет полезным для тех, кто немного работал с тестами – дает базовое понимание о том, каким образом можно писать тесты.
Продолжение статьи про написание сетевого слоя.
В этой части разбирается подход к тестированию уже написанного ранее слоя. Это часто бывает полезно и удобно, когда сам бекэнд еще не готов, а фронт уходит вперед. Покрытие самого клиента, сервиса запросов, а также middleware сущностей.
Будет полезным для тех, кто немного работал с тестами – дает базовое понимание о том, каким образом можно писать тесты.
calin.crist()
The perfect iOS networking layer does not exist - Part 2
Of course not. But there are great starting points to build a modular, extensible, and testable networking layer in iOS using Swift. Part 2 covers unit and integration tests.
🔥3
Calculating the semantic distance between words with the Natural Language framework
Natural Language framework позволяет компьютерам понимать и взаимодействовать с человеческим языком, обрабатывать и анализировать текстовые данные, извлекать значимую информацию и понимать отношения между словами и фразами.
Класс NLEmbedding позволяет создавать векторное пространство, в котором строки представлены в виде векторов, и рассчитывать семантическое расстояние между словами, а также находить синонимы.
Это может понадобиться для создания приложений, которые анализируют текст на смысловые связи или создание чат ботов с адекватными ответами на запросы.
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
}
}
}
🔥3❤2👍2
Faster iOS Networking with Shared Dictionary Compression
Сетевые задержки остаются проблемой для пользовательского опыта на iOS устройствах, и одним из способов улучшения этой ситуации является использование shared dictionary compression.
Что такое shared dictionary compression?
Это метод сжатия, при котором клиент и сервер обмениваются копией некоторых данных (словаря), что позволяет уменьшить размер запросов.
Использование shared dictionary compression может привести к значительному улучшению времени загрузки, особенно для пользователей со слабыми или ненадежными сетевыми соединениями.
Однако, стоит понимать, что без доработок со стороны бекэнда данная практика невозможна 🫢
Сетевые задержки остаются проблемой для пользовательского опыта на iOS устройствах, и одним из способов улучшения этой ситуации является использование shared dictionary compression.
Что такое shared dictionary compression?
Это метод сжатия, при котором клиент и сервер обмениваются копией некоторых данных (словаря), что позволяет уменьшить размер запросов.
Использование shared dictionary compression может привести к значительному улучшению времени загрузки, особенно для пользователей со слабыми или ненадежными сетевыми соединениями.
Однако, стоит понимать, что без доработок со стороны бекэнда данная практика невозможна 🫢
👍5🤯1
Корзина в Додо Пицце на iOS 14: баг длиной в полгода
Интересная история фикса бага, который долго не могли отловить.
Иногда, даже самые некритичные баги могут подсказать слабые места в коде. А с учетом обновлений оси они могут возникать неожиданно и в самых неочевидных местах.
Сама же проблема была простая: после редизайна приложения Додо Пиццы, кнопка корзины стала невидимой для пользователей на iOS 14, вызывая жалобы и проблемы с отображением стоимости продуктов. И фикс был в пару строк 🫣
Интересная история фикса бага, который долго не могли отловить.
Иногда, даже самые некритичные баги могут подсказать слабые места в коде. А с учетом обновлений оси они могут возникать неожиданно и в самых неочевидных местах.
Сама же проблема была простая: после редизайна приложения Додо Пиццы, кнопка корзины стала невидимой для пользователей на iOS 14, вызывая жалобы и проблемы с отображением стоимости продуктов. И фикс был в пару строк 🫣
👍5❤1👎1🤔1🤬1
Beginner’s Guide to Protocol Buffers and gRPC with Swift
Отличная статья про Protocol Buffer или «protobuf», разбираются основные особенности его использования и gRPC.
Также автор описывает подробные шаги по настройке базового сервера gRPC в Swift с использованием библиотек Swift Protobuf и gRPC, включая создание структур данных Swift, создание интерфейса gRPC и внедрение интерфейса на стороне сервера.
Кстати, для сети он использует акторы и async/await.
Отличная статья про 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.iss.onessage.todoID })
else {
return .init(
error: RPCError.init(
code: .notFound,
message: "Todo not found."
)
)
}
todo.completed = true
todos = todos.filter { $0.todoID != request.iss.onessage.todoID }
todos.append(todo)
return .init(message: todo)
}
🔥4
Азартная разработка iOS приложения игры 2048 с ChatGPT
Объемная и подробная статья про совместную разработку с ChatGPT известной игры 2048.
Также в игру вводится новый элемент: ИИ - алгоритм, который будет автоматически ходить. В качестве примера были взяты два: Monte Carlo и Expectimax
Все достаточно подробно описано и сопровождается обильным количеством скриншотов.
Объемная и подробная статья про совместную разработку с ChatGPT известной игры 2048.
Также в игру вводится новый элемент: ИИ - алгоритм, который будет автоматически ходить. В качестве примера были взяты два: Monte Carlo и Expectimax
Все достаточно подробно описано и сопровождается обильным количеством скриншотов.
🔥4
Why Do View Controllers Need init(coder:)?
Класс UIViewController поддерживает протокол NSCoding, что требует реализации инициализатора init(coder:), даже если он не используется напрямую.
Даже при создании view controllers программно, необходимо использовать UIStoryboards, которые в процессе создания используют NSCoding для воссоздания состояния view controller и его представлений.
Класс UIViewController поддерживает протокол NSCoding, что требует реализации инициализатора init(coder:), даже если он не используется напрямую.
Даже при создании view controllers программно, необходимо использовать UIStoryboards, которые в процессе создания используют NSCoding для воссоздания состояния view controller и его представлений.
🔥2👎1
Swift TaskGroup на примерах
Если вы хотели разобраться в особенностях применения TaskGroup и чем она отличается от Task и async let, то эта статья для вас.
Приводятся примеры использования TaskGroup для решения конкурентных тасок, включая обработку ошибок, отмену операций и автоматическая отмена дочерних задач.
Также есть примеры работы с AsyncStream.
Если вы хотели разобраться в особенностях применения TaskGroup и чем она отличается от Task и async let, то эта статья для вас.
Приводятся примеры использования TaskGroup для решения конкурентных тасок, включая обработку ошибок, отмену операций и автоматическая отмена дочерних задач.
Также есть примеры работы с AsyncStream.
❤4🔥3🤬1
How Do Binaries work together? What breaks ABI?
Для успешной работы двух библиотек необходимо обеспечить совместимость как API (интерфейс программирования приложений), так и ABI (бинарный интерфейс приложений). Изменения, такие как удаление существующих функций, изменение их имен или добавление новых параметров, могут привести к нарушению ABI.
В статье достаточно подробно описан процесс работы ABI/API стабильности и какие изменения не приведут к нарушению.
Для успешной работы двух библиотек необходимо обеспечить совместимость как API (интерфейс программирования приложений), так и ABI (бинарный интерфейс приложений). Изменения, такие как удаление существующих функций, изменение их имен или добавление новых параметров, могут привести к нарушению ABI.
В статье достаточно подробно описан процесс работы ABI/API стабильности и какие изменения не приведут к нарушению.
🔥2