viewIsAppearing
Некоторые могли пропустить, но на WWDC 2023 было представлено важное дополнение про жизненный цикл контроллера.
Этот метод вызывается после вызова viewWillAppear и перед вызовом viewWillLayoutSubviews. Отлично подходит для fine-tune'а динамического интерфейса или самой презентации контроллера.
Некоторые могли пропустить, но на WWDC 2023 было представлено важное дополнение про жизненный цикл контроллера.
Этот метод вызывается после вызова viewWillAppear и перед вызовом viewWillLayoutSubviews. Отлично подходит для fine-tune'а динамического интерфейса или самой презентации контроллера.
Apple Developer Documentation
viewIsAppearing(_:) | Apple Developer Documentation
Notifies the view controller that the system is adding the view controller’s view to a view hierarchy.
❤🔥9
Typed throws in Swift
В Swift 6.0 изменили привычный подход работы с выбрасываемыми ошибками: в прошлых версиях нельзя было указать конкретный тип. Теперь компилятор будет понимать какую именно ошибку мы будем выбрасывать.
В месте использования нам теперь не нужно лишнее приведение типов.
В Swift 6.0 изменили привычный подход работы с выбрасываемыми ошибками: в прошлых версиях нельзя было указать конкретный тип. Теперь компилятор будет понимать какую именно ошибку мы будем выбрасывать.
enum FooError: Error {
case tooBig
case tooSmall
}
func foo() throws(FooError) -> Int {
let value = Int.random(in: 1...100)
guard value < 60 else {
throw FooError.tooBig
}
guard value > 20 else {
throw FooError.tooSmall
}
return value
}
В месте использования нам теперь не нужно лишнее приведение типов.
func boo() {
do {
let value = try foo()
print(value)
} catch {
switch error {
case .tooBig:
print("Too big...")
case .tooSmall: print("Too small...")
}
}
}
⚡27
Performance Testing для iOS
Для тестирования производительности iOS приложений существуют различные способы, включая использование Xcode Organizer, MetricKit и TestFlight для анализа показателей запуска, отзывчивости интерфейса, потребления памяти и других аспектов.
В статье разобраны различные способы сбора метрик, в том числе использование блока measure для измерения производительности кода, создание signpost'ов, а также запись данных и последующий анализ результатов для определения трендов.
Для тестирования производительности iOS приложений существуют различные способы, включая использование Xcode Organizer, MetricKit и TestFlight для анализа показателей запуска, отзывчивости интерфейса, потребления памяти и других аспектов.
В статье разобраны различные способы сбора метрик, в том числе использование блока measure для измерения производительности кода, создание signpost'ов, а также запись данных и последующий анализ результатов для определения трендов.
Хабр
Performance Testing для iOS
Все мы любим, когда приложение, которым пользуемся, работает отзывчиво, быстро, а также те операции, которые мы хотим совершить, происходили максимально быстро: буть то банковское приложение или...
⚡7❤2
Upload iOS App to TestFlight with GitHub Actions and Fastlane Match
Если вы проводите деплой приложения руками и вас это достало, то это статья для вас. Автор рассказывает, как провести настройку деплоя используя fastlane, связке с GitHub Secrets для хранения ключей и GitHub actions для построения полноценного workflow.
Неплохая статья для понимания того, как работает Continuous Deployment.
Если вы проводите деплой приложения руками и вас это достало, то это статья для вас. Автор рассказывает, как провести настройку деплоя используя fastlane, связке с GitHub Secrets для хранения ключей и GitHub actions для построения полноценного workflow.
Неплохая статья для понимания того, как работает Continuous Deployment.
Bright Inventions
Upload iOS App to TestFlight with GitHub Actions and Fastlane Match – 2025 Tutorial with Example
In previous parts of a tutorial we were building app and running tests locally with fastlane and building app and running tests with usage…
⚡3🔥2
Marking Swift Properties Available by iOS Version
В текущих версиях Swift мы можем пометить структуры, классы и расширения доступными для определенных версий ОС.
Но не можем так поступить со свойствами. В статье предлагается способ сделать это с помощью старого доброго NSObject и вычисляемого свойства, для достижения такого же результата.
В текущих версиях Swift мы можем пометить структуры, классы и расширения доступными для определенных версий ОС.
@available(iOS 18.0, *)
struct GetQuoteControlWidget: ControlWidget {
// code
}
Но не можем так поступить со свойствами. В статье предлагается способ сделать это с помощью старого доброго NSObject и вычисляемого свойства, для достижения такого же результата.
private var _customTool: NSObject? = nil
@available(iOS 18.0, *)
private var customToolWrapper: PKToolPickerCustomItem {
if _customTool == nil {
let tool = PKToolPickerCustomItem(configuration: .init(identifier: someID, name: someName))
_customTool = tool
}
return _customTool as! PKToolPickerCustomItem
}
⚡7
SWIFT BUILD TIMES AND MODULE VERIFICATION
После расширения кодовой базы и рефакторинга, автор разбил приложение на множество модулей и стал замечать просадки в сборке проекта. После исследования он обнаружил, что флаг
Но стоит понимать, что этот флаг не панацея и он лишь экономит время сборки, пропуская один из этапов и перед отправкой релизной сборки его все же стоит включить обратно.
После расширения кодовой базы и рефакторинга, автор разбил приложение на множество модулей и стал замечать просадки в сборке проекта. После исследования он обнаружил, что флаг
ENABLE_MODULE_VERIFIER
был установлен в YES
. Сам флаг отвечает за верификацию модулей на этапе сборки. Автор выключил этот флаг для дебаг сборок и уменьшил время с 3,5 минут до 52 секунд.Но стоит понимать, что этот флаг не панацея и он лишь экономит время сборки, пропуская один из этапов и перед отправкой релизной сборки его все же стоит включить обратно.
pfandrade.me
Swift Build Times and Module Verification…
It’s been a while since I’ve written anything here… I guess that’s mainly because I was focusing on building Secrets 4 and did not want to write about it before it launched. Then, I lost the habit of actually writing stuff here. Let’s see if I can change…
⚡5
Benchmark Package
Не так давно был представлен новый пакет Benchmark. Его основная цель – измерение производительности. Количество метрик из коробки большое: 27.
Так же можно добавлять свои метрики.
На выходе будем получать таблицу с измерениями. Но можно сохранять данные и в других форматах.
Выглядит круто и работоспособно.
Не так давно был представлен новый пакет Benchmark. Его основная цель – измерение производительности. Количество метрик из коробки большое: 27.
Так же можно добавлять свои метрики.
На выходе будем получать таблицу с измерениями. Но можно сохранять данные и в других форматах.
Выглядит круто и работоспособно.
⚡5
Борьба с утечками памяти: от задачи до победы
Классное видео с мобиуса про борьбу с утечками памяти: тут и про работу с Memory Graph, про который не так много документации и примеры про автоматизацию поиска утечек через UI тесты.
Классное видео с мобиуса про борьбу с утечками памяти: тут и про работу с Memory Graph, про который не так много документации и примеры про автоматизацию поиска утечек через UI тесты.
⚡10
Антимат в чате на iOS: как я мешаю пользователям сквернословить
Автор делится опытом, как в чате мешал пользователям сквернословить с помощью локальных регулярных выражений. Как итог: получилось хорошо и понятно как можно дальше улучшать, но все равно, если пользователь захочет написать запрещенное слово, то он найдет способ это сделать с помощью комбинаций букв и цифр, юникод символы и прочих хитростей.
Как MVP точно пойдет и не факт, что продуктово имеет смысл делать что-то лучше.
Автор делится опытом, как в чате мешал пользователям сквернословить с помощью локальных регулярных выражений. Как итог: получилось хорошо и понятно как можно дальше улучшать, но все равно, если пользователь захочет написать запрещенное слово, то он найдет способ это сделать с помощью комбинаций букв и цифр, юникод символы и прочих хитростей.
Как MVP точно пойдет и не факт, что продуктово имеет смысл делать что-то лучше.
Хабр
Антимат в чате на iOS: как я мешаю пользователям сквернословить
Привет, Хабр! На связи снова Александр Пиманов (по-прежнему iOS-разработчик МТС Диджитал). Сегодня поделюсь своим опытом в одной интересной нишевой теме: фильтрации нецензурной лексики в приложении...
⚡4
Morphology in Swift
Проблемы с морфологией в программировании могут привести к неправильному склонению слов и неправильному грамматическому согласованию в предложениях.
С iOS 15 Foundation предлагает решение этой проблемы, позволяя автоматически обрабатывать такие ситуации и термины обращения в локализованных строках.
Для более точного управления в Swift можно использовать структуру Morphology, позволяющую выполнять ручное согласование грамматики во время выполнения.
Проблемы с морфологией в программировании могут привести к неправильному склонению слов и неправильному грамматическому согласованию в предложениях.
С iOS 15 Foundation предлагает решение этой проблемы, позволяя автоматически обрабатывать такие ситуации и термины обращения в локализованных строках.
Text("She will receive ^[\(count) games](inflect: true).")
Для более точного управления в Swift можно использовать структуру Morphology, позволяющую выполнять ручное согласование грамматики во время выполнения.
Swiftjective-C
Morphology in Swift
Morphology, or for mere humans - the study of the many forms of words, is ripe with interesting programming applications. Let's take a look at a few of them.
⚡5
Wrapping async-await with a completion handler in Swift
Статья про то, как обернуть async-await кода в completion handler. Вы столкнетесь с таким, например, если используете сторонние библиотеки, которые принимают только хендлеры, а ваша кодовая база на основе Swift Concurrency.
Статья про то, как обернуть async-await кода в completion handler. Вы столкнетесь с таким, например, если используете сторонние библиотеки, которые принимают только хендлеры, а ваша кодовая база на основе Swift Concurrency.
extension Task {
@discardableResult
init<T>(
priority: TaskPriority? = nil,
operation: @escaping () async throws -> T,
queue: DispatchQueue = .main,
completion: @escaping (Result<T, Failure>) -> Void
) where Success == Void, Failure == any Error {
self.init(priority: priority) {
do {
let value = try await operation()
queue.async {
completion(.success(value))
}
} catch {
queue.async {
completion(.failure(error))
}
}
}
}
}
⚡2
The Memory Leak: An Xcode Detective Story
История о том, как инженер пытался отладить простой по описанию баг и как глубоко он зашел. Если очень коротко, то проблема была в неправильном использовании
Понимание механизмов работы с памятью помогает избегать таких ситуаций.
История о том, как инженер пытался отладить простой по описанию баг и как глубоко он зашел. Если очень коротко, то проблема была в неправильном использовании
[weak self]
в кложуре 🫠Понимание механизмов работы с памятью помогает избегать таких ситуаций.
Emergetools
Emerge Tools Blog | The Memory Leak: An Xcode Detective Story
A deep-dive into debugging on iOS
❤4🔥2⚡1
Announcing Swift 6
Анонсировали релиз Swift 6 🥳 и нас ждет очень много изменений, вот небольшой список:
- поддержка 128-битных целых чисел
- новая библиотека синхронизации, которая включает примитивы, такие как mutex
- новый подход к выбрасыванию ошибок
- владение некопируемых типов
- расширение интеропа с C++
- новый макрос для отображения информации в LLDB @DebugDescription
- фреймворк для тестирования Swift Testing
Анонсировали релиз Swift 6 🥳 и нас ждет очень много изменений, вот небольшой список:
- поддержка 128-битных целых чисел
- новая библиотека синхронизации, которая включает примитивы, такие как mutex
- новый подход к выбрасыванию ошибок
- владение некопируемых типов
- расширение интеропа с C++
- новый макрос для отображения информации в LLDB @DebugDescription
- фреймворк для тестирования Swift Testing
Swift.org
Announcing Swift 6
We’re delighted to announce the general availability of Swift 6. This is a major new release that expands Swift to more platforms and domains.
🔥10
AVAudioSourceNode, AVAudioSinkNode: Low-Level Audio In Swift
AVAudioSourceNode – узлы AVAudio, предоставляющие способ обработки входных и выходных аудиоданных. Для работы с аудио в режиме реального времени, придется выйти на уровень работы с указателями через UnsafeMutableAudioBufferListPointer и UnsafeMutableBufferPointer. Стоит помнить, что в таком случае управление памятью ложиться на плечи разработчика.
Если вам интересна работа со звуком на низком уровне – эта статья точно для вас.
AVAudioSourceNode – узлы AVAudio, предоставляющие способ обработки входных и выходных аудиоданных. Для работы с аудио в режиме реального времени, придется выйти на уровень работы с указателями через UnsafeMutableAudioBufferListPointer и UnsafeMutableBufferPointer. Стоит помнить, что в таком случае управление памятью ложиться на плечи разработчика.
Если вам интересна работа со звуком на низком уровне – эта статья точно для вас.
Orestis Papadopoulos
AVAudioSourceNode, AVAudioSinkNode: Low-Level Audio In Swift
I'm Orestis Papadopoulos. I work as a software developer. This is my blog, I write about software, sounds and Swift.
🔥3
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