-
Novidades do UIKit
Modernize seu app com as APIs mais recentes do UIKit, incluindo suporte aprimorado à barra de menus, rastreamento automático de observação, um novo método de atualização da interface de usuário e melhorias nas animações. Também vamos abordar como você pode incluir cenas do SwiftUI em seu app do UIKit e explorar os Símbolos SF, seletores de cores HDR e muito mais.
Capítulos
- 0:00 - Introdução
- 0:59 - Novo sistema de design
- 2:29 - Contêiners e adaptabilidade
- 3:21 - A barra de menus
- 9:58 - Melhorias na arquitetura
- 10:21 - Rastreamento automático de observação
- 12:33 - Novo método de atualização de interface de usuário
- 15:45 - Melhorias nas animações
- 17:45 - Atualizações de cenas
- 18:55 - Compatibilidade com cores HDR
- 20:38 - Notificações do Swift
- 21:20 - Migrar para um ciclo de vida baseado em cenas
- 22:40 - Compatibilidade com o OpenURL para URLs de arquivos
- 23:17 - Símbolos SF 7
- 25:13 - Próximas etapas
Recursos
Vídeos relacionados
WWDC25
- Aprimore o design do seu app para iPad
- Conheça o novo sistema de design
- Crie um app do UIKit com o novo design
- Deixe o seu app do UIKit mais flexível
- Novidades do app Símbolos SF 7
WWDC24
WWDC23
WWDC21
-
Buscar neste vídeo...
-
-
4:56 - Main menu system configuration
// Main menu system configuration var config = UIMainMenuSystem.Configuration() // Declare support for default commands, like printing config.printingPreference = .included // Opt out of default commands, like inspector config.inspectorPreference = .removed // Configure the Find commands to be a single "Search" element config.findingConfiguration.style = .search -
5:39 - Main menu system build configuration
// Main menu system configuration // Have the main menu system build using this configuration, and make custom additions. // Call this early, e.g. in application(_:didFinishLaunchingWithOptions:), and call it once UIMainMenuSystem.shared.setBuildConfiguration(config) { builder in builder.insertElements([...], afterCommand: #selector(copy(_:))) let deleteKeyCommand = UIKeyCommand(...) builder.replace(command: #selector(delete(_:)), withElements: [deleteKeyCommand]) } -
7:01 - Keyboard shortcut repeatability
// Keyboard shortcut repeatability let keyCommand = UIKeyCommand(...) keyCommand.repeatBehavior = .nonRepeatable -
7:43 - Focus-based deferred menu elements (App Delegate)
// Focus-based deferred menu elements extension UIDeferredMenuElement.Identifier { static let browserHistory: Self = .init(rawValue: "com.example.deferred-element.history") } // Create a focus-based deferred element that will display browser history let historyDeferredElement = UIDeferredMenuElement.usingFocus( identifier: .browserHistory, shouldCacheItems: false ) // Insert it into the app’s custom History menu when building the main menu builder.insertElements([historyDeferredElement], atEndOfMenu: .history) -
8:06 - Focus-based deferred menu elements (View Controller)
// Focus-based deferred menu elements class BrowserViewController: UIViewController { // ... override func provider( for deferredElement: UIDeferredMenuElement ) -> UIDeferredMenuElement.Provider? { if deferredElement.identifier == .browserHistory { return UIDeferredMenuElement.Provider { completion in let browserHistoryMenuElements = profile.browserHistoryElements() completion(browserHistoryMenuElements) } } return nil } } -
10:54 - Using an Observable object and automatic observation tracking
// Using an Observable object and automatic observation tracking @Observable class UnreadMessagesModel { var showStatus: Bool var statusText: String } class MessageListViewController: UIViewController { var unreadMessagesModel: UnreadMessagesModel var statusLabel: UILabel override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() statusLabel.alpha = unreadMessagesModel.showStatus ? 1.0 : 0.0 statusLabel.text = unreadMessagesModel.statusText } } -
11:48 - Configuring a UICollectionView cell with automatic observation tracking
// Configuring a UICollectionView cell with automatic observation tracking @Observable class ListItemModel { var icon: UIImage var title: String var subtitle: String } func collectionView( _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath ) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) let listItemModel = listItemModel(for: indexPath) cell.configurationUpdateHandler = { cell, state in var content = UIListContentConfiguration.subtitleCell() content.image = listItemModel.icon content.text = listItemModel.title content.secondaryText = listItemModel.subtitle cell.contentConfiguration = content } return cell } -
13:27 - Using automatic observation tracking and updateProperties()
// Using automatic observation tracking and updateProperties() @Observable class BadgeModel { var badgeCount: Int? } class MyViewController: UIViewController { var model: BadgeModel let folderButton: UIBarButtonItem override func updateProperties() { super.updateProperties() if let badgeCount = model.badgeCount { folderButton.badge = .count(badgeCount) } else { folderButton.badge = nil } } } -
16:57 - Using the flushUpdates animation option to automatically animate updates
// Using the flushUpdates animation option to automatically animate updates // Automatically animate changes with Observable objects UIView.animate(options: .flushUpdates) { model.badgeColor = .red } -
17:23 - Automatically animate changes to Auto Layout constraints with flushUpdates
// Automatically animate changes to Auto Layout constraints UIView.animate(options: .flushUpdates) { // Change the constant of a NSLayoutConstraint topSpacingConstraint.constant = 20 // Change which constraints are active leadingEdgeConstraint.isActive = false trailingEdgeConstraint.isActive = true } -
18:07 - Setting up a UIHostingSceneDelegate
// Setting up a UIHostingSceneDelegate import UIKit import SwiftUI class ZenGardenSceneDelegate: UIResponder, UIHostingSceneDelegate { static var rootScene: some Scene { WindowGroup(id: "zengarden") { ZenGardenView() } #if os(visionOS) ImmersiveSpace(id: "zengardenspace") { ZenGardenSpace() } .immersionStyle(selection: .constant(.full), in: .mixed, .progressive, .full) #endif } } -
18:28 - Using a UIHostingSceneDelegate
// Using a UIHostingSceneDelegate func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { let configuration = UISceneConfiguration(name: "Zen Garden Scene", sessionRole: connectingSceneSession.role) configuration.delegateClass = ZenGardenSceneDelegate.self return configuration } -
18:41 - Requesting a scene
// Requesting a scene func openZenGardenSpace() { let request = UISceneSessionActivationRequest( hostingDelegateClass: ZenGardenSceneDelegate.self, id: “zengardenspace")! UIApplication.shared.activateSceneSession(for: request) } -
19:18 - HDR color support
// Create an HDR red relative to a 2.5x peak white let hdrRed = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0, linearExposure: 2.5) -
19:50 - HDR color picking
// Support picking HDR colors relative to a // maximum peak white of 2x colorPickerController.maximumLinearExposure = 2.0 -
20:06 - Mixing SDR and HDR content
// Mixing SDR and HDR content registerForTraitChanges([UITraitHDRHeadroomUsageLimit.self]) { traitEnvironment, previousTraitCollection in let currentHeadroomLimit = traitEnvironment.traitCollection.hdrHeadroomUsageLimit // Update HDR usage based on currentHeadroomLimit’s value } -
20:54 - Adopting Swift notifications
// Adopting Swift notifications override func viewDidLoad() { super.viewDidLoad() let keyboardObserver = NotificationCenter.default.addObserver( of: UIScreen.self for: .keyboardWillShow ) { message in UIView.animate( withDuration: message.animationDuration, delay: 0, options: .flushUpdates ) { // Use message.endFrame to animate the layout of views with the keyboard let keyboardOverlap = view.bounds.maxY - message.endFrame.minY bottomConstraint.constant = keyboardOverlap } } } -
24:26 - Using a symbol content transition to automatically animate symbol updates
// Using a symbol content transition to automatically animate symbol updates var configuration = UIButton.Configuration.plain() configuration.symbolContentTransition = UISymbolContentTransition(.replace)
-
-
- 0:00 - Introdução
Saiba mais sobre os aprimoramentos do UIKit no iOS, iPadOS, tvOS, visionOS e Mac Catalyst. Este vídeo aborda o novo sistema de design, contêineres e adaptabilidade, APIs para a barra de menus no iPadOS e Mac Catalyst, avanços arquitetônicos centrais e melhorias gerais no framework.
- 0:59 - Novo sistema de design
O novo sistema de design apresenta o Liquid Glass: um material dinâmico e translúcido que atualiza os componentes padrão do UIKit e melhora as transições de navegação. O UIKit também possui uma nova API para levar o Liquid Glass para a sua interface de usuário personalizada.
- 2:29 - Contêiners e adaptabilidade
O iOS 26 aprimora o "UISplitViewController" com inspetores para exibição detalhada de conteúdo e redimensionamento dinâmico de colunas.
- 3:21 - A barra de menus
O iOS 26 aprimora a barra de menus do iPad, que agora pode ser acessada com um gesto de deslizar a partir da parte superior da tela, oferecendo acesso rápido às funcionalidades do app sem a necessidade de um teclado físico. A barra de menus sempre deve exibir todos os comandos do app, mesmo aqueles que estão desativados ou que não possuem atalhos de teclado. Personalize a barra de menus usando a nova API para configuração do menu principal e implemente menus dinâmicos com base na visualização em foco. Foram introduzidas ações padrão como "Fechar" e "Novo da Área de Transferência". As ações para alinhamento de texto, alternância da barra lateral e alternância do inspetor agora estão expostas para personalização. Garanta que as ações estejam disponíveis no seu app sem depender da barra de menus.
- 9:58 - Melhorias na arquitetura
O UIKit continua evoluindo com novos recursos para padrões modernos, melhores práticas e maior interoperabilidade com o SwiftUI.
- 10:21 - Rastreamento automático de observação
O UIKit agora rastreia automaticamente objetos Observable referenciados em métodos de atualização como "layoutSubviews", eliminando a necessidade de chamadas manuais para "setNeedsLayout". Esse recurso está ativado por padrão no iOS 26 e você pode implantá-lo retroativamente até o iOS 18 com a chave "UIObservationTrackingEnabled" no Info.plist. As alterações nas propriedades do modelo Observable que atualizam elementos da interface do usuário acionam automaticamente a invalidação da visualização e as novas execuções dos métodos de atualização relevantes, mantendo a interface do usuário sincronizada sem código adicional.
- 12:33 - Novo método de atualização de interface de usuário
O UIKit apresenta um novo método, "updateProperties", disponível em "UIView" e "UIViewController". Esse método é executado de modo independente antes de "layoutSubviews" e permite preencher conteúdo, aplicar estilos e configurar comportamentos com mais eficiência. "updateProperties" rastreia automaticamente modelos Observables e pode ser acionado manualmente chamando "setNeedsUpdateProperties". Usando esse método, você pode evitar passagens de layout desnecessárias, melhorando o desempenho do seu app.
- 15:45 - Melhorias nas animações
No iOS 26, o UIKit introduz "flushUpdates", uma opção de animação que aplica automaticamente atualizações pendentes antes e depois das animações, eliminando a necessidade de chamadas manuais a "layoutIfNeeded". Isso simplifica o código, reduz erros e funciona com objetos Observable e alterações automáticas de restrição de layout.
- 17:45 - Atualizações de cenas
Agora você pode integrar cenas do SwiftUI aos apps do UIKit usando o novo protocolo "UIHostingSceneDelegate". Crie apps que se adaptem a diferentes dispositivos, como um app de meditação com um jardim zen 2D no iPhone e iPad e uma experiência imersiva no visionOS, solicitando programaticamente uma cena específica do SwiftUI.
- 18:55 - Compatibilidade com cores HDR
No iOS 26, o UIKit também aprimora a renderização HDR além de imagens para incluir cores. Crie cores HDR usando "UIColor" e ative a seleção de cores HDR nos seletores de cores. Use o novo traço "UITraitHDRHeadroomUsage" para saber quando o conteúdo HDR deve fazer fallback para SDR.
- 20:38 - Notificações do Swift
O UIKit representa cada notificação como um tipo dedicado "NotificationCenter.Message" no iOS 26, fornecendo notificações fortemente tipadas para facilitar o tratamento de eventos, como visto no exemplo de ajuste de layout quando o teclado aparece.
- 21:20 - Migrar para um ciclo de vida baseado em cenas
'UIScene' substitui 'UIApplication' como o padrão para o desenvolvimento de app, tornando os apps mais portáteis e flexíveis. Você deve adotar o ciclo de vida "UIScene", pois os métodos legados foram descontinuados e, a partir da versão posterior ao iOS 26, os apps que não tiverem adotado o ciclo de vida da cena não serão abertos.
- 22:40 - Compatibilidade com o OpenURL para URLs de arquivos
O método "openURL" agora permite que os apps encaminhem documentos não nativos para visualizadores padrão ou usem controladores de pré-visualização rápida caso não exista um padrão.
- 23:17 - Símbolos SF 7
O SF Symbols 7 apresenta novas funcionalidades de desenho, incluindo os efeitos "Desenhar Desativado" e "Desenhar Ativado", modo de desenho variável para desenhar valores arbitrários ao longo de um caminho e animações especiais com transições de Substituição Mágica. O UIKit agora possui uma API para fácil adoção dessas transições em "UIButton", e os símbolos podem ser coloridos com gradientes gerados automaticamente.
- 25:13 - Próximas etapas
Para atualizar seu app para o iOS 26, compile com o novo SDK, refine as interfaces de usuário para corresponderem ao novo design, utilize contêineres padrão e as novas APIs de menu, e adote o método "updateProperties" e o rastreamento de observação para melhorar o desempenho.