es
Feedback
iOS Broadcast

iOS Broadcast

Ir al canal en Telegram

Подборка новостей и статей для iOS разработчиков. Новости Kotlin и мультиплатформы @kotlin_broadcast Новости Android @android_broadcast Реклама и прочее @ab_manager

Mostrar más
3 499
Suscriptores
-224 horas
+37 días
-1830 días
Archivo de publicaciones
⚡️ Новые Mac mini и Mac Studio Приятные утренние новости, Apple без отдельной презентации вчера обновила сразу два настольных
+3
⚡️ Новые Mac mini и Mac Studio Приятные утренние новости, Apple без отдельной презентации вчера обновила сразу два настольных Mac. И в этот раз интереснее всего даже не прирост CPU, а то, насколько явно Apple начала продавать Mac как машину для локального AI и агентов. 🖥Mac mini Базовый mini первым получил новый M6: 🟢12-ядерный CPU и 12-ядерный GPU 🟢Neural Accelerators теперь есть в каждом ядре GPU 🟢до x4 производительности в AI-задачах и x2 по графике относительно M4 🟢16 ГБ RAM в базе, максимум 32 ГБ, пропускная способность 170 ГБ/с 🟢SSD до x2 быстрее 🟢Wi-Fi 7 и Bluetooth 6 🟢2.5Gb Ethernet теперь в базе, 10Gb опционально 🟢3× Thunderbolt 4 сзади И мне нравится, как Apple сама описывает новый mini: always-on agentic computing. То есть маленький Mac под столом для локальных моделей, coding agents и всяких домашних AI-сервисов теперь буквально официальный use case. Есть и версия на M5 Pro: 🟢до 18 CPU и 20 GPU ядер 🟢до 64 ГБ RAM и 307 ГБ/с 🟢Thunderbolt 5 🟢до x4 быстрее M4 Pro в обработке LLM prompt'ов по тестам Apple По ценам: 💵Mac mini M6 от $899 💵Mac mini M5 Pro от $1699 32 ГБ максимум у обычного M6 немного портят красивую историю про локальные LLM, но как компактная машина для разработки и агентов mini становится очень интересным. 🖥 Mac Studio Тут уже начинается тяжёлая артиллерия. M5 Max: 🟢18-ядерный CPU 🟢до 40 GPU ядер с Neural Accelerators 🟢до 128 ГБ RAM 🟢614 ГБ/с пропускной способности памяти 🟢до x3.9 быстрее M4 Max в LLM prompt processing M5 Ultra: 🟢до 36 CPU ядер 🟢до 80 GPU ядер 🟢до 512 ГБ unified memory 🟢1.2 ТБ/с пропускной способности памяти 🟢до x4 быстрее M3 Ultra в LLM-задачах по тестам Apple 512 ГБ unified memory уже выглядит не столько как домашний компьютер, сколько как локальный AI-сервер в очень маленькой коробке. Причём Apple теперь официально поддерживает объединение нескольких Studio через Thunderbolt 5 + RDMA. Кластер из четырёх машин обещает до x3 к скорости distributed AI inference. Из остального: 🟢Wi-Fi 7 и Bluetooth 6 🟢до 6× Thunderbolt 5 🟢до 8 дисплеев 🟢SSD до x2 быстрее Цены тоже соответствующие: 💵Mac Studio M5 Max от $2499 💵Mac Studio M5 Ultra от $5499 Продажи обеих линеек стартуют 22 сентября. Мне кажется, тут хорошо заметен новый вектор Apple. Раньше Mac продавали через монтаж, музыку и Xcode, а теперь практически каждый второй абзац пресс-релиза про local LLM, inference, agents и AI development. Для обычной iOS-разработки мощности снова с огромным запасом. А вот как компактные машины под локальных coding agents новые mini выглядят всё интереснее. Кук завершает свою работу в Apple на высокой ноте 🤘

⚡️Презентация новых iPhone состоится 9 сентября Что ждете от презентации? 🟢Представят ли складной iPhone Ultra 🟢Что нового
️Презентация новых iPhone состоится 9 сентября Что ждете от презентации? 🟢Представят ли складной iPhone Ultra 🟢Что нового будет в iPhone 18 если чехлы остались те же 🟢Будут ли изменения в Apple Watch

🛡 Вредоносная dylib может спрятаться внутри обычного приложения Редкая статья про разбор базы про реальные уязвимости, в это
🛡 Вредоносная dylib может спрятаться внутри обычного приложения Редкая статья про разбор базы про реальные уязвимости, в этот раз рассматривается dylib.  Это обычная динамическая библиотека с кодом, которую приложение может загрузить при запуске или уже во время работы. Проблема начинается, когда вместо нормальной библиотеки внутрь процесса попадает вредоносная. Тогда malware не обязательно запускать отдельным подозрительным приложением. Код может спокойно выполняться внутри условного Photoshop. И это даёт довольно неприятный бонус. Если Photoshop уже получил доступ к Documents, сети или другим защищённым TCC ресурсам, загруженная внутрь него dylib работает в том же процессе и может использовать эти разрешения. При этом со стороны системы всё выглядит примерно так: ➡️Photoshop открыл файл. ➡️Photoshop сходил в сеть. А то, что на самом деле действие инициировал чужой код внутри dylib, многие security API уже не показывают. Patrick Wardle в свежем исследовании Objective-See напоминает, что это не теоретическая история. В supply-chain атаке на 3CX злоумышленники модифицировали libffmpeg.dylib внутри приложения. Вредоносная версия какое-то время не детектилась security-продуктами, а само приложение даже прошло нотаризацию Apple. Как такое искать? Автор показывает сразу три уровня: 🟢Статически разбирать Mach-O и проверять зависимости приложения 🟢Во время работы смотреть executable memory mappings процесса через proc_pidinfo 🟢Ловить сам момент загрузки dylib через Endpoint Security И последний вариант самый интересный. ES_EVENT_TYPE_AUTH_MMAP позволяет получить событие ещё до того, как executable mapping будет добавлен в процесс. То есть security tool может посмотреть: 🟢Откуда загружается библиотека 🟢Как она подписана 🟢Совпадает ли Team ID с приложением 🟢Выглядит ли вообще эта dylib ожидаемой И если условный Photoshop внезапно пытается загрузить библиотеку с чужой подписью, mapping можно просто запретить. Вредоносный код даже не начнёт выполняться. Конечно, здесь тоже нет магической кнопки "защитить всё". Если ошибочно заблокировать обязательную dylib, приложение может вообще не запуститься. А экзотические варианты с anonymous executable memory потребуют дополнительных проверок. iOS разработчикам тут можно выдохнуть, iOS не разрешает просто подложить чужую .dylib внутрь другого приложения и запустить её. На iOS всё жёстче: код приложения подписан, embedded frameworks тоже подписаны, чужой код не должен пройти проверку подписи, а sandbox не даёт одному приложению залезть в bundle другого и что-то там заменить. Важная оговорка: если вредоносный код попал в приложение ещё до подписи, например через заражённый SDK или скомпрометированный CI, тогда iOS уже будет считать его частью легитимного приложения.

📱 Как тестировать навигацию в SwiftUI Навигацию обычно тестируют примерно никак. Еще 3 года назад я рассказывал как можно в
+2
📱 Как тестировать навигацию в SwiftUI Навигацию обычно тестируют примерно никак. Еще 3 года назад я рассказывал как можно в UIKit описывать навигацию декларативно и тестировать ее (Декларативная навигация в iOS-приложении). В SwiftUI тенденция тестировать навигацию, к моему удивлению, до сих не стала повсеместной. Хотя почти у всех есть NavigationStack, несколько маршрутов, deep links, sheet, ошибки и авторизация, и если подумать - навигация уже является частью бизнес-логики. В статье Azam Sharp интересный подход: не тестировать сам NavigationStack. Вместо этого вынести решение по навигации в отдельную логику. Например, вместо:
if isLoggedIn {
    navigationPath.append(.home)
} else {
    navigationPath.append(.login)
}
сделать так, чтобы ViewModel или router решал: destination = .home или: destination = .login А SwiftUI уже занимается отображением этого состояния. Тогда тесту вообще не нужен UI. Можно проверить: 🟢авторизованный пользователь → .home 🟢неавторизованный → .login 🟢после сохранения → .details 🟢ошибка → .error 🟢deep link → правильный маршрут Основная идея - сделать навигацию обычным состоянием приложения. Например:
enum Route: Hashable {
    case home
    case profile
    case settings
}
А NavigationStack просто отображает текущий маршрут. Это особенно хорошо работает с NavigationPath, потому что сам path можно рассматривать как данные. Изменился path → изменился navigation state → SwiftUI обновил UI. после такого сдвига парадигмы тестировать становится намного проще. При этом не обязательно сразу строить огромный Router. Для небольшого приложения вполне может хватить @State или @Observable-модели. После того как Navigation становится обычными данными, тестировать становится намного проще. Ну а если вам идея понравится, советую пойти дальше и посмотреть мой доклад, фреймворк отлично подходит и для SwiftUI

🐥 Data Detector в iOS 26: ссылки прямо из обычного текста В iOS 26 Apple добавила новый фреймворк - DataDetector, который ум
+8
🐥 Data Detector в iOS 26: ссылки прямо из обычного текста В iOS 26 Apple добавила новый фреймворк - DataDetector, который умеет находить в тексте полезные сущности: ссылки, телефоны, адреса, даты и другие данные. Раньше для такого сценария часто приходилось самостоятельно разбирать строку, искать regex'ами URL и телефоны, а потом превращать найденные куски в ссылки. Совсем олдскульные разработчики вспомнят про NSDataDetector, но его далеко не так просто адаптировать для прямой работы со строкой в Swift. DataDetector умеет работать не только с обычным String, но и с AttributedString, добавляя найденным данным соответствующие атрибуты. То есть текст:
Позвони мне завтра в 15:00 или посмотри https://t.me/ios_broadcast
может автоматически превратиться в интерактивный текст с распознанными сущностями. Особенно полезно для: 🟢чатов 🟢заметок 🟢email 🟢документов 🟢preview пользовательского текста Это системный механизм, который знает гораздо больше о том, что именно находится в тексте. Основной плюс системного подхода: Data Detector учитывает локаль и системные форматы. Это сильно поможет при международном распространении приложения. Телефон, дата или адрес могут выглядеть совершенно по-разному в разных странах, и поддерживать все эти варианты самостоятельно довольно быстро становится неприятно. Но DataDetector не превращает любой Text автоматически в интерактивный. Это именно инструмент для анализа текста и добавления metadata. А уже UI-слой решает, как эти данные отображать и что делать по нажатию. Очень радует что это не SwiftUI компонент для работы с текстом, а небольшой нормальный системный фреймворк - кирпичик. Он закрывает одну раздражающую задачу.

📱 ContentBuilder - секрет ускорения проверки типов в SwiftUI На сессии WWDC 2026 инженеры Apple представили новую функц
📱 ContentBuilder - секрет ускорения проверки типов в SwiftUI На сессии WWDC 2026 инженеры Apple представили новую функцию SwiftUI: ContentBuilder. Он представляет собой не что иное, как ViewBuilder с более широким охватом - API, которые раньше принимали ViewBuilderToolbarContentBuilder, или CommandsBuilder по отдельности, теперь это один конструктор. Apple также утверждает, что это изменение значительно повышает производительность проверки типов. Давайте рассмотрим что же такое ContentBuilder и за счет чего достигается такая производительность. Для начала давайте вспомним как работает @ViewBuilder в SwiftUI:
@ViewBuilder
var content: some View {
    Text("Hello")
    Image(systemName: "star")
}
И SwiftUI как будто просто понимает, что делать с несколькими View, но никакой магии тут нет. @ViewBuilder это result builder, то есть специальный механизм Swift, который превращает декларативный код в обычные вызовы методов builder'а. То есть когда мы пишем:
if isLoading {
    ProgressView()
} else {
    ContentView()
}
SwiftUI не исполняет это как обычный if, а возвращающий разные типы. ViewBuilder строит из этого единую структуру, которую затем SwiftUI использует для своего view tree. За счет этого body может содержать несколько View, хотя обычная функция не может просто так вернуть несколько разные типы. ViewBuilder не является чем-то исключительно SwiftUI-ным, это обычный result builder из Swift. Поэтому похожий подход можно использовать и для собственных DSL. За счет чего же достигается ускорение проверки типов? Помимо typealias указания на ViewBuilder, реальным фактором повышения производительности стало изменение способа объявления API. Выигрыш обусловлен тем, что SwiftUI переработал инициализаторы общих компонентов и выходные типы builder-а.
public static func buildBlock<Content>(
    _ content: Content
) -> Content

@available(iOS 27.0, macOS 27.0, *)
public static func buildBlock<each Content>(
    _ content: repeat each Content
) -> TupleContent<repeat each Content>

public static func buildIf<Content>(
    _ content: Content?
) -> Content?

public static func buildEither<TrueContent, FalseContent>(
    first: TrueContent
) -> _ConditionalContent<TrueContent, FalseContent>
Обратите внимание: ни одна из этих сигнатур не содержит Content: ViewContent: ToolbarContent или Content: Commands ограничений. Задача builder-а стала чисто структурной. Недавно представленный TupleContent является ключевым элементом дизайна. Его отличительная особенность заключается в том, что он принимает различные формы в зависимости от того, что могут делать его элементы. Другими словами, TupleContent изначально не принадлежит ни к какому домену. Это View только в том случае, если каждый элемент, который он содержит, является View. когда все его элементы являются ToolbarContent, он является содержимым панели инструментов. Optional_ConditionalContentGroup и ForEach используют один и тот же подход. Таким образом, разработчик может сначала создать единую конкретную структуру:
TupleContent<Text, Image>
Только когда сигнатура функции требует some View компилятор возвращается к проверке того, что и Text и Image соответствуют View. Для Group новый интерфейс можно описать так:
public struct Group<Content> { ... }

extension Group {
    public init(@ContentBuilder content: () -> Content)
}

extension Group: View where Content: View {}
extension Group: ToolbarContent where Content: ToolbarContent {}
extension Group: Commands where Content: Commands {}
Для доменов ContentBuilder унифицированы - View, ToolbarContent, Commands и т. д. — Group { ... } в обычном клиентском коде теперь предпочтительнее использовать эту универсальную точку входа в сборку без ограничений по доменам. Apple решила исправить междоменные вложенные общие компоненты, такие как GroupForEach, и Section. Сократилось время проверки типов выражений, содержащих эти деревья перегрузок.

📱 Как заставить SwiftUI делать красивые переносы Обычно статьи про текст рассказывают то как быстро и точно рассчитать разме
📱 Как заставить SwiftUI делать красивые переносы Обычно статьи про текст рассказывают то как быстро и точно рассчитать размер контейнера, но тут более редкая проблема - не красивые переносы слов. Случай, когда текст красиво выглядит почти на всех размерах экрана, а потом на каком-нибудь iPhone последняя строка внезапно состоит из одного-двух слов. Понятная логика, перенести это слово на предыдущую строку не понятно как описать без костылей вставки переносов в исходный текст, ведь стандартный Text не даёт нормального контроля над такими переносами. В статье интересный подход: использовать AttributedString и управлять правилами переноса через paragraph style. В частности, можно задать lineBreakStrategy и использовать .pushOut, чтобы SwiftUI старался не оставлять слишком короткую последнюю строку. Получается довольно приятная штука: 🟢не нужно вручную вставлять \n 🟢не нужно делать разные варианты текста для разных устройств 🟢перенос остаётся адаптивным И это хороший пример того, как иногда проблема SwiftUI находится не в самом Text, а уровнем ниже, в типографике и AttributedString. При этом есть важный нюанс: Не стоит пытаться запретить любые короткие строки. Иногда перенос действительно является правильным, а попытка любой ценой выровнять текст только ухудшит результат. Статья меня зацепила даже не самой идеей решения, а концепцией: типографику тоже можно сделать частью layout-поведения. И если текст выглядит странно только на некоторых размерах экрана, возможно, не нужно добавлять ещё один frame(). Сначала стоит посмотреть, какие правила переноса вообще используются.

🐥 @FocusState в SwiftUI Давайте базовую тему - фокус в SwiftUI. @FocusState позволяет хранить состояние фокуса прямо в Swift
+1
🐥 @FocusState в SwiftUI Давайте базовую тему - фокус в SwiftUI.  @FocusState позволяет хранить состояние фокуса прямо в SwiftUI и управлять им из кода. Например, можно описать поля формы: 🟡имя🟡email🟡пароль. После чего можно переключать фокус между ними после ввода. Это можно сделать через enum: enum Field { case name, email, password } А затем привязать его к focused(...) В итоге логика становится довольно читаемой: 🟢открыть экран и сразу поставить фокус на поле 🟢нажать далее и перейти к следующему 🟢после ошибки вернуть пользователя к нужному полю 🟢скрыть клавиатуру, сбросив focus в nil @FocusState лучше воспринимать именно как состояние UI, а не как часть бизнес-логики. Не нужно тащить информацию о том, какое поле сейчас активно, в модель или сервис. Фокус относится к интерфейсу. Но не стоит использовать несколько независимых @FocusState, когда все поля относятся к одной форме. Обычно один enum для всей формы получается проще и предсказуемее. Магия @FocusState лежит не только в упрощении работы с формами, это подход по делегированию поведения системе. Это особенно актуально, если интерфейс по-настоящему кросплатформенный и работает не только на iOS/iPad, но и на mac или даже Apple TV. Вместо becomeFirstResponder, ссылок на UIKit и ручного управления клавиатурой достаточно описать: какое поле сейчас должно быть в фокусе и дальше SwiftUI сам занимается остальным.

🆓 Типобезопасные JSON в StructuredQueries Оч интересное обновление вышло у библиотеки StructuredQueries. Сама библиотека раз
+5
🆓 Типобезопасные JSON в StructuredQueries Оч интересное обновление вышло у библиотеки StructuredQueries. Сама библиотека разработана Point-Free предоставляет набор инструментов, которые позволяют вам писать типобезопасные, выразительные и компонуемые SQL-выражения на языке Swift. Но данное обновление расширяет DSL на JSON и JSONB ( это тип данных, который хранит JSON-документы в оптимизированном бинарном формате). Элегантный DSL для указания типа для сериализации в таблице:
@Table struct Trip: Identifiable {
  let id: UUID
  var name = ""
  @Column(as: Location.JSONRepresentation.self)
  var location: Location
}
Вот так будет выглядеть запрос местоположения поездки, хранящейся в столбце JSON:
@Selection struct Location: Codable {
  var latitude = 0.0
  var longitude = 0.0
}
При применении макроса @Selection к Location структура типа становится видимой для builder-а запросов, и дает возможность перемещаться по JSON с помощью метода jsonExtract и привычного пути к ключу в Swift:
Trip.where {
  $0.location
    .jsonExtract(\.longitude) < 0
}
// Превращается в SQL
SELECT … FROM "trips"
WHERE json_extract(
  "trips"."location", 
  '$."longitude"') < 0
Это означает, что вы получаете безопасность схемы для столбцов вашей таблицы, для полей внутри ваших JSON-данных и для извлекаемых значений. И эти выражения можно использовать в любом месте запроса: whereselectorder в полях и т. д. Вы также можете обновлять данные в формате JSON непосредственно в базе данных, не загружая их в память, используя jsonSetjsonInsertjsonAppendjsonRemove и jsonReplace:
Profile.update {
  $0.author = $0.author
    .jsonSet(\.name, "Blob")
}
// превращается в 
UPDATE "profiles"
SET "author" = json_set(
  "profiles"."author", 
  '$."name"', 'Blob'
)
Profile.update {
  $0.tags = $0.tags
    .jsonAppend("new")
}
// превращается в 
UPDATE "profiles"
SET "tags" = json_insert(
  "profiles"."tags", 
  '$[#]', 'new'
)
Не сказал бы что работа с SQLite напрямую часто требуется, но во-первых это красиво 😀 . А Во-вторых можно взять на вооружение такой подход для создания своих DSL для работы с JSON 😺️ MR со всеми доработками и тестами

🐥 Почему @MainActor и протоколы в Swift 6 могут поссориться В теории всё просто, есть протокол: protocol ImageLoader { ... }
🐥 Почему @MainActor и протоколы в Swift 6 могут поссориться В теории всё просто, есть протокол: protocol ImageLoader { ... } Реализация, которая работает с UI: @MainActor final class ImageLoaderImpl: ImageLoader { ... } Но Swift 6 начинает задавать неприятный вопрос: а сам протокол изолирован от Main Actor или нет? И вот тут начинается самое интересное. @MainActor на конкретной реализации не означает автоматически, что любой код, который работает с протоколом, тоже находится на Main Actor. Для компилятора протокол может использоваться совершенно независимо от конкретной реализации. В результате вполне невинный код начинает упираться в ошибки concurrency: 🟡Вызов main-actor метода из nonisolated контекста 🟡Несоответствие требований протокола и actor isolation 🟡Необходимость добавлять @MainActor туда, где раньше его вообще не было Особенно часто это всплывает при dependency injection. Например, ViewModel хранит зависимость как: let loader: ImageLoader а конкретно переданный ImageLoaderImpl является @MainActor. Swift должен гарантировать, что контракт ImageLoader сам по себе безопасен. И здесь есть несколько вариантов: ➡️ Можно сделать весь протокол @MainActor ➡️ Можно изолировать только отдельные методы ➡️ Можно использовать nonisolated, если конкретная операция действительно не зависит от Main Actor И вот последний вариант особенно важно не использовать просто для того, чтобы "заткнуть компилятор". Если метод реально работает с состоянием, которое должно жить на Main Actor, nonisolated проблему не решает. Он просто заставляет вас взять ответственность за безопасность на себя. Попробую подытожить: @MainActor — это не просто атрибут класса. Это часть контракта, и при работе через протокол этот контракт должен быть виден там, где он действительно нужен. Поэтому при проектировании Swift 6 API стоит заранее решить: 🟢Весь сервис main-actor isolated? 🟢Только часть его методов? 🟢Протокол вообще должен знать про actor isolation? 🟢Можно ли использовать dependency без Main Actor? Это особенно важно для архитектуры с ViewModel + protocols + dependency injection. Это со SwiftUI как раз очень распространено. Раньше можно было сказать:
«Ну эта реализация всё равно работает на Main Actor».
Swift 6 отвечает:
«Мне всё равно. Я проверяю контракт».
И, пожалуй, это хорошая новость. Компилятор наконец заставляет нас явно описывать, где именно должен выполняться код, вместо того чтобы надеяться, что конкретная реализация всё разрулит сама

🎯 Новый уровень работы с фото и видео Рассматриваем новый фреймворк — Media Intelligence. Если совсем коротко, это API, кото
+4
🎯 Новый уровень работы с фото и видео Рассматриваем новый фреймворк — Media Intelligence. Если совсем коротко, это API, которое позволяет приложению понимать содержимое фото и видео, а не просто отображать их. Например, определить: 🟣что происходит в кадре 🟣какие объекты есть на изображении 🟣какие сцены встречаются в видео 🟣где начинается нужный момент 🟣какие фрагменты похожи друг на друга Apple постепенно начинает повышать уровень абстракции при работе с AI и делиться внутренними моделями. Появляется абстракция, благодаря которой Apple сможет подменять реализацию. Гораздо важнее становится какую задачу нужно решить. Раньше для поиска нужного момента в видео приходилось строить собственный пайплайн, теперь система сама может помочь понять, что находится в медиаконтенте. Новые API работают локально, без необходимости встраивать огромные модели в приложение. Очень похоже что все то что уже обкатали в команде Photos становится доступно всем, как только API удалось стабилизировать. Полезные ссылки: ➡ iOS 27: Media Intelligence FrameworkMedia Intelligence Framework Documentation

🐥 Swift 6 стал заметно дружелюбнее к Concurrency Продолжаем эксперименты с многопоточностью в Swift 6, в этой области мы точ
+1
🐥 Swift 6 стал заметно дружелюбнее к Concurrency Продолжаем эксперименты с многопоточностью в Swift 6, в этой области мы точно движемся в правильном направлении. Одна из главных претензий к Swift 6 звучала примерно так: Я просто включил Swift 6, а компилятор решил переписать половину моего проекта. Sendable@MainActor, изоляции, десятки новых предупреждений... И вроде всё правильно, но начать миграцию было больно. Именно поэтому Apple представила Approachable Concurrency. Идея очень простая. Вместо того чтобы сразу требовать идеальный concurrency-код, компилятор позволяет включать проверки постепенно. Мы получили преимущества новой модели, но без ощущения, что проект нужно переписать за один раз. Многие типы из UIKit и SwiftUI уже аннотированы так, что с ними стало проще работать, часть проверок теперь включается только тогда, когда они действительно приносят пользу. Но Approachable Concurrency — это не способ избежать миграции, а способ сделать её управляемой. Если в коде есть потенциальные race condition или нарушение изоляции акторов, рано или поздно их всё равно придётся исправить. Радует что в этой области Apple приняли тот факт, что iOS-приложения не всегда пишутся с нуля и нужно заботиться и о разработчиках которые поддерживают свои приложения годами. Гайды от Apple по миграции: ➡Embracing Swift ConcurrencyEnabling Complete Concurrency Checking

🔨 Liquid Glass не любит UIKit костыли Очень похожие проблемы рассматриваются в статье, которые выплывали у меня недавно при
+3
🔨 Liquid Glass не любит UIKit костыли Очень похожие проблемы рассматриваются в статье, которые выплывали у меня недавно при адаптации Liquid Glass старых UIKit компонентов. Эта тема особенно актуальна сейчас, в связи со скорым релизом iOS 26 и там все еще много мелких плясок с бубном. Для UIKit это отличная проверка того, насколько приложение использует современные API. Все проблемы можно описать одним предложением - "Liquid Glass не любит старые хаки" 🟡Если вручную меняли safeAreaInsets, теперь можно получить странные артефакты 🟡Если рисовали свои navigation bar или tab bar поверх системных, эффекты Glass могут работать совсем не так, как ожидалось 🟡Если использовали приватные или неочевидные способы управления фоном, новый дизайн легко начинает рассыпаться Получается интересная ситуация - все что раньше использовалось чтобы подбить интерфейс под дизайны, теперь требует дополнительных приседаний. Очередной раз Apple делает работающей стандартную конфигурацию без граничных кейсов. Если хочешь кастомку, отрисовывай сам. И это касается не только внешнего вида. В iOS 26 Apple добавила новые способы управлять navigation bar, toolbar, tab bar и их поведением. То есть вместо очередного workaround теперь чаще можно найти системное решение. Но все таки Liqud Glass может послужить поводом пройтись по проекту и задать себе несколько вопросов. 🟢Можно ли перейти на стандартный элемент 🟢Точно ли актуальны все старые UIKit-хаки 🟢Можно ли заменить собственное решение новым API из iOS 26 Ну и не забывайте про оригинайльные гайды от Apple по миграции: ➡️ Build a UIKit app with the new design ➡️ Adopting Liquid Glass

🎯 Способен ли SpeechAnalyzer заменить Whisper Последний год, кроме AI из каждого утюга есть еще один тренд - Whisper. Действ
🎯 Способен ли SpeechAnalyzer заменить Whisper Последний год, кроме AI из каждого утюга есть еще один тренд - Whisper. Действительно, транскрибация вышла на новый уровень и при должной интеграции в систему можно гораздо быстрее записывать свои мысли или управлять исполнением и вабкодить. Весь год, если в приложении нужна была нормальная speech-to-text транскрибация, ответ почти всегда был один - берём Whisper. Он хорошо распознаёт речь, поддерживает много языков и давно стал выбором по умолчанию. В данной заметке же подсвечивается альтернатива - новый SpeechAnalyzer от Apple. Ребята из Inscribe прогнали benchmark на LibriSpeech и сравнили новый Apple speech API со старым SFSpeechRecognizer и несколькими Whisper-моделями. Результат неожиданный: 🟡На английской речи SpeechAnalyzer оказался точнее всех Whisper-моделей, которые они тестировали, включая Whisper Small 🟡В 3 раза быстрее Whisper Small на том же железе. Apple не просто чуть обновила speech API. Она фактически дала новый on-device движок, который для английской транскрибации уже может быть лучшим выбором на Apple-платформах: 🟢Не нужно тащить модель в bundle 🟢Не нужно возиться с CoreML-конвертацией Whisper 🟢меньше размер приложения 🟢всё работает on-device 🟢API живёт внутри системы 🟢приватность проще объяснить пользователю Но радоваться пока рано, у Whisper всё ещё есть сильные стороны: 🟡намного больше языков 🟡кроссплатформенность 🟡предсказуемое поведение вне Apple ecosystem Если вы делаете speech-to-text под iOS/macOS и вас устраивают языки, которые поддерживает Apple, SpeechAnalyzer теперь нужно рассматривать первым. Но скорее всего все равно как fallback прийдется оставлять Whisper. P.S. С русским у нового SpeechAnalyzer пока не всё гладко. SpeechTranscriber только на бумаге поддерживает русский (в официальном списке ru_RU есть), но в реальных тестах русский ru_RU может не отдаваться через supportedLocales

📱 Как получить Apple Developer Organization без головной боли Для использования расширенных возможностей Apple🤍 (командные
📱 Как получить Apple Developer Organization без головной боли Для использования расширенных возможностей Apple🤍 (командные сертификаты, TestFlight, публикация от имени компании) требуется юридическое лицо. Регистрация компании за рубежом — наиболее простой путь. Easy Payments помогают: ➡️Cоздать ИП или ООО в Грузии ➡️Открыть счёт в банке (дистанционно) ➡️Получить все документы для подачи заявки на Organization-аккаунт Весь процесс сопровождается экспертами, что исключает ошибки и задержки. ➡️ Бесплатная консультация — на сайте Easy Payments или в Telegram. #реклама

🔨 CADisplayLink становится ближе к UIWindowScene CADisplayLink - для того чтобы свести некоторым олдскулы 😀. Очень давно не
🔨 CADisplayLink становится ближе к UIWindowScene CADisplayLink - для того чтобы свести некоторым олдскулы 😀. Очень давно не сталкивался с задачей куда его было бы логично применить. CADisplayLink нужен для случаев, когда код должен выполняться синхронно с обновлением экрана. Это редкие кейсы, когда важно попасть в ритм с обновлением экрана. Раньше это использовалось для кастомных анимаций или игровых движков, где все должно двигаться вместе с кадрами. В iOS 27 Apple добавила новый способ создавать display link прямо от UIWindowScene. Теперь модель становится более современной: display-driven работа принадлежит конкретной сцене, что как будто создано для iPad или Stage Manager, но я все еще топлю за теорию о складном iPhone. Итак, есть задачи, где одна scene активна, другая нет, а третья вообще переехала на другой display. В такой модели глобально думать про экран становится всё менее удобно, проще сказать: вот конкретная UIWindowScene, и вот работа, которая должна синхронизироваться с её display. Apple даже депрекейтит старый UIScreen.displayLink(...) и предлагает использовать equivalent API на UIWindowScene. Тут меняется модель владения, если анимация, рендеринг или frame-driven логика относится к конкретному окну, то и display link должен жить рядом с этим окном. Так проще управлять жизненным циклом, не продолжать делать работу для scene, которая уже не нужна, проще думать про multi-window поведение. Главное не превращайте CADisplayLink в молоток, это не замена Timer. Если нужно обновить что-то раз в секунду или периодически проверить значение, достаточно обычного timer или async task. Display link стоит доставать тогда, когда важна плавность и привязка к кадрам. Ну и не забываем что это beta API iOS 27, так что API и поведение могут поменяться до релиза.

1️⃣2️⃣3️⃣4️⃣5️⃣ SE-0532: Optional noncopyable improvements and generalizations в Optional добавляют ref, mutableRef, put(), а
1️⃣2️⃣3️⃣4️⃣5️⃣ SE-0532: Optional noncopyable improvements and generalizations в Optional добавляют refmutableRefput(), а ещё обобщают mapflatMap и unsafelyUnwrapped для noncopyable wrapped values! Это все про движение Swift в сторону ownership, borrowing, move-only типов и более явного управления ресурсами. Чтобы Swift нормально работал с noncopyable значениями, Optional тоже должен уметь с ними жить без боли. Проблема была в том, что обычный if let для noncopyable optional мог использовать значение:
if let payload = optional {
    ...
}
И получить ошибку use after consume Просто потому что значение нельзя скопировать, а язык должен очень аккуратно следить, кто им владеет. В SE-0532 предлагают сделать работу с такими optional более явно управляемой: 🟢ref — чтобы получить borrowed reference к значению внутри optional 🟢mutableRef — чтобы изменить значение внутри optional без вытаскивания наружу 🟢put() — чтобы положить новое значение в optional и сразу получить mutable reference на него Плюс mapflatMap и unsafelyUnwrapped становятся более пригодными для noncopyable и nonescapable типов. Понятное дело, что скорее всего нас это особо не заденет, noncopyable-типы пока не стали повседневной частью iOS-разработки, да и врядли станет, но вот для библиотек и низкоуровневого кода, это удобный синтаксический сахар

📱 Три SwiftUI group, которые легко перепутать В SwiftUI есть три модификатора с очень похожими названиями: ➡️ compositingGro
📱 Три SwiftUI group, которые легко перепутать В SwiftUI есть три модификатора с очень похожими названиями: ➡️ compositingGroup() ➡️ geometryGroup() ➡️ drawingGroup() Но работают на разных уровнях. Если добавить не тот group, ничего магического не произойдёт. В лучшем случае не изменится ничего. В худшем появится лишняя работа для рендера 🟡compositingGroup() нужен, когда проблема в графическом результате. Классический пример: несколько аватарок лежат внахлёст, и вы ставите opacity на весь ряд. Без compositingGroup() прозрачность может примениться к каждой аватарке отдельно. В итоге они начинают просвечивать друг через друга, хотя вы хотели просто сделать весь ряд полупрозрачным. То есть это не про layout. Это про то, как группа выглядит после композиции 🟡geometryGroup() нужен, когда проблема в геометрии. Например, родитель двигает view, а внутри в этот же момент меняется текст, размер или фон. Без явной границы SwiftUI может анимировать части view отдельно, и интерфейс на мгновение выглядит так, будто элемент развалился на куски 🟡drawingGroup() звучит похожим, но это уже другая история. Он рендерит содержимое в offscreen image, а потом SwiftUI работает с ним как с одной картинкой. Иногда это может помочь, если у вас сложная графика, много shape, blur, clipping и повторяющихся операций. drawingGroup() лучше добавлять не по ощущениям, а после профилирования, т.к. он достаточно затратный. А еще он подходит именно для графического SwiftUI-контента. Text, Image, Shape и композиции из них. А вот произвольные UIKit/AppKit view, web view или media player он нормально в картинку не превратит Статья отлично демострирует работу SwiftUI изнутри. Иногда баг в интерфейсе не в анимации, не в layout и не в цветах. Он просто в том, на каком этапе SwiftUI вы пытаетесь сгруппировать view. И чем лучше понимаешь этот pipeline, тем меньше хочется лечить всё подряд случайным .drawingGroup()

🧠 Разработка ИИ-приложений с Claude Code В чем суть? Claude Code ускоряет написание и отладку кода. Но его главная сила — не
🧠 Разработка ИИ-приложений с Claude Code В чем суть? Claude Code ускоряет написание и отладку кода. Но его главная сила — не в магии «сделай всё за меня», а в умении разработчика грамотно ставить задачи. ❌ Если просто попросить «сделай приложение» — получите набор нерабочих кусков. ✅ Если дробить задачу, задавать контекст и контролировать архитектуру — получите готовый продукт. Бесплатный вебинар курса «Вайб-кодинг» 21 июля в 20:00, где разберем практическое использование Claude Code для создания: — Telegram-ботов и ИИ-агентов; — Внутренних сервисов и автоматизаций; — Серверной логики и программных интерфейсов (API). 🎯 Ключевые темы урока: Структура промптов и работа с большими проектами; Пошаговая разработка и проверка результата (а не генерация «вслепую»); Поиск ошибок и доработка готового кода. 👨‍💻 Для кого этот урок? Для тех, кто хочет выстроить процесс вайб-кодинга в реальных продуктах, а не просто играться с генерацией фрагментов. 🚫 Это НЕ для вас, если: — Вы хотите заменить инженерное мышление одним запросом; — Не готовы проверять результат и контролировать код; — Думаете, что ИИ соберет качественный продукт без вашей задачи и контекста. 👉 Зарегистрироваться учиться строить системы, а не просто генерировать строки кода! Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576 www.otus.ru

🐥 Multipeer Connectivity все Multipeer Connectivity нужен для сценариев, когда несколько Apple-устройств должны найти друг д
🐥 Multipeer Connectivity все Multipeer Connectivity нужен для сценариев, когда несколько Apple-устройств должны найти друг друга рядом и обмениваться данными без вашего сервера, например: локальный multiplayer, передача данных между iPhone и iPad, офлайн-синхронизация, companion app, совместная работа рядом. Но использовать это можно было на бумаге - взял MCSession, нашёл соседние устройства, подключился, отправил данные. В реальных же приложениях у Multipeer Connectivity давно накопилась репутация фреймворка, который работает только в демо. У пользователей же 🟡устройства видят друг друга, но не подключаются 🟡сессия зависает в connecting, а потом падает в notConnected. 🟡если на двух девайсах всё хорошо, то на нескольких точно разваливается Apple выпустила technote про миграцию с Multipeer Connectivity на Network framework. А на Developer Forums инженеры Apple довольно прямо говорят: если вы упёрлись в проблемы MCSession, смотрите в сторону Network framework. Multipeer Connectivity слишком много прячет внутри себя. Он сам решает, как искать устройства, как соединять peers, как строить сессию и какой сетевой путь использовать. Это удобно на старте, но плохо, когда нужно понять, почему всё сломалось. Network framework менее магический, зато честный: 🟢NWBrowser для поиска устройств 🟢NWListener для входящих соединений 🟢NWConnection для общения 🟢TCP, UDP, QUIC и свой протокол поверх этого Если у вас старый проект на MCSession, не обязательно срочно всё переписывать. Но если вы сегодня проектируете новую фичу для обмена данными между устройствами рядом, я бы уже не начинал с Multipeer Connectivity