Пятничный квиз📣
class Person: NSObject {
var name: String
init(name: String) { self.name = name }
override var description: String { name }
}
var teamA: [Person] = [
Person(name: "Alice"),
Person(name: "Bob"),
Person(name: "Charlie")
]
var teamB = teamA
teamA[0].name = "Diana"
teamA.removeLast()
print(teamB)
Please open Telegram to view this post
VIEW IN TELEGRAM
Что выведет принт?
Anonymous Quiz
24%
[Alice, Bob, Charlie]
41%
[Diana, Bob]
32%
[Diana, Bob, Charlie]
3%
[Alice, Bob]
SwiftyGroup
Что выведет принт?
• Array в Swift — структура (value type),
значит сам массив копируется.
• Но внутри массива лежат объекты класса —
а класс это reference type (копируется только ссылка на объект).
• Когда мы делаем var teamB = teamA,
создаётся новый массив, но оба массива содержат ссылки на одни и те же объекты.
• Изменяя teamA[0].name,
мы изменяем сам объект, а не массив —
поэтому изменения видны и в teamB.
• А вот операция removeLast() влияет только на сам массив teamA,
поэтому teamB по-прежнему хранит все три элемента.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18 8
В iOS 26 UINavigationController получил новый жест,
который делает возврат назад намного естественнее.
🆕 interactiveContentPopGestureRecognizer
Раньше жест “свайп назад” работал только от левого края экрана.
Теперь появился новый распознаватель — interactiveContentPopGestureRecognizer,
который позволяет начинать свайп из любой точки контента, а не только с границы.
Пример использования
let gesture = navigationController?.interactiveContentPopGestureRecognizer
myScrollView.panGestureRecognizer.require(toFail: gesture!)
или просто активировать его вручную:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
navigationController?.interactiveContentPopGestureRecognizer.isEnabled = true
}
💡 Что это даёт
• Жест “назад” становится доступным по всему экрану,
даже если контент перехватывает касания.
• Больше не нужны костыли с кастомными pan-распознавателями.
• Переходы становятся естественнее и плавнее, но при этом
всё ещё остаются интерактивными и работают с анимациями UINavigationController.
📱 Итого: теперь свайп-назад работает так, как многие всегда хотели —
в любом месте экрана, без попадания строго в край и без конфликтов со scrollView.
#ios26
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1
📱 Combine — тайное оружие iOS-разработчика, о котором все слышали, но мало кто реально понимает
На Хабре вышла большая статья от Банки.ру, где Combine объясняют не как «ещё один фреймворк», а как фундаментальную модель работы с данными в iOS. И реально раскладывают всё по полочкам.
🔍 Что важно понять про Combine
• Это не просто Publisher и Subscriber — это целая реактивная модель.
• SwiftUI под капотом живёт на Combine.
• @Published, ObservableObject, цепочки операторов — всё это работает как поток данных, а не как «просто переменная».
• Combine заставляет думать декларативно: данные текут → UI реагирует.
• Автор показывает, как это работает на самом низком уровне — даже создаёт свой мини-Combine.
⚙️ Почему это полезно
• Лучше понимаешь, что именно делает SwiftUI, когда ты меняешь состояние.
• Перестаёшь бояться операторов и подписок.
• Видишь, где Combine силён, а где — проще использовать async/await.
• Понимаешь, как писать код, который не разваливается от гонок состояний.
🚀 Что это меняет
• В продакшене Combine остаётся важным инструментом — особенно в больших проектах.
• Async/await не убил реактивный подход — наоборот, он отлично его дополняет.
• Знание Combine = сильнее понимание архитектуры и потоков данных.
🗣️ Вывод
Combine — это не модный фреймворк, а фундамент. Если понимать его «мозги», SwiftUI и реактивный код становятся намного проще.
Читать статью →
На Хабре вышла большая статья от Банки.ру, где Combine объясняют не как «ещё один фреймворк», а как фундаментальную модель работы с данными в iOS. И реально раскладывают всё по полочкам.
🔍 Что важно понять про Combine
• Это не просто Publisher и Subscriber — это целая реактивная модель.
• SwiftUI под капотом живёт на Combine.
• @Published, ObservableObject, цепочки операторов — всё это работает как поток данных, а не как «просто переменная».
• Combine заставляет думать декларативно: данные текут → UI реагирует.
• Автор показывает, как это работает на самом низком уровне — даже создаёт свой мини-Combine.
⚙️ Почему это полезно
• Лучше понимаешь, что именно делает SwiftUI, когда ты меняешь состояние.
• Перестаёшь бояться операторов и подписок.
• Видишь, где Combine силён, а где — проще использовать async/await.
• Понимаешь, как писать код, который не разваливается от гонок состояний.
🚀 Что это меняет
• В продакшене Combine остаётся важным инструментом — особенно в больших проектах.
• Async/await не убил реактивный подход — наоборот, он отлично его дополняет.
• Знание Combine = сильнее понимание архитектуры и потоков данных.
🗣️ Вывод
Combine — это не модный фреймворк, а фундамент. Если понимать его «мозги», SwiftUI и реактивный код становятся намного проще.
Читать статью →
👍8🔥7❤1
🧩 UIKit 26 — фича №10
Сегодня разберём одно из самых заметных обновлений для iPad iOS 26 —
новые возможности работы с системным меню-баром на iPadOS.
В iPadOS теперь есть полноценное меню как на macOS: File, Edit, View, Find…
И с приходом iOS 26 разработчики наконец могут гибко управлять этим меню:
добавлять свои пункты, подменять системные, скрывать ненужные и менять структуру прямо в рантайме —
без хаков, без обходных путей и без пересборки всего меню целиком.
🆕 Новые идентификаторы меню
• .newItem пришёл на замену устаревшему .newScene.
• .findPanel — отдельная группа команд для поиска (Find, Replace, Search Options).
Это пригодится, когда вы хотите кастомизировать системные меню, но не переписывать структуру полностью.
🛠 Новые методы UIMenuBuilder
Теперь можно динамически модифицировать меню по отдельным элементам.
🔄 Замена
➕ Вставка
🗑 Удаление
Полный контроль над структурой без пересоздания меню — наконец-то нативно.
🧠 Когда это полезно
• скрыть/показать пункты меню в зависимости от состояния приложения
• выделять специфические команды (например, режим редактирования)
• подменять стандартные команды на свои
• динамически вставлять быстрые действия
• отключать определённые действия при отсутствии контекста
Раньше всё это делали через костыли, теперь же API официально поддерживает подобные сценарии.
Сегодня разберём одно из самых заметных обновлений для iPad iOS 26 —
новые возможности работы с системным меню-баром на iPadOS.
В iPadOS теперь есть полноценное меню как на macOS: File, Edit, View, Find…
И с приходом iOS 26 разработчики наконец могут гибко управлять этим меню:
добавлять свои пункты, подменять системные, скрывать ненужные и менять структуру прямо в рантайме —
без хаков, без обходных путей и без пересборки всего меню целиком.
🆕 Новые идентификаторы меню
UIMenu.Identifier.newItem
UIMenu.Identifier.findPanel
• .newItem пришёл на замену устаревшему .newScene.
• .findPanel — отдельная группа команд для поиска (Find, Replace, Search Options).
Это пригодится, когда вы хотите кастомизировать системные меню, но не переписывать структуру полностью.
🛠 Новые методы UIMenuBuilder
Теперь можно динамически модифицировать меню по отдельным элементам.
🔄 Замена
builder.replace(menu: .file, with: newMenu)
builder.replace(action: .paste, with: newPasteAction)
builder.replace(command: "myCmd", propertyList: nil, with: newCommand)
➕ Вставка
builder.insertElements([element], beforeMenu: .edit)
builder.insertElements([element], afterMenu: .view)
builder.insertElements([element], atStartOfMenu: .file)
builder.insertElements([element], atEndOfMenu: .file)
🗑 Удаление
builder.remove(action: .duplicate)
builder.remove(command: "customCommand", propertyList: nil)
Полный контроль над структурой без пересоздания меню — наконец-то нативно.
🧠 Когда это полезно
• скрыть/показать пункты меню в зависимости от состояния приложения
• выделять специфические команды (например, режим редактирования)
• подменять стандартные команды на свои
• динамически вставлять быстрые действия
• отключать определённые действия при отсутствии контекста
Раньше всё это делали через костыли, теперь же API официально поддерживает подобные сценарии.
❤3
✨ UIKit 26 — фича №11
Сегодня разберём обновления UIButton.Configuration, которые Apple добавила в iOS 26.
Это две небольшие, но очень важные фичи, которые одновременно улучшают визуальную часть и дают более современное поведение кнопок.
🧊 1. Новые Liquid Glass-кнопки
UIKit получил готовые конфигурации кнопок в стиле Liquid Glass —
полупрозрачные, блестящие, с мягкими бликами и эффектом стекла.
Добавлены 4 новых статических метода:
Как они отличаются?
• .glass() — стандартная стеклянная кнопка
• .clearGlass() — более прозрачная, менее акцентная
• .prominentGlass() — акцентная версия, похожа на .prominent стиль
• .prominentClearGlass() — акцентная, но с лёгкой прозрачностью
🔄 2. symbolContentTransition
Теперь UIButton.Configuration умеет анимировать смену SF Symbol
в кнопке автоматически, без вашего кода анимации.
Добавлено новое свойство:
Теперь всякий раз, когда вы меняете image:
UIKit сам сделает плавную анимацию
(замена, появление, масштабирование — в зависимости от выбранного transition).
🎬 Поддерживаемые переходы
UISymbolContentTransition(.replace)
UISymbolContentTransition(.scale)
UISymbolContentTransition(.reveal)
#ios26
Сегодня разберём обновления UIButton.Configuration, которые Apple добавила в iOS 26.
Это две небольшие, но очень важные фичи, которые одновременно улучшают визуальную часть и дают более современное поведение кнопок.
🧊 1. Новые Liquid Glass-кнопки
UIKit получил готовые конфигурации кнопок в стиле Liquid Glass —
полупрозрачные, блестящие, с мягкими бликами и эффектом стекла.
Добавлены 4 новых статических метода:
UIButton.Configuration.glass()
UIButton.Configuration.clearGlass()
UIButton.Configuration.prominentGlass()
UIButton.Configuration.prominentClearGlass()
Как они отличаются?
• .glass() — стандартная стеклянная кнопка
• .clearGlass() — более прозрачная, менее акцентная
• .prominentGlass() — акцентная версия, похожа на .prominent стиль
• .prominentClearGlass() — акцентная, но с лёгкой прозрачностью
🔄 2. symbolContentTransition
Теперь UIButton.Configuration умеет анимировать смену SF Symbol
в кнопке автоматически, без вашего кода анимации.
Добавлено новое свойство:
var symbolContentTransition: UISymbolContentTransition? { get set }
Теперь всякий раз, когда вы меняете image:
button.configuration?.image = UIImage(systemName: "heart.fill")
UIKit сам сделает плавную анимацию
(замена, появление, масштабирование — в зависимости от выбранного transition).
🎬 Поддерживаемые переходы
UISymbolContentTransition(.replace)
UISymbolContentTransition(.scale)
UISymbolContentTransition(.reveal)
#ios26
🔥10👎1
Всем привет🍷
По реакциям вижу марафорн мой не особо заходит😕 , поэтому подготовил для вас перевод базовой статьи, чтобы загладить вину, сделал все красиво в Телеграфе, как советовали подписчики🙏 .
Ковариантность и контравариантность в Swift
• Возвращаемые типы у функций/замыканий — ковариантны.
• Параметры функций/замыканий — контравариантны.
• Свои generic-типы — инвариантны, а стандартные коллекции Swift ведут себя «особенно» благодаря магии компилятора.
Подробное объяснение — тут:
https://telegra.ph/Kovariantnost-i-kontravariantnost-v-Swift-11-27
Всем пис!🙈
По реакциям вижу марафорн мой не особо заходит
Ковариантность и контравариантность в Swift
• Возвращаемые типы у функций/замыканий — ковариантны.
• Параметры функций/замыканий — контравариантны.
• Свои generic-типы — инвариантны, а стандартные коллекции Swift ведут себя «особенно» благодаря магии компилятора.
Подробное объяснение — тут:
https://telegra.ph/Kovariantnost-i-kontravariantnost-v-Swift-11-27
Всем пис!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10 4❤1👍1 1
Решил сделать большую скидку — минус 70% на все виды подписок. Сейчас самое время залететь, потому что внутри уже лежит огромное количество материала, который я собираю каждый день.
Что получите по подписке:
•
Вопросы уровня Middle/Senior, мои ответы, разборы ловушек, tricky-моменты, async/await, KVO, memory warnings, SOLID-антипаттерны и многое другое.
•
Комплексные Swift-задачи «что выведет», edge cases, сложные примеры, практические задачи, подробно разобранные решения.
•
REST vs WebSocket, KVO, память, архитектура, работа с CoreData/SwiftData, RxSwift → Combine → async/await, Actors, UIView/SwiftUI тонкости.
•
Популярные материалы с Medium/Dev/Reddit, а также переводы официальной Swift-доки.
•
Подборка библиотек, настройки проекта, примеры рефакторинга, «грязные» хаки, которыми мы все иногда пользуемся.
•
Скидка действует ограниченное время.
Если думали подписаться — сейчас лучший момент
Boosty: 70% https://boosty.to/buik
Tribute: 70% https://t.me/tribute/app?startapp=ssYu
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7 2 1 1 1 1
🎨 UIKit 26 — фича №12
SF Symbols получили новые режимы рендеринга.
Теперь символы могут выглядеть ярче, объёмнее и “живее” — без кастомной графики.
🔹 1. Градиентный рендеринг
Символ автоматически получает мягкий системный градиент (в стиле iOS 26 / visionOS).
🔹 2. “Draw” режим
Символ выглядит как будто нарисован кистью:
Полезно для декоративных UI, заметок, творчества.
🔹 3. Variable Value + Color mode
Теперь “живые” символы можно рендерить цветом:
Например — индикаторы (заряд, прогресс, температура).
SF Symbols получили новые режимы рендеринга.
Теперь символы могут выглядеть ярче, объёмнее и “живее” — без кастомной графики.
🔹 1. Градиентный рендеринг
image = image.applyingSymbolConfiguration(
.init(colorRenderingMode: .gradient)
)
Символ автоматически получает мягкий системный градиент (в стиле iOS 26 / visionOS).
🔹 2. “Draw” режим
Символ выглядит как будто нарисован кистью:
image = image.applyingSymbolConfiguration(
.init(variableValueMode: .draw)
)
Полезно для декоративных UI, заметок, творчества.
🔹 3. Variable Value + Color mode
Теперь “живые” символы можно рендерить цветом:
image = image.applyingSymbolConfiguration(
.init(variableValueMode: .color)
)
Например — индикаторы (заряд, прогресс, температура).
❤6 5👍3
tab-bar-controller-tab-bar-minimize-behavior-demo.mp4
400.8 KB
🏷️ UIKit 26 — фича №13
Bottom Accessory в UITabBarController
В iOS 26 Apple впервые добавила официальный способ размещать плавающую панель над таббаром — как в Music или Podcasts.
Раньше все делали это костылями через additionalSafeAreaInsets и ручное добавление subviews.
Теперь есть нормальный API.
🆕 UITabAccessory + bottomAccessory
Чтобы добавить нижний аксессуар:
А чтобы показать/скрыть с анимацией:
Это может быть мини-плеер, панель состояния, быстрые действия — всё, что раньше приходилось “прибивать гвоздями”.
📦 Поведение таббара: сворачивание и расширение
В iOS 26 таббар умеет минимизироваться при скролле,
и bottom accessory тоже меняет состояние вместе с ним.
Режимы задаются:
Доступные варианты:
• .automatic — система сама решает
• .never — не сворачивать
• .onScrollDown — свернуть при скролле вниз
• .onScrollUp — свернуть при скролле вверх
🌐 Определение состояния аксессуара
UIKit вводит новый enum:
UITabAccessory.Environment
• .regular — аксессуар в полном размере
• .inline — компактный (в минимизированном таббаре)
• .none — не в среде таб-аксессуара
• .unspecified — ещё не отобразился
Состояние можно получить так:
🧭 Новый layout guide
Чтобы правильно размещать контент над таббаром и аксессуаром:
Вью, прикреплённые к этому layout guide, автоматически адаптируются
к изменениям высоты таббара и состоянию аксессуара.
🔥 В итоге: теперь можно официально и красиво делать “мини-плееры”
и любые нижние панели поверх таббара — без костылей, багов и ручных отступов.
Bottom Accessory в UITabBarController
В iOS 26 Apple впервые добавила официальный способ размещать плавающую панель над таббаром — как в Music или Podcasts.
Раньше все делали это костылями через additionalSafeAreaInsets и ручное добавление subviews.
Теперь есть нормальный API.
🆕 UITabAccessory + bottomAccessory
Чтобы добавить нижний аксессуар:
let accessory = UITabAccessory(contentView: customView)
tabBarController.bottomAccessory = accessory
А чтобы показать/скрыть с анимацией:
tabBarController.setBottomAccessory(accessory, animated: true)
Это может быть мини-плеер, панель состояния, быстрые действия — всё, что раньше приходилось “прибивать гвоздями”.
📦 Поведение таббара: сворачивание и расширение
В iOS 26 таббар умеет минимизироваться при скролле,
и bottom accessory тоже меняет состояние вместе с ним.
Режимы задаются:
tabBarController.tabBarMinimizeBehavior = .onScrollDown
Доступные варианты:
• .automatic — система сама решает
• .never — не сворачивать
• .onScrollDown — свернуть при скролле вниз
• .onScrollUp — свернуть при скролле вверх
🌐 Определение состояния аксессуара
UIKit вводит новый enum:
UITabAccessory.Environment
• .regular — аксессуар в полном размере
• .inline — компактный (в минимизированном таббаре)
• .none — не в среде таб-аксессуара
• .unspecified — ещё не отобразился
Состояние можно получить так:
traitCollection.tabAccessoryEnvironment
🧭 Новый layout guide
Чтобы правильно размещать контент над таббаром и аксессуаром:
let guide = tabBarController.contentLayoutGuide
Вью, прикреплённые к этому layout guide, автоматически адаптируются
к изменениям высоты таббара и состоянию аксессуара.
🔥 В итоге: теперь можно официально и красиво делать “мини-плееры”
и любые нижние панели поверх таббара — без костылей, багов и ручных отступов.
👍10 3❤1
🔍 ObservedObject vs @Observable в SwiftUI — в чём разница?
Если ты всё ещё используешь ObservedObject, самое время понять, почему новый @Observable меняет подход к управлению состоянием в SwiftUI.
Вот краткое и понятное сравнение 👇
🆕 1. @Observable (Swift 5.9 / SwiftData / iOS 17+)
Что это?
Новый макрос от Apple, который автоматически генерирует логику наблюдения без:
• ObservableObject
• @Published
• objectWillChange
Преимущества:
• меньше шаблонного кода
• быстрее работает благодаря compile-time генерации
• более чистые модели данных
Пример:
🧓 2. ObservedObject (устаревающий, но всё ещё поддерживается)
Что это?
Старый механизм слежения за классами, реализующими ObservableObject.
Минусы:
• обязателен ObservableObject
• нужно ставить @Published на каждое поле
• больше кода
• наблюдение работает в рантайме → медленнее
Пример:
💡 Вывод
➡️ @Observable — будущее SwiftUI: чище, быстрее, удобнее.
➡️ ObservedObject стоит использовать только для поддержки старых iOS.
#SwiftUI
Если ты всё ещё используешь ObservedObject, самое время понять, почему новый @Observable меняет подход к управлению состоянием в SwiftUI.
Вот краткое и понятное сравнение 👇
🆕 1. @Observable (Swift 5.9 / SwiftData / iOS 17+)
Что это?
Новый макрос от Apple, который автоматически генерирует логику наблюдения без:
• ObservableObject
• @Published
• objectWillChange
Преимущества:
• меньше шаблонного кода
• быстрее работает благодаря compile-time генерации
• более чистые модели данных
Пример:
@Observable
class UserSettings {
var username: String = "Puneet"
var isLoggedIn: Bool = false
}
🧓 2. ObservedObject (устаревающий, но всё ещё поддерживается)
Что это?
Старый механизм слежения за классами, реализующими ObservableObject.
Минусы:
• обязателен ObservableObject
• нужно ставить @Published на каждое поле
• больше кода
• наблюдение работает в рантайме → медленнее
Пример:
class UserSettings: ObservableObject {
@Published var username: String = "John"
@Published var isLoggedIn: Bool = false
}
💡 Вывод
➡️ @Observable — будущее SwiftUI: чище, быстрее, удобнее.
➡️ ObservedObject стоит использовать только для поддержки старых iOS.
#SwiftUI
👍8🔥4 3❤2
👎16 6
В Swift приняли **SE-0493 — async в defer.
Раньше:
defer был строго синхронным.
Даже внутри async-функции нельзя было написать await в defer.
Из-за этого:
— асинхронный cleanup приходилось дублировать
— или делать Task { } внутри defer (который не ждёт выполнения)
Теперь:
в defer можно вызывать await, если окружающий контекст async.
Что важно:
— defer по-прежнему выполняется при выходе из scope
— порядок defer сохраняется (LIFO)
— await внутри defer ожидается, а не fire-and-forget
— работает только в async-контексте
https://github.com/swiftlang/swift-evolution/blob/main/proposals/0493-defer-async.md
Proposal принят и войдёт в Swift.
Раньше:
defer был строго синхронным.
Даже внутри async-функции нельзя было написать await в defer.
Из-за этого:
— асинхронный cleanup приходилось дублировать
— или делать Task { } внутри defer (который не ждёт выполнения)
Теперь:
в defer можно вызывать await, если окружающий контекст async.
func load() async {
await start()
defer {
await cleanup()
}
try await work()
}
Что важно:
— defer по-прежнему выполняется при выходе из scope
— порядок defer сохраняется (LIFO)
— await внутри defer ожидается, а не fire-and-forget
— работает только в async-контексте
https://github.com/swiftlang/swift-evolution/blob/main/proposals/0493-defer-async.md
Proposal принят и войдёт в Swift.
🔥26 6❤🔥2❤1
Forwarded from Mobile VK Hub
This media is not supported in your browser
VIEW IN TELEGRAM
Конец года, и снова заканчиваются все подписки 😱
Узнали? Согласны? Не беда — мы как раз разыгрываем промокоды на год от Облака Mail и VK Музыки!
Условия участия простые:
🔹 подпишитесь на наш канал @mobilehubvk
🔹нажмите кнопку «Участвовать»
🔹 дождитесь 30 декабря — в этом посте мы выберем случайным образом 6 победителей
Информацию об организаторе, правилах и призах ищите по ссылке.
Удачи!
Узнали? Согласны? Не беда — мы как раз разыгрываем промокоды на год от Облака Mail и VK Музыки!
Условия участия простые:
🔹 подпишитесь на наш канал @mobilehubvk
🔹нажмите кнопку «Участвовать»
🔹 дождитесь 30 декабря — в этом посте мы выберем случайным образом 6 победителей
Информацию об организаторе, правилах и призах ищите по ссылке.
Удачи!
👎6👍3 1