Secret Management on iOS
🙅♂️ Если по какой-то причине вы храните токены или ключи в исходном коде - у меня для вас плохие новости: так не стоит делать
⚠️ Секреты не следует хранить в исходном коде или в файлах конфигурации Xcode, так как они могут быть доступны в скомпилированном приложении. Вместо этого рекомендуется использовать серверное хранение.
⚠️ Обфускация секретов с помощью генерации кода и шифрования может затруднить их извлечение, но не гарантирует полной безопасности.
❓ Лучший способ защитить секреты — это не хранить их на клиенте. Если это невозможно, следует рассмотреть возможность использования серверного хранения и обфускации для снижения рисков.
ℹ️ Исследования показывают, что тысячи секретов, таких как API-ключи, ежедневно утечка на платформах, таких как GitHub, что подчеркивает важность безопасного управления секретами.
Пусть статья и не новая, но актуальная.
Пусть статья и не новая, но актуальная.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Взлом через картинку в Apple: уроки громкой уязвимости для разработчиков
🚨 Уязвимость
‼️ Атака может происходить без взаимодействия пользователя (
🔼 Пользователям рекомендуется обновлять свои устройства до последних версий
❓ Для предотвращения подобных уязвимостей необходимо внедрять процессы безопасной разработки, включая фаззинг и статический анализ кода, а также использовать методы защиты от реверс-инжиниринга.
PT-2025-34177 (CVE-2025-43300)
в системном фреймворке ImageIO
позволяет злоумышленникам выполнять произвольный код через вредоносные изображения, что ставит под угрозу миллионы устройств Apple.zero-click
), что делает её особенно опасной, так как уязвимость использовалась в реальных атаках на конкретных людей.iOS/Android
для уменьшения риска быть атакованным и избегать открытия подозрительных файлов, особенно если они приходят как документы.Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Debugging Swift Concurrency: “Am I on the Main Actor?”
В
⚠️ Используйте
❓ Можно создавать собственные актеры с помощью
➡️ Используйте информацию о очереди в
В
Swift 6
важно думать не о потоках, а о акторах, чтобы избежать ошибок с доступом к пользовательскому интерфейсу и тяжелым вычислениям. MainActor.assertIsolated()
для проверки, что код выполняется на главном актере, что помогает выявить ошибки во время разработки. @globalActor,
что позволяет использовать аналогичные методы проверки изоляции.Xcode
для понимания контекста выполнения актеров и отладки проблем с многопоточностью.Please open Telegram to view this post
VIEW IN TELEGRAM
⚡6
Жизненный цикл UIViewController в 2025 году: что изменилось и что устарело
🔍 Методы
⌛ Классический жизненный цикл
🔗 Для корректного управления дочерними контроллерами необходимо использовать методы
➡️ Рекомендуется использовать методы
➡️ Методы для восстановления состояния, такие как
viewDidUnload
и didReceiveMemoryWarning
устарели, в то время как новые хуки, такие как viewIsAppearing
и viewSafeAreaInsetsDidChange
, стали стандартом для работы с UIViewController
.UIViewController
включает методы инициализации, загрузки представления, а также методы для управления отображением и изменениями окружения.addChild
и removeFromParent
, чтобы обеспечить правильное получение событий жизненного цикла.updateViewConstraints
и traitCollectionDidChange
для адаптации интерфейса к изменениям окружения, таким как смена темы или ориентации устройства.encodeRestorableState
и decodeRestorableState
, остаются актуальными, однако большинство разработчиков предпочитают использовать UserDefaults
или CoreData
для сохранения данных.Please open Telegram to view this post
VIEW IN TELEGRAM
1👍6
Debug crashes in iOS using MetricKit
⚠️
❓ Для начала работы с
ℹ️ Отчеты о сбоях обрабатываются с помощью метода
🔍 Для тестирования реализации
MetricKit
— это система для сбора и анализа отчетов о сбоях на уровне системы, которая была введена в iOS 13, позволяя выявлять сбои, которые традиционные инструменты не могут зафиксировать.MetricKit
необходимо импортировать его в AppDelegate
и подписаться на протокол MXMetricManagerSubscriber
, чтобы получать отчеты о сбоях.handleCrashDiagnostics
, который позволяет логировать краткие сводки, анализировать стек вызовов и архивировать информацию о сбоях.MetricKit
можно симулировать сбои, такие как выход за пределы массива или принудительное развертывание nil
, и проверить, как система реагирует на эти сбои.class AppDelegate: UIResponder, UIApplicationDelegate, MXMetricManagerSubscriber {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Register as a subscriber to receive metrics and diagnostics
MXMetricManager.shared.add(self)
return true
}
// Implement the required delegate method for diagnostics
func didReceive(_ payloads: [MXDiagnosticPayload]) {
// Process crash reports
for payload in payloads {
if let crashDiagnostics = payload.crashDiagnostics {
handleCrashDiagnostics(crashDiagnostics)
}
}
}
func applicationWillTerminate(_ application: UIApplication) {
// Unsubscribe when the app terminates
MXMetricManager.shared.remove(self)
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡2👍1
ARC в Swift
🎉 Всех с прошедшим Днем программиста! И чтобы не забывать основы - принес статью про механизм подсчета ссылок.
❓
⚠️ Циклы сильных ссылок (
🔗
⚙️ ARC работает на уровне
✔️ Автоматический подсчет ссылок упрощает управление памятью, избавляя разработчиков от необходимости вручную управлять ссылками, что делает код более лаконичным и понятным.
ARC (Automatic Reference Counting)
- это метод управления памятью в Swift
, который автоматически отслеживает количество сильных ссылок на объекты и освобождает их, когда счётчик достигает нуля.retain cycles
) могут возникать, когда два объекта ссылаются друг на друга, что мешает ARC освободить память. Это может привести к утечкам памяти.Weak
ссылки не учитываются ARC при подсчёте ссылок, что помогает избежать retain cycles
, в то время как unowned
ссылки никогда не становятся nil
, но могут крашнуть приложение при обращении к уничтоженному объекту.SIL (Swift Intermediate Language)
, где компилятор автоматически добавляет инструкции подсчёта ссылок, что делает код более чистым и безопасным.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6❤2👍2
Swift 6.2 Released
⚡️ Swift 6.2 выпущена 15 сентября. Кратко, что нового.
❓ Упрощенное написание безопасного параллельного кода с помощью новых атрибутов, таких как
🔒 В новой версии добавлены типы
🔥 Расширение Swift для VS Code теперь официально подтверждено и включает функции, такие как фоновая индексация и встроенная отладка с LLDB.
❓ Swift 6.2 теперь поддерживает WebAssembly, позволяя создавать приложения для браузеров и других сред выполнения.
⚙️ Библиотеки Swift 6.2 включают новый пакет
@concurrent,
и делает код однопоточным по умолчанию. InlineArray и Span,
которые обеспечивают безопасный доступ к памяти и высокую производительность без дополнительных затрат. Subprocess
для управления внешними процессами и улучшенный API для NotificationCenter.
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡6👍2❤1🔥1
Не могу не поделиться важной и крутой инфой: мой друг выпустил 10 часовой бесплатный курс!!! про iOS разработку для начинающих 🔥
Если вы начали изучать Swift – обязательно к просмотру. И не забывайте делиться с теми, кто тож хочет начать этот увлекательный путь.
https://www.youtube.com/watch?v=SUKocLwjA5k
Если вы начали изучать Swift – обязательно к просмотру. И не забывайте делиться с теми, кто тож хочет начать этот увлекательный путь.
https://www.youtube.com/watch?v=SUKocLwjA5k
YouTube
Swift - полный курс для начинающих iOS разработчиков. Это БАЗА – Теория, практика, домашки
Swift - полный курс для начинающих. База для iOS разработчиков, которые хотят построить успешную карьеру
Тренировка собеседования по iOS разработке https://t.iss.one/emma_in_it_bot
Решение реальных задач по верстке из Big Tech с тестированием и ревью кода h…
Тренировка собеседования по iOS разработке https://t.iss.one/emma_in_it_bot
Решение реальных задач по верстке из Big Tech с тестированием и ревью кода h…
🔥8👍5❤2
Как Swift Runtime влияет на производительность iOS-приложений
⚡️ Тут наши ребята рассказывают про производительность - супер объемный и полезный обзор. Вот лишь несколько моментов.
⚙️
‼️ Метод
⚠️ Рекомендуется избегать использования
🤫 Использование
соответствия для каждого протокола.
💯 Рекомендую к прочтению.
Swift Runtime
играет ключевую роль в производительности iOS-приложений, особенно в управлении памятью и проверке соответствия типов, что может значительно замедлить работу приложения.swift_conformsToProtocolMaybeInstantiateSuperclasses
является узким местом производительности, так как он может занимать от 1 до 3 мс на каждом вызове, особенно при использовании операторов as?
и as!
или методов String(describing:)
и String(reflecting:)
.String(describing:)
и операторов as?
и as!
, а также минимизировать использование type-generic-constraint
-ов для повышения производительности приложения.type-generic-constraint
-ов может значительно замедлить приложение, так как каждый вызов метода swift_conformsToProtocolMaybeInstantiateSuperclasses
требует проверки соответствия для каждого протокола.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2
Swift Default Value in String Interpolations
🔥 Swift 6.2 улучшает интерполяцию строк с опциональными значениями, позволяя использовать параметр значения по умолчанию.
❓ При интерполяции строк с опционалами компилятор выдает предупреждение, если не указано значение по умолчанию.
🤫 Теперь можно использовать новый параметр по умолчанию в строке, чтобы она не зависела от типа опционального значения. Однако, он не будет работать с локализацией:
LocalizedStringKey
не поддерживает такой формат.
// The count is not set
Text("The count is \(count, default: "not set")")
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Строки в Swift
❓ Строки в Swift представляют собой контейнеры для символов и являются типами значений, что отличает их от многих других языков программирования.
➡️ Для доступа к символам в строках Swift используется специальный тип индекса
🖥 Строки могут быть представлены в различных кодировках, таких как
➡️ Строки Swift могут быть конвертированы в
String.Index,
а не обычные целые числа, что связано с особенностями представления символов. unicodeScalars, utf16
и utf8,
каждая из которых имеет свои особенности и количество кодовых точек. Сами же строки используют оптимизацию Copy-on-Write, что позволяет эффективно управлять памятью и ускорять доступ к данным. NSString
и обратно, что позволяет использовать их в проектах, где смешиваются Swift и Objective-C.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Command tools, threads and QoS
Почему супер навороченные новые мак не могут быстро сжать большую папку через🤕
❓ macOS использует различные уровни
ℹ️ Однопоточные процессы, такие как
Почему супер навороченные новые мак не могут быстро сжать большую папку через
tar?
Крайне интересная статья, которая поможет лучше разбираться в многопоточности на примере реальной задачи архивирования. Вот краткое содержание.QoS
для распределения потоков по ядрам процессора, что влияет на производительность. QoS
варьируется от 9 (background) до 33 (userInteractive).tar
, значительно медленнее многопоточных альтернатив, которые могут использовать все доступные производительные ядра.Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Feature flags in Swift
🚩
❓ По умолчанию в
🔥 Создание перечисления
ℹ️ Такой механизм следует рассматривать как временный инструмент и удалять флаги, когда функция готова. Рассмотрите возможность удаленной настройки для мгновенного включения или отключения функций. Крайне полезный инструмент.
Feature flags
в Swift позволяют включать и отключать определенные функциональности. В статье автор приводит в пример в зависимости от конфигурации сборки, таких как Debug
, TestFlight
и App Store
.Xcode
есть две конфигурации: Debug
и Release
. Рекомендуется создавать дубликаты для App Store
и TestFlight
для управления функциональностью.Distribution
и структуры FeatureFlags
позволяет управлять доступом к функциям в зависимости от текущей конфигурации сборки.public struct FeatureFlags: Sendable, Decodable {
public let requirePaywall: Bool
public let requireOnboarding: Bool
public let featureX: Bool
public init(distribution: Distribution) {
switch distribution {
case .debug:
self.requirePaywall = true
self.requireOnboarding = true
self.featureX = true
case .appstore:
self.requirePaywall = true
self.requireOnboarding = true
self.featureX = false
case .testflight:
self.requirePaywall = false
self.requireOnboarding = true
self.featureX = true
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
How to unwrap [weak self] in Swift Concurrency Tasks?
🔍 В Swift, использование
❌ Создание неструктурированного
✔️ Для предотвращения сильного удержания
❓ При выполнении длительных задач, таких как загрузка нескольких страниц, перемещение
[weak self]
в замыканиях помогает избежать циклов удержания, но не всегда необходимо, особенно для не-escaping
замыканий.Task
может привести к утечкам памяти, если [weak self]
используется неправильно, так как Task
начинает выполняться сразу после его создания.Task { [weak self] in
guard let self else { return } // это не решает проблему
let data = await loadData()
let models = await processData(data)
}
self
в Task
, рекомендуется проверять наличие self внутри тела цикла или использовать self?
для избежания распаковки.guard let self
внутрь цикла позволяет избежать удержания self
дольше, чем это необходимо.Task { [weak self] in
let data = await loadData()
guard self != nil else { return }
guard let models = await self?.processData(data) else {
return
}
// use models
}
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡4👎2🔥1
Derived Data: 5 Things iOS Developers Do Wrong
😐 Многие разработчики iOS не понимают, для чего предназначена папка
❓ Удаление всей папки
ℹ️ Инструменты, такие как
🔍 Разработчики должны исследовать содержимое папки сборки для выявления неиспользуемых ресурсов и оптимизации размера приложения.
🖥
Derived Data
, что может привести к неэффективному использованию её возможностей.Derived Data
может замедлить процесс сборки, так как каждый проект имеет свою собственную папку, и удаление её требует повторной компиляции всех зависимостей.RocketSim
, могут помочь командам отслеживать время сборки и выявлять узкие места, что может значительно повысить производительность.Xcode
предоставляет простой способ доступа к папке Derived Data
через настройки, что облегчает её использование.Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Массивы в Swift
🟢 Принес очередную базу.
ℹ️ Массивы в
❓ Добавление элементов в массив происходит за амортизированное константное время, однако при расширении массива может потребоваться больше времени из-за копирования элементов.
⚠️ Массивы в
👀 Они представляют собой обертку над буфером, который хранит данные в куче. В зависимости от наличия
❓ Swift реализует механизм
❓
Swift
- это структуры данных, которые хранят коллекции элементов одного типа и поддерживают доступ по индексу за O(1)
.Swift
являются типами значений, что означает, что изменения в одном массиве не затрагивают его копии. Для работы с ссылочными типами необходимо использовать глубокое копирование.Objective-C runtime
, используются разные типы буферов.Copy-on-Write
, который позволяет избежать ненужного копирования данных до момента их изменения.ArraySlice
позволяет работать с подмножеством элементов массива без их копирования, что экономит память и время.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1
Разбираемся с existential container в Swift
❓
⚙️
❓
❗️ В отличие от дженериков, которые используют статическую диспетчеризацию,
✔️ Рекомендуется использовать дженерики по умолчанию, если нет необходимости в динамическом определении типа, чтобы избежать излишнего использования памяти и увеличения размера бинарного файла.
Existential container
— это структура данных в Swift, которая хранит значения типов, скрытых за протоколами, и используется для динамического вызова методов и управления жизненным циклом значений.Existential container
для non class-constrained
типов занимает 5 машинных слов (40 байт
) и состоит из 24 байт
данных, указателя на метаданные типа и указателя на таблицу свидетельств протокола.Value witness table (VWT)
описывает операции с конкретными типами, включая инициализацию, копирование и уничтожение значений, что позволяет компилятору генерировать соответствующий код для этих операций.existential container
применяет динамическую диспетчеризацию, что требует выделения памяти в куче для значений больше 3 байт.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4😁1
How to Use OptionSet in Swift with code samples
ℹ️
🖥 В примере кода создается структура
❓ Хотя можно использовать enum для аналогичных задач,
✔️
OptionSet
— это протокол в Swift
, который представляет опции в виде битов, позволяя комбинировать несколько значений и выполнять операции, такие как объединение и пересечение.TasksListOptions
, которая использует OptionSet
для определения опций отображения задач, таких как фильтр, поиск и сортировка.struct TasksListOptions: OptionSet {
let rawValue: Int
static let showFilter = TasksListOptions(rawValue: 1 << 0)
static let showSearch = TasksListOptions(rawValue: 1 << 1)
static let showSort = TasksListOptions(rawValue: 1 << 2)
static let showLayoutSelector = TasksListOptions(rawValue: 1 << 3)
}
OptionSet
более эффективен и предоставляет встроенные функции для работы с опциями без дополнительного кода.OptionSet
является предпочтительным инструментом для конфигурации функций, стилей или разрешений в Swift
, обеспечивая компактность и производительность.Please open Telegram to view this post
VIEW IN TELEGRAM
❤5
Using Observations to observe @Observable model properties
🆕 С
🔍 Объект
❗️ Важно использовать
⚠️ При использовании Observations можно пропустить значения, если они производятся быстрее, чем вы их обрабатываете, поэтому рекомендуется реализовать собственное буферизование.
➡️ Новая система
Xcode 26
и Swift 6.2
появилась возможность использовать объект Observations
для наблюдения за свойствами моделей @Observable
, что упрощает процесс наблюдения вне SwiftUI
.Observations
позволяет создать AsyncSequence
, который будет эмитировать значения при изменении наблюдаемых свойств, таких как count в модели Counter
.[weak self]
в замыкании Observations
, чтобы избежать циклов удержания, что может привести к утечкам памяти.Observations
предлагает did set semantics
, в отличие от withObservationTracking
, который использует will set semantics
, что улучшает реакцию на изменения.@Observable
class Counter {
var count: Int
}
class CounterObserver {
let counter: Counter
init(counter: Counter) {
self.counter = counter
}
func observe() {
Task { [weak self] in
let values = Observations { [weak self] in
guard let self else { return 0 }
return self.counter.count
}
for await value in values {
guard let self else { break }
print("counter.count: \(value)")
}
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Detecting Text Language with NLLanguageRecognizer in Swift
ℹ️ Для определения доминирующего языка текста используется структура
❓
⚙️ Можно добавить возможность возвращать оценки уверенности в предсказании языка и использовать языковые подсказки для повышения точности распознавания в многоязычных приложениях.
✔️
LanguageDetector
, которая инициализирует NLLanguageRecognizer
, обрабатывает строку и возвращает код языка в формате ISO 639-1
.NLLanguageRecognizer
использует статистические модели, обученные на больших текстовых корпусах, и лучше всего работает с полными предложениями или абзацами, а не с короткими фразами.NLLanguageRecognizer
— это мощный API, который позволяет интегрировать определение языка в приложение без необходимости в серверных вызовах и задержках.import NaturalLanguage
struct LanguageDetector {
static func languageCode(for text: String) -> String? {
let recognizer = NLLanguageRecognizer()
recognizer.processString(text)
if let language = recognizer.dominantLanguage {
return language.rawValue // "en", "ru", "de", etc.
}
return nil
}
}
static func detectLanguage(for text: String) -> (code: String, confidence: Double)? {
let recognizer = NLLanguageRecognizer()
recognizer.processString(text)
guard let language = recognizer.dominantLanguage else { return nil }
let hypotheses = recognizer.languageHypotheses(withMaximum: 1)
let confidence = hypotheses[language] ?? 0
return (language.rawValue, confidence)
}
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡2