Forwarded from Flutter & Dart | Мобильный трудоголик
Всем привет! Недавно наткнулся на статью, в которой разработчик делится опытом тестирования Flutter-приложения на iPhone друга без Mac и без подписки Apple Developer. Знакомая ситуация: есть приложение на Flutter, нужно показать кому-то с iPhone. Mac нет, платить $99 в год за Apple Developer Program жалко. Оказывается, есть рабочий путь, и автор его подробно описал. Не магия, а грамотная сборка цепочки из четырех инструментов.
Почему iOS сложнее Android:
На Android тестовая установка занимает пятнадцать минут. Включил отладку по USB, запустил adb install, готово. Google Play Console - $25 единоразово. RuStore - бесплатно.
С iPhone все иначе. Официальный путь Apple: Mac для Xcode, подписка $99 в год, TestFlight. Дорого и не всегда доступно.
Схема из четырех шагов:
Есть обходной путь, который обходится без Mac и без платной подписки.
Нюансы, которые важно знать:
Тестировать Flutter-приложение на iPhone без Mac и без $99 реально. Схема из четырех инструментов работает. Основная сложность не в настройке, а в том, чтобы найти все куски и собрать их в одно целое.
Для инди-разработчика это рабочий путь, чтобы показать приложение друзьям и тестировщикам. Для полноценного релиза в App Store придется решать вопрос с оплатой подписки. Но тестирование на железе перестает быть барьером.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤7👏2🔥1🙏1
В Claude Code на десктопе появилась поддержка iOS Simulator. Теперь агент может запускать приложение в симуляторе, управлять им, делать скриншоты и проверять работу интерфейса. Панель с симулятором открывается прямо в приложении, рядом с чатом. Это не требует прав на доступ к экрану и не переключает рабочие окна.
Как это работает:
Когда Claude собирает или запускает приложение, он автоматически открывает симулятор в специальной панели. Можно попросить его проверить конкретный экран, пройти по потоку или зафиксировать баг. Симулятор показывает устройство в реальном времени. Видно, что делает агент и можно в любой момент вмешаться.
Управлять симулятором можно как через Claude, так и вручную. Клики, свайпы, кнопки Home и Lock, поворот экрана - все работает прямо из панели. Можно делать скриншоты и записи экрана.
Важно: у каждого сеанса свой симулятор. Это значит, что параллельные сессии не мешают друг другу.
Что важно знать про доступ:
Claude запрашивает разрешение на управление симулятором один раз на устройство. После того как вы разрешили, он может кликать, вводить текст и делать скриншоты без дополнительных запросов. Это не требует прав на доступ к экрану, потому что все происходит внутри симулятора.
Действия вроде открытия URL или сборки проекта следуют обычным правилам разрешений. Их можно настроить отдельно.
Если нужно отключить доступ - есть настройка в приложении. Для организаций доступны управляемые политики, которые отключают симулятор для всех.
Поддержка iOS Simulator в Claude Code - это шаг в сторону более глубокой интеграции агентов в процесс разработки. Теперь можно не просто генерировать код, но и проверять его работу в симуляторе. Агент сам запускает приложение, кликает по экранам, проверяет изменения. Разработчик видит все в реальном времени и может вмешаться в любой момент.
Это не замена ручного тестирования, но серьезное ускорение для рутинных проверок. Особенно когда нужно быстро убедиться, что правка не сломала UI или поток. И главное - не приходится переключаться между окнами и терять контекст.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
❤17👍10🤔3🔥1🤯1
В iOS 27 компания Apple изменила подход к работе с CADisplayLink. Раньше его создавали через UIScreen. Теперь через UIWindowScene. Изменение выглядит небольшим, но оно меняет модель владения и делает код более предсказуемым в многоконных приложениях.
В чем разница между Timer и CADisplayLink:
Timer и CADisplayLink решают разные задачи. Timer привязан к интервалам времени, он срабатывает по расписанием цикла выполнения. CADisplayLink синхронизирован с частотой обновления экрана. Это принципиальная разница.
Timer подходит для задач, где не важен каждый кадр. Обратный отсчет, периодический опрос сервера, обновление данных в фоне. CADisplayLink для визуальных задач, где важна плавность и синхронизация с экраном. Анимации, игры, рендеринг, физика.
Если попытаться использовать Timer для визуального движения, он будет менее плавным, потому что Timer не учитывает момент обновления кадров. Он просто срабатывает, когда приходит время.
Что нового в iOS 27:
В iOS 27 компания Apple добавила новый способ создания CADisplayLink прямо через UIWindowScene. Старый метод через UIScreen объявлен устаревшим.
// Новый способ в iOS 27
if let scene = view.window?.windowScene {
displayLink = scene.displayLink { link in
print(link.targetTimestamp - link.timestamp)
}
displayLink?.add(to: .main, forMode: .common)
}
Это логичный шаг. В многоконных приложениях, особенно на iPad с Stage Manager, одна сцена активна, другая нет, третья вообще на другом дисплее. Глобально думать про экран становится неудобно. Проще сказать: «вот конкретная UIWindowScene и вот работа, которая должна синхронизироваться с ее дисплеем».
Почему это важно:
Это улучшает модель владения. Если анимация или рендеринг принадлежат конкретному окну, то и CADisplayLink должен жить рядом с этим окном. Так проще управлять жизненным циклом, а не продолжать делать работу для сцены, которая уже неактивна.
В многоконных приложениях становится проще думать о поведении каждой сцены отдельно. Одна сцена может обновляться с частотой 120 Гц, другая с 60 Гц. CADisplayLink, привязанный к конкретной сцене, автоматически подстраивается под ее дисплей.
Когда использовать CADisplayLink, а когда Timer:
Главное, что стоит запомнить:
CADisplayLink не замена Timer. Это специализированный инструмент для визуальных задач.
CADisplayLink в iOS 27 стал более сцено-ориентированным. Это небольшое API-изменение, но важное архитектурное решение. Оно отражает вектор развития UIKit в сторону многоконных приложений.
Для разработчиков это значит, что визуальную работу теперь удобнее привязывать к конкретной сцене, а не к глобальному экрану. Проще управлять жизненным циклом, проще думать о многоконном поведении.
Но главное правило остается прежним: CADisplayLink - это не универсальный таймер. Это инструмент для визуальных задач, где важна синхронизация с кадрами. Для всего остального есть Timer.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
С момента появления SwiftData разработчики периодически сталкивались с ограничениями. Фильтрация по enum требовала костылей. Группировка данных в секции была недоступна. Наблюдение за изменениями вне SwiftUI View - сложной задачей. В iOS 27 компания Apple закрыла большинство этих пробелов. Разберем ключевые улучшения.
Enum-предикаты стали реальностью:
До iOS 27 фильтрация по enum-свойствам была больной темой. Если модель содержала enum, приходилось сохранять его raw-значение в отдельное поле и строить предикаты уже на основе него. Теперь это работает напрямую.
_books = Query(filter: #Predicate<Book> {
$0.category == .fiction
})
Модель становится чище. Не нужно дублировать данные только для фильтрации.
Группировка в секции:
Появилась поддержка группировки результатов через параметр sectionBy в макросе
@Query.
@Query(sort: \Expense.name, sectionBy: \Expense.budgetName)
var expenses: [Expense]
При этом данные группируются прямо в базе, а не в памяти. Есть ограничение: значение для группировки должно быть сохраненным свойством. Связанные свойства (например, expense.budget?.name) пока не поддерживаются. Приходится дублировать данные.
Составные предикаты:
Раньше, чтобы объединить несколько условий, нужно было собрать все в один большой предикат. Сейчас появились Predicate(all:) и Predicate(any:).
let searchPredicate = #Predicate<Book> {
$0.name.localizedStandardContains(search)
}
let bestSellerPredicate = #Predicate<Book> {
$0.isBestSeller == isBestSeller
}
_books = Query(
filter: Predicate(all: [searchPredicate, bestSellerPredicate])
)
Удобно для динамических фильтров. Предикаты можно собирать по частям и комбинировать.
Атрибут .codable:
Новый параметр для макроса
@Attribute. Если тип нельзя разложить на колонки, но он реализует Codable, SwiftData может сохранить его как BLOB.
@Attribute(.codable)
var identifier: MKMapItem.Identifier
Важный нюанс: данные, сохраненные через .codable, нельзя использовать в фильтрах и сортировках. Это просто сериализованный кусок данных.
SwiftData в iOS 27 стала более практичной. Меньше костылей, больше возможностей. Enum-предикаты убирают дублирование. Секции упрощают представление данных. .codable закрывает проблему со сложными типами. ResultsObserver позволяет строить логику на изменениях без привязки к UI.
Это не революция, но плотное обновление, которое делает SwiftData пригодным для более сложных проектов. Особенно тех, где данные нужно не просто показывать, но и обрабатывать, синхронизировать и обновлять за пределами интерфейса.
Но еще не все проблемы решены. Группировка по связанным свойствам до сих пор не работает. Хранилище изменений через HistoryObserver требует ручной работы с токенами. Но направление верное.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
Привет! С новым Siri на базе ИИ компания Apple обещает, что можно будет просто сказать «Найди ту футболку, которую я хотел купить пару месяцев назад» и Siri найдет ответ. Но как это работает для сторонних приложений? В iOS 27 обновился Siri SDK. Теперь приложения могут лучше интегрироваться с голосовым ассистентом. Разберем ключевые улучшения.
AppEntity и IndexedEntity:
Для того чтобы ваши данные могли участвовать в запросах к Siri, нужно создать легкую версию модели - AppEntity. Это не сама модель, а ее описание для системы.
struct TeamEntity: AppEntity {
static var defaultQuery = TeamEntityQuery()
let id: String
@Property(title: "Team Name") var name: String
@Property(title: "Roster Size") var rosterSize: Int
}
Если ваши данные можно индексировать, достаточно добавить IndexedEntity. Система автоматически проиндексирует контент и Siri сможет его искать.
extension TeamEntity: IndexedEntity {}
С помощью
@Property(indexingKey:) можно указать, какие именно поля должны участвовать в поиске.App Schemas:
Apple подготовила готовые схемы для популярных типов данных: сообщения, контакты, задачи. Если ваше приложение попадает в одну из этих категорий, нужно просто указать схему через
@AppEntity.
@AppEntity(schema: .messages.message)
struct MessageEntity: IndexedEntity {
@Property(indexingKey: \.textContent) var body: AttributedString?
}
Xcode подсказывает доступные поля. Apple уже настроила Siri на понимание этих схем - контекст, уточняющие вопросы и связки между действиями работают почти без дополнительного кода.
On-screen Awareness:
Чтобы Siri могла отвечать на вопросы о том, что сейчас на экране, есть два подхода. NSUserActivity для одного элемента (например, фотографии). View annotations для списков (например нескольких сообщений или контактов).
.userActivity("com.example.entity", element: entity.asEntity()) { entity, activity in
activity.title = entity.title
}
Или с помощью модификатора .appEntityIdentifier.
.appEntityIdentifier(EntityIdentifier(for: Entity.self, identifier: p.id))
Передача данных через Transferable:
Для обмена данными между приложениями через Siri (например «Отправь это письмо» или «Создай событие») используется Transferable.
extension TeamEntity: Transferable {
static var transferRepresentation: some TransferRepresentation {
IntentValueRepresentation(
exporting: { entity in
IntentPerson(name: .displayName(entity.name))
},
importing: { person in
ContactEntity(name: person.name.displayString)
}
)
}
}
Новый Siri SDK делает интеграцию с голосовым ассистентом более структурированной. AppEntity, IndexedEntity и готовые схемы закрывают большинство сценариев. On-screen Awareness позволяет приложениям делиться контекстом с Siri. Transferable дает возможность передавать данные между приложениями.
Но есть белое пятно: что делать, если приложение не попадает в готовые схемы Apple? Как использовать весь потенциал нового Siri в этом случае? Ответа пока нет.
Тем не менее, для большинства приложений подход понятный и достаточно простой. Начать стоит с конформности IndexedEntity - это самый быстрый способ сделать данные доступными для Siri без глубокой перестройки архитектуры.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Кот Денисова
Все еще встречаются разработчики, которые однажды попробовали ИИ чат-боты и на этом остановились. ChatGPT в 2022 году выдавал ерунду? Значит нейросети ничего не умеют и пишут ерунду. Никакой логики, почему через три года ситуация могла измениться. Просто застывшее убеждение, подкрепленное отсутствием желания попробовать снова.
Как изменились инструменты:
За это время технологии шагнули далеко. Современные ИИ не просто отвечают на вопросы - они анализируют весь проект, понимают контекст, вносят правки в несколько файлов одновременно. Да, ошибки случаются. Но частота не идет ни в какое сравнение с тем, что было на заре их появления.
Двойные стандарты:
При этом те же самые люди спокойно копируют куски кода с форумов, Stack Overflow, случайных статей и видеоуроков. По их мнению код от человека - это нормально, а от машины - плохо. Хотя качество кода из непроверенных источников никто не гарантирует.
Про баги:
Главный аргумент скептиков - ИИ плодит баги. Но их собственный код тоже далек от идеала. Просто свои ошибки кажутся простительными, а чужие - нет. Человек может накосячить с душой, а машина - бездушно. Но результат для бизнеса одинаковый.
Кто на самом деле в выигрыше:
Пока одни спорят в комментариях, их коллеги уже используют помощников и сдают задачи быстрее. Разрыв в продуктивности становится все заметнее. И со временем он только увеличится.
ИТ развивается непрерывно, и каждый разработчик, который хочет оставаться востребованным, обязан идти в ногу со временем. Инструменты изменились, и игнорировать это изменение означает сознательно отставать. Настоящая ценность специалиста всегда была не в умении печатать код, а в умении принимать архитектурные решения и видеть картину целиком. Отрицание прогресса не защитит карьеру, а только приблизит момент, когда коллеги, использующие современные средства, окончательно уйдут вперед.
Подписаться на канал:
Закрытый канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
❤17💯9👍5🙏1👀1
На WWDC26 компания Apple представила новый способ работы с Foundation Models. Теперь с ними можно взаимодействовать не только через Xcode, но и напрямую из терминала. Для этого достаточно обновить Mac до последней версии, установить Xcode 27 (бета) и запустить команду fm в консоли.
Инструмент позволяет отправлять запросы к моделям, проверять их доступность, считать токены и работать со структурированными данными. Например команда fm respond "Ваш запрос" отправит запрос к модели, а fm available покажет, какие модели доступны на устройстве. Есть поддержка потоковой передачи, структурированного вывода через JSON Schema и работа с изображениями. CLI также позволяет запускать локальный сервер для интеграции с другими инструментами.
Foundation Models CLI - это шаг к тому, чтобы сделать Apple Intelligence доступной не только для iOS-разработчиков, но и для всех, кто работает в терминале. Скрипты, автоматизация, быстрые эксперименты - теперь все это можно делать без Xcode.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15 9❤3🔥3🙏1👀1
This media is not supported in your browser
VIEW IN TELEGRAM
На WWDC 26 компания Apple сделала важный шаг, который меняет подход к адаптивной верстке. Теперь приложения для iPhone можно запускать на Mac через iPhone Mirroring с изменяемым размером окна. А приложения для iPhone на iPad тоже получают возможность изменять размер окна. Это значит, что привычный horizontalSizeClass перестает быть основным критерием для определения ширины экрана.
Почему ваше приложение может выглядеть некрасиво:
Если протестировать свое приложение в этой новой среде, можно обнаружить, что оно ведет себя не так, как ожидалось. NavigationSplitView не переключается на многоколоночный режим. Вкладки не превращаются в боковую панель. А horizontalSizeClass остается .compact, даже когда окно становится шире.
На iPad в режиме pad horizontalSizeClass все еще меняется в зависимости от ширины окна. Но если запустить iPad в режиме совместимости только для iPhone, поведение становится таким же, как у iPhone-хоста в Device Hub.
Это не баг беты. Это осознанное решение Apple.
Новые правила:
В сессии «Modernize your UIKit app» Apple прямо говорит: приложения для iPhone попадают в среду с изменяемым размером. Разработчики должны адаптироваться к произвольным размерам сцены, а не рассчитывать на фиксированное соотношение сторон.
UIScreen.main и границы экрана больше не надежны. Вместо них нужно использовать эффективную геометрию оконной сцены или фактический доступный размер представления.
userInterfaceIdiom больше не подходит как основа для решений по компоновке. Приложение для iPhone на iPad или в зеркалировании на Mac может работать в контексте телефона, но это не означает узкий экран.
Ориентация тоже больше не надежна. В среде с изменяемым размером поддерживаемые ориентации становятся рекомендациями, а не жесткими правилами.
Надежен ли horizontalSizeClass:
Короткий ответ - да. Но он отражает обобщенные характеристики текущего окружения, а не фактическую ширину окна.
Широкое окно на iPhone не гарантирует .regular. Узкое окно на iPad может давать разные результаты в зависимости от контекста. Это одна из самых частых ошибок в этом году.
userInterfaceIdiom описывает только семантику хоста. horizontalSizeClass - контекстную оценку системы. А геометрия представления или сцены дает точную информацию для компоновки.
Эволюция Apple:
Если посмотреть на изменения последних лет, видна четкая тенденция. Apple последовательно уменьшает важность «типа устройства + ориентации» как основы для компоновки.
В 2014 году появились Size Class. В 2019 - UIScene и многоконность. В 2022 - десктоп-класс iPad. В 2023 - система trait, которая распространяется слоями. В 2024 - Tab Bar и Sidebar как разные представления одной иерархии. В 2026 - iPhone-приложения в изменяемом размере.
Вместе с этим полноэкранный режим на iPad постепенно переходит из «того, что требует разработчик» в «то, что определяется пользователем и системой».
Эпоха фиксированного холста подходит к концу. horizontalSizeClass больше не дает точного ответа на вопрос, сколько места доступно. Геометрия представления и сцены становится основным инструментом для адаптивной верстки.
Пользователи теперь сами решают, как будет выглядеть приложение. Разработчикам нужно учитывать больше сценариев. Количество случаев, которые нужно обрабатывать, увеличилось. Но Apple дала инструменты, чтобы справляться с этим. Главное - перестать полагаться на старые подходы и начать строить интерфейсы вокруг доступного пространства.
И это нововведение - еще один намек на то, что складной iPhone уже не за горами. Apple последовательно готовит экосистему к устройствам с динамически меняющейся геометрией экрана. Разработчикам пора готовиться.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Flutter & Dart | Мобильный трудоголик
Вышла новая версия Flutter 3.47. Обновление заметное. Material и Cupertino наконец-то выехали из SDK в отдельные пакеты. Impeller стал рендерером по умолчанию на десктопе. Плюс подготовка к осенним обновлениям Apple и другие улучшения. Давайте разберем все основные изменения.
Material и Cupertino теперь отдельные пакеты:
Главное изменение. Material и Cupertino больше не встроены в SDK. Теперь это отдельные пакеты на
pub.dev: material_ui и cupertino_ui. Это значит, что обновления виджетов теперь могут выходить независимо от релизов Flutter.Пока это опционально. Старые импорты из package:flutter/material.dart все еще работают, но они объявлены устаревшими и будут удалены в ноябре.
Для миграции достаточно выполнить команду:
dart fix --apply --code=migrate_design_widgets
После этого импорты обновятся автоматически. Если что-то пошло не так, можно добавить пакеты вручную:
flutter pub add material_ui
flutter pub add cupertino_ui
Важный момент для пакетов с зависимостями: если вы еще не обновились, а ваши зависимости уже используют новый подход, поможет MaterialUiCompatibilityBridge.
Также вместе с UI-пакетами разобрали flutter_localizations. Теперь делегаты локализации живут внутри material_ui и cupertino_ui, а не в отдельном пакете.
Подготовка к iOS 27 и macOS 27:
Apple осенью выпустит Xcode 27 с новыми требованиями. Минимальная версия iOS поднята до 15, macOS до 12. iOS 27 SDK требует жизненного цикла UIScene. Приложения без него не запустятся на новых устройствах.
Для большинства проектов CLI мигрирует автоматически. Но если в проекте есть кастомный AppDelegate, придется править руками. Лучше проверить сейчас.
Также Flutter постепенно сворачивает поддержку Intel Mac. В этой версии только предупреждения, но в будущем сборка на Intel перестанет работать. Можно уже сейчас переключиться на ARM64-only:
flutter config --enable-macos-arm64-only
По Swift Package Manager прогресс: 92 из топ-100 плагинов уже перешли на SPM. Если вы еще не включили SPM, можно попробовать:
flutter config --enable-swift-package-manager
Impeller теперь на десктопе по умолчанию:
Impeller стал рендерером по умолчанию на macOS, Windows и Linux. Если вы не знаете, что это - новый рендеринг-движок, который компилирует шейдеры на этапе сборки, а не в рантайме. Это решает проблему шейдерных джанков. Первая анимация работает так же плавно, как и все последующие.
На macOS также включили Wide Gamut Color - более насыщенные и точные цвета.
Отключить Impeller можно, но в будущих версиях опция будет удалена.
Flavors для десктопа:
Flavors, которые работали на мобилках, теперь доступны и на Windows и Linux. Можно использовать разные ассеты и настройки для разных окружений.
flutter build windows --flavor production
flutter build linux --flavor staging
Экспериментальный многооконный режим тоже доработали. На Windows и Linux появились popup-окна. Можно делать контекстные меню и палитры.
Flutter 3.47 - важное обновление. Главное - Material и Cupertino выехали из SDK. Это упростит обновления виджетов и снизит зависимость от релизов Flutter.
Impeller на десктопе - большой шаг для производительности. Flavors и многооконный режим делают десктоп-разработку более гибкой. А подготовка к осеннему релизу Apple заставляет проверить проекты на совместимость.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤7🔥2🙏1🤝1
Как изменить форму стеклянных кнопок в SwiftUI.
В iOS 26 появились новые Liquid Glass API, включая стиль кнопок .glass. Это сделало кнопки более современными и визуально привлекательными. Но есть один нюанс: вне навигационной панели стеклянная кнопка по умолчанию отображается в виде капсулы. Для текстовых кнопок это хорошо, но для иконок часто хочется сделать круглую форму. У Apple есть готовое решение и это не кастомный стиль.
В чем суть проблемы:
Когда вы используете .buttonStyle(.glass), SwiftUI сам выбирает форму кнопки. В большинстве случаев это капсула. Для маленьких иконок, например переключателя темы или настройки, круглая форма выглядит более естественно.
Можно попытаться обрезать кнопку через .clipShape(.circle), но это не совсем то, что нужно. Обрезка применяется после того, как стиль уже отрисовал кнопку. Эффекты, материалы, подсветка и hover-состояния могут работать некорректно.
Верное решение - buttonBorderShape:
В SwiftUI есть модификатор buttonBorderShape, который задает форму системной плашки кнопки. Он работает с системными стилями, включая .glass.
Это не обрезка, а указание системе, какую форму использовать для кнопки. Все эффекты и состояния сохраняются.
Доступные варианты:
Модификатор поддерживает несколько предустановленных форм:
🔵 .automatic - система решает сама.
🔵 .capsule - капсула, подходит для текстовых кнопок.
🔵 .circle - круг, хорош для иконок.
🔵 .roundedRectangle - скругленный прямоугольник.
🔵 .roundedRectangle(radius: 12) - с заданным радиусом.
Можно применять модификатор как к отдельной кнопке, так и к контейнеру. Если повесить на HStack, все кнопки внутри получат одинаковую форму.
🔗 Читать подробнее
💡 Вывод:
.buttonStyle(.glass) дает современный вид, но форма по умолчанию - капсула. Для иконок это не всегда хорошо. Решение - .buttonBorderShape(.circle). Это старый модификатор, но в контексте стеклянных кнопок он работает идеально и не нужно писать кастомный стиль.
Подписаться на канал:
➡️ Telegram | Max
В iOS 26 появились новые Liquid Glass API, включая стиль кнопок .glass. Это сделало кнопки более современными и визуально привлекательными. Но есть один нюанс: вне навигационной панели стеклянная кнопка по умолчанию отображается в виде капсулы. Для текстовых кнопок это хорошо, но для иконок часто хочется сделать круглую форму. У Apple есть готовое решение и это не кастомный стиль.
В чем суть проблемы:
Когда вы используете .buttonStyle(.glass), SwiftUI сам выбирает форму кнопки. В большинстве случаев это капсула. Для маленьких иконок, например переключателя темы или настройки, круглая форма выглядит более естественно.
Можно попытаться обрезать кнопку через .clipShape(.circle), но это не совсем то, что нужно. Обрезка применяется после того, как стиль уже отрисовал кнопку. Эффекты, материалы, подсветка и hover-состояния могут работать некорректно.
Верное решение - buttonBorderShape:
В SwiftUI есть модификатор buttonBorderShape, который задает форму системной плашки кнопки. Он работает с системными стилями, включая .glass.
Button {
// Действие
} label: {
Image(systemName: "sun.max")
}
.buttonBorderShape(.circle)
.buttonStyle(.glass)Это не обрезка, а указание системе, какую форму использовать для кнопки. Все эффекты и состояния сохраняются.
Доступные варианты:
Модификатор поддерживает несколько предустановленных форм:
Можно применять модификатор как к отдельной кнопке, так и к контейнеру. Если повесить на HStack, все кнопки внутри получат одинаковую форму.
HStack {
Button { ... } label: { Image(systemName: "sun.max") }
Button { ... } label: { Image(systemName: "moon") }
}
.buttonBorderShape(.circle)
.buttonStyle(.glass).buttonStyle(.glass) дает современный вид, но форма по умолчанию - капсула. Для иконок это не всегда хорошо. Решение - .buttonBorderShape(.circle). Это старый модификатор, но в контексте стеклянных кнопок он работает идеально и не нужно писать кастомный стиль.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
На WWDC 2026 компания Apple объявила, что разработчики с менее чем 2 миллионами первых загрузок в App Store смогут использовать Foundation Models, работающие в Private Cloud Compute, без оплаты облачного API. Это делает ИИ-инфраструктуру доступной для тех, кто только начинает.
Кто может получить доступ:
Условия простые. Разработчик должен быть участником программы малого бизнеса Apple. Общее количество первых загрузок всех его приложений в App Store должно быть меньше 2 миллионов. Также нужен entitlement для Private Cloud Compute.
Если приложение превышает лимит, Apple уведомляет разработчика и дает 6 месяцев на переход к платной модели или альтернативному решению.
Почему это важно:
Сейчас эксперименты с ИИ перестали быть дешевыми. Запросы к большим моделям - это затраты на инфраструктуру, которые для начинающих разработчиков могут стать серьезным барьером. Apple убирает этот барьер, давая доступ к моделям с беспрецедентной защитой приватности.
Это похоже на программу малого бизнеса, где Apple снижает комиссию для небольших разработчиков. Цель - привлечь независимых разработчиков и стартапы, которые не хотят нести дополнительные расходы на облачные сервисы.
Что еще изменилось в Foundation Models:
В этом году платформа расширяется. Появилась поддержка работы с изображениями. Добавлена интеграция с серверными моделями - разработчики могут подключать поставщика облачных услуг по своему выбору. Это дает гибкость для решения более сложных задач.
Apple делает ИИ доступным для небольших команд. Бесплатный доступ к Foundation Models в Private Cloud Compute - это способ снизить порог входа в мир больших моделей. Независимые разработчики могут экспериментировать и создавать функции на основе ИИ без начальных затрат на инфраструктуру.
Если приложение выстрелит и превысит 2 миллиона загрузок - придется начать платить. Но к тому моменту у разработчика уже будет работающий продукт, а не гипотеза. Это разумный подход, который помогает стартапам не тратить дополнительные средства на этапе прототипа.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
❤16🔥9👍4🤯1🙏1
This media is not supported in your browser
VIEW IN TELEGRAM
В iOS 27 SwiftUI получил обновление для управления анимациями при навигации. Раньше для переходов было только два встроенных варианта: .automatic и .zoom(sourceID:in:). Теперь добавили .crossFade и AnyNavigationTransition. Это дает больше гибкости без необходимости писать кастомные решения.
Проблема с zoom:
ZoomNavigationTransition хорошо работает, когда у перехода есть визуальный источник. Пользователь тапает карточку или ячейку, и она плавно расширяется до полноэкранного вида. Это выглядит естественно.
Но что делать, если экран открывается по-другому? Например, из deeplink, уведомления, App Intent или Siri. В таких случаях у системы нет визуальной точки отсчета. Zoom становится искусственным и неестественным.
Решение - crossFade:
В iOS 27 появился CrossFadeNavigationTransition. Это новый тип перехода, который не требует источника. Экран просто плавно появляется через затемнение, без привязки к какому-либо элементу.
.sheet(isPresented: $showInfo) {
LandmarkInfo()
.presentationDetents([.medium])
.navigationTransition(.crossFade)
}Идеально для случаев, где у системы нет визуального источника. Например, открытие по уведомлению или из виджета.
Динамический выбор перехода через AnyNavigationTransition:
Второе нововведение - AnyNavigationTransition. Раньше .navigationTransition(_:) требовал конкретный тип на месте вызова. Нельзя было выбрать переход динамически, в зависимости от того, как был открыт экран.
Теперь можно обернуть любой переход в AnyNavigationTransition и использовать как значение.
struct LandmarkInfo: View {
var useCrossFade: Bool
var transition: AnyNavigationTransition {
useCrossFade
? AnyNavigationTransition(.crossFade)
: AnyNavigationTransition(.automatic)
}
var body: some View {
InfoContent()
.presentationDetents([.medium])
.navigationTransition(transition)
}
}Один и тот же экран может открываться по-разному. По тапу - используем zoom. Из уведомления - crossFade. По диплинку - automatic. И это работает без дублирования кода.
CrossFadeNavigationTransition решает проблему переходов без визуального источника. AnyNavigationTransition позволяет выбирать переход динамически в зависимости от контекста.
Современные приложения открываются не только по тапу на ячейку. Виджеты, уведомления, Siri, universal links - каждый сценарий требует своего поведения. Новые API делают навигацию в SwiftUI более гибкой и естественной.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16 7❤4🔥2🙏1
Forwarded from Кот Денисова
Наткнулся на откровенную статью разработчика, который трижды пытался сделать прибыльное приложение. Результат: 2000 установок и 8 платных подписок по 6 долларов. Одна из них - его собственная. После полугода работы по ночам, в выходные и в отпуске.
Это не первый блин комом. Первый проект умер на этапе обучения. Второй - после полугода разработки и потраченных полумиллиона рублей - оказался никому не нужен. Ноль пользователей. Третий, с умными установками «не делать маркетплейсы» и «привлекать пользователей с первых дней», дал 2000 установок и конверсию, о которой даже говорить стыдно.
Главное открытие автора:
80% времени и сил уходит не на код. А на маркетинг. Реклама в сторах - выкинутые деньги. 5 тысяч рублей дают 30 установок. Из них 90% уходят сразу. Пара человек пользуются бесплатно. Никто не покупает. Платная реклама почти никогда не окупается. Единственное, что работает, - креативный подход и создание контента. Но на это уходит 80% усилий. Мечты о пассивном доходе разбиваются о реальность: разработка - это меньшая часть работы.
Эмоциональные качели:
Автор описывает состояние, которое знакомо каждому, кто пробовал: от вдохновения до «на что я трачу свою жизнь». После очередной подписки надежда возвращается. Потом снова отчаяние. И так по кругу.
Добавляют масла инфоцыгане с курсами «Заработай 10к на приложении за 3 дня без навыков». Они тиражируют единичные успешные кейсы, выдавая их за систему. Про шансы, провалы и реальные бюджеты на маркетинг они молчат.
Мое мнение:
С приходом ИИ-агентов количество приложений в магазинах выросло в разы. Раньше конкуренция была огромной, теперь она запредельная. Да, хорошие и качественные приложения всегда будут востребованы. Но чтобы их раскрутить, нужны серьезные деньги на маркетинг. Пет-проект с минимальным бюджетом было сложно продвинуть и раньше. Сейчас - практически невозможно. ИИ упростил создание приложений, но не упростил их продвижение. Наоборот - усложнил, потому что предложение выросло, а внимание пользователей осталось прежним.
С точки зрения денег, делать свой продукт - плохая идея. Статистически выгоднее строить карьеру в найме. Но не все измеряется деньгами. Пет-проекты незаменимы для практики и обучения. Даже если проект не взлетит, навыки, которые вы прокачаете в процессе, останутся с вами навсегда.
Подписаться на канал:
Закрытый канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🤯8🤔3🔥1🙏1👀1
Apple провела реструктуризацию, затронувшую команды, работающие над Vision Pro, Siri и ИИ-интеграциями. Сокращено более 200 позиций: около 100 в Vision Pro, 100 в Siri и софтверных командах. Это часть стратегии по перераспределению ресурсов в сторону новых ИИ-разработок и устройств.
Что произошло с Vision Pro:
Команда Vision Pro сокращена примерно на 100 человек. Закрыто направление, отвечавшее за игры и уменьшена группа, создававшая иммерсивный видео-контент. Причина кроется в дороговизне производства. Один эпизод 3D-видео может стоить несколько миллионов долларов, а количество активных пользователей у данного устройства остается небольшим.
Apple не полностью отказывается от иммерсивного видео. Компания планирует производить меньше такого контента силами Apple и больше полагаться на сторонних разработчиков.
Почему так происходит:
Гарнитура, вышедшая в 2024 году за $3500 (сейчас стоит $3699) не стала массовым продуктом. Она оказалась дорогой, тяжелой и нишевой. Основное применение нашла в инженерной и медицинской среде, где требуется высокая точность визуализации.
Новый CEO Джон Тернус, по слухам, с самого начала не был сторонником Vision Pro. Именно он весной 2025 года перехватил команду разработчиков прикладного ИИ и контролировал развитие Apple Intelligence. Его приоритеты очевидны - ИИ и устройства, которые могут быть интегрированы в повседневную жизнь большего числа пользователей.
Сокращения в Siri и ИИ-командах:
100 сокращений пришлись на команды Siri и Intelligent Systems Experience - подразделение, отвечающее за интеграцию ИИ в устройства Apple. Это связано с переходом на новую архитектуру Siri AI.
Обновленная Siri, анонсированная на WWDC, построена на совершенно новой технической базе. Она должна понимать контекст, содержимое экрана и выполнять действия в приложениях. Переход на эту архитектуру требует других навыков, поэтому часть старых позиций сокращается, а новые создаются.
Apple сокращает 200 позиций - это капля в море для компании со штатом в 166 тысяч человек. Но это четкий сигнал: приоритеты изменились.
Vision Pro оказался слишком дорогим, слишком тяжелым и слишком нишевым. Иммерсивный контент - слишком дорогим в производстве. Игры - не нашли аудиторию. Компания не закрывает продукт, но сворачивает активное развитие.
Новая стратегия - ИИ и устройства, которые можно носить каждый день. Умные очки. AirPods с камерами. Siri, которая действительно работает. Vision Pro был экспериментом. И, судя по всему, Apple сделала соответствующие выводы.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯12🤔6❤2👍2👀1
На WWDC26 компания Apple анонсировала новые возможности для продвижения приложений. Теперь разработчики могут использовать хэдеры и другие креативные ассеты в поисковой выдаче, на странице приложения и в In-App Events. И недавно Apple выпустила подробные гайдлайны с примерами и шаблонами.
Новые ассеты:
В iOS 27 и iPadOS 27 появились новые визуальные элементы для App Store:
Все ассеты хранятся в новой библиотеке Asset Library. Их можно загружать независимо от обновления приложения.
Общие правила для всех ассетов:
Apple сформулировала несколько ключевых принципов.
Форматы и рекомендации:
Для статичных изображений Apple рекомендует использовать актуальный дизайн и четкий фокус. Текст должен быть коротким и дополнять визуал, а не дублировать его. Все элементы должны быть читаемы на разных устройствах - ключевые объекты лучше размещать в центре.
Для видео важно выбрать сильный постер. Видео должно начинаться с главной ценности приложения. Монтаж не должен быть слишком быстрым - пользователь должен успевать понять, что происходит. Видео зациклены, так что финал должен плавно переходить в начало.
Звук по умолчанию выключен. Поэтому визуал должен работать без звука. Если звук есть - это должно быть фоновое дополнение, а не способ передачи информации.
Что важно для хэдера:
Хэдер задает тон всей странице. Это первое, что видит пользователь. Apple рекомендует фокусироваться на одной идее. Не стоит перегружать визуал - это размывает впечатление.
Хэдер должен быть понятен человеку, который впервые видит приложение. Визуал должен быть цепляющим, но не перегруженным.
Можно использовать универсальный креатив для хэдера и поиска - это повышает узнаваемость бренда.
Как не совершить ошибку:
Apple прямо запрещает несколько вещей. Нельзя использовать логотипы или отсылки к другим платформам. Нельзя писать про цены и скидки. Нельзя ставить значки «Editor's Choice», «App of the Day» - они уже отображаются системой автоматически.
Важно помнить про возрастной рейтинг. Даже если приложение 17+, ассеты в App Store должны соответствовать 4+. Никакого оружия, направленного на зрителя, крови, откровенных сцен и запрещенных тем.
Новые креативные ассеты в App Store - это гибкий инструмент для продвижения. Хэдеры, поисковые креативы и ассеты для событий дают больше контроля над визуалом. Apple выпустила четкие гайдлайны, чтобы разработчики не тратили время на догадки.
Главное: помнить про ограничения. Не использовать цены, логотипы других платформ, контент для взрослых. И не перегружать визуал. Хороший хэдер - это одна идея, ясная с первого взгляда. И шаблоны помогут реализовать ее быстрее.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15❤6👀2👍1🙏1
В Xcode 27 Beta 5 появился headless MCP сервер. Теперь можно запускать Xcode Tools без открытия самого Xcode. Агент может создавать проекты, собирать их, рендерить превью и управлять симулятором. Все через командную строку.
Что изменилось:
Раньше MCP сервер в Xcode работал только пока была открыта IDE. Как только вы закрывали Xcode - инструменты прекращали работу.
В Xcode 27 Beta 5 добавили команду xcrun mcp-server. Она запускает тот же сервер, но без графического интерфейса. В сочетании с экспортируемыми навыками Apple это позволяет агентам работать с проектом полностью автономно.
Включение headless режима:
sudo xcrun mcp-server enable
xcrun mcp-server start
После этого сервер работает в фоне. Статус можно проверить командой:
xcrun mcp-server status
Что нужно для работы:
Два компонента должны быть в репозитории.
{
"mcpServers": {
"xcode": {
"type": "stdio",
"command": "xcrun",
"args": ["mcpbridge"],
"env": {
"DEVELOPER_DIR": "/Applications/Xcode-beta.app/Contents/Developer"
}
}
}
}SKILL.md с инструкциями для агента: как писать SwiftUI, как работать с симулятором, как использовать новые API.xcrun agent skills export --output-dir .claude/skills
После экспорта агент автоматически подхватывает навыки из папки .claude/skills.
Как работает разрешение:
Первый раз, когда агент пытается открыть проект, появляется системный запрос. Он идет от headless-сервиса, а не от Claude. Нужно подтвердить доступ к папке с проектом.
Разрешение можно дать на 24 часа или навсегда. Если нужно пропустить все запросы - есть флаг --unsafe-always-allow-all-agents. Но это не рекомендуется применять для прода.
Что может делать агент без Xcode UI:
После настройки агент может:
Headless MCP сервер в Xcode 27 Beta 5 - это шаг к автономной работе ИИ-агентов с проектами. Агенты могут создавать, собирать, тестировать и запускать приложения без участия человека в UI.
Навыки Apple дают агенту контекст: как писать код, как взаимодействовать с симулятором, как использовать последние API. Это превращает Xcode из IDE в платформу для агентской разработки.
Пока это бета. API может меняться. Но направление ясно: Apple готовит Xcode для эры, когда код будет писать не человек, а агент. А человек будет только задавать направление и проверять результат.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥5❤2🙏1 1
Forwarded from Flutter & Dart | Мобильный трудоголик
В Dart 3.13 появилась фича, которую ждали годами - primary constructors. Теперь класс с полями и конструктором можно объявить в одну строку. Но путь к этому решению был долгим. Команда Dart потратила много времени на обсуждение деталей и принятие компромиссов. Боб Нюстром написал большой разбор о том, через что пришлось пройти. Давайте разберем самые важные моменты из данного разбора.
Почему синтаксический сахар важен:
Primary constructors не добавляют в язык новых возможностей. Все, что можно сделать через них, уже можно было написать старым способом. Это чистый синтаксический сахар.
Вопрос в том, зачем он нужен. Синтаксический сахар оправдан в нескольких случаях.
Зачем нужен primary constructors:
Primary constructors решают конкретную проблему: объявление класса с конструктором, который просто сохраняет параметры в поля.
Без primary constructors код выглядит так:
class Point {
final int x;
final int y;
Point(int x, int y) : x = x, y = y;
}С использованием initializing formals:
class Point {
final int x;
final int y;
Point(this.x, this.y);
}Но разработчики хотели еще короче. Чтобы можно было просто написать так:
class Point(final int x, final int y);
Основная проблема:
Главная сложность: синтаксический клиф. Это когда ты начинаешь с простого синтаксиса, а потом хочешь добавить маленькое изменение, но оно не вписывается, и ты вынужден переписывать все.
Например, у класса есть primary constructor с кучей параметров. Потом нужно добавить логирование в конструктор. Если primary constructor не поддерживает тело, придется переписать все обратно на старый синтаксис.
Чтобы избежать этого, в Dart добавили блоки this { ... } внутри класса. Они позволяют добавить тело или инициализатор для primary constructor без переписывания всего.
class FormatterOptions(
final int indent = 0,
final int pageWidth = 80,
) {
this {
log.write('Created options.');
}
}
Новый синтаксис конструкторов:
Еще одно изменение касается объявления конструкторов. Раньше нужно было повторять имя класса:
class LongClassName {
LongClassName(); // безымянный
LongClassName.create(); // именованный
}Теперь можно использовать ключевое слово new:
class LongClassName {
new(); // безымянный
new create(); // именованный
}Для фабричных конструкторов:
class AnotherLongClass {
factory () { ... } // фабричный
factory create() { ... } // именованный фабричный
}Это короче, особенно для длинных имен классов. И решает проблему с typedef и расширениями, где имя класса не всегда доступно.
Primary constructors в Dart 3.13 - это не просто очередной синтаксический сахар. Это результат долгого размышления о том, как сделать язык удобнее и проще.
Команда языка учла опыт других языков, добавила защиту от синтаксических клифов и изменила объявление конструкторов на более простое. В итоге код стал короче, , а язык чуть более приятным для повседневной работы.
Это не последнее изменение. Язык продолжает развиваться. Но primary constructors - хороший пример того, как дизайн языка может быть одновременно эволюционным и продуманным.
Подписаться на канал:
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍7🔥2🙏1🤝1
С 14 по 18 сентября пройдет новый сезон Podlodka iOS Crew. В этот раз в центре внимания авторов конференции то, как AI меняет iOS-разработку.
Что ждёт участников:
• Стратегия внедрения терминальных ИИ-агентов и MCP-интеграции в ежедневную iOS-разработку
• AI как экзокостюм мобильного разработчика: harness, skills, CLI, orchestration, validation и evals
• Знания о том, как запускать локальные модели на Apple Silicon
• Готовые скрипты, которые можно забрать в свой проект: шаблон рабочего пространства агента, примеры скиллов и MCP, пайплайн от Jira-задачи до Merge Request.
И это ещё не всё! Подробности о сезоне смотрите на сайте, и там же есть билеты по early-bird цене.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11🗿8👍3🤔1🙏1👀1