-
Novidades do Swift
Confira as atualizações do Swift. Vamos apresentar as melhorias no fluxo de trabalho que aumentam a sua produtividade, além de APIs de biblioteca novas e modernizadas para tarefas essenciais de programação. Mostraremos exemplos de adoção do Swift em camadas do ecossistema de software. Por fim, vamos explorar novos recursos da linguagem que tornam a programação de concorrência mais acessível e possibilitam alcançar o desempenho máximo, quando necessário.
Capítulos
- 0:00 - Introdução
- 0:48 - Atualizações da swiftlang
- 3:06 - Fluxo de trabalho de desenvolvimento: escrever código
- 4:40 - Fluxo de trabalho de desenvolvimento: compilar
- 7:36 - Fluxo de trabalho de desenvolvimento: depurar
- 9:14 - Bibliotecas: Subprocess
- 10:45 - Bibliotecas: Foundation
- 12:31 - Bibliotecas: Observation
- 14:13 - Bibliotecas: Testing
- 16:08 - Swift em toda a arquitetura: Embedded Swift
- 18:00 - Swift em toda a arquitetura: segurança
- 19:37 - Swift em toda a arquitetura: servidor
- 23:23 - Swift em toda a arquitetura: plataformas
- 26:11 - Evolução da linguagem: desempenho
- 30:28 - Evolução da linguagem: concorrência
- 37:15 - Conclusão
Recursos
Vídeos relacionados
WWDC25
- Adote os recursos de concorrência do Swift
- Codificação guiada: aprimore um app usando a concorrência do Swift
- Combine C, C++ e Swift com segurança
- Conheça o framework Containerization
- Explore a interoperabilidade entre Swift e Java
- Melhore o uso da memória e o desempenho com o Swift
WWDC24
-
Buscar neste vídeo...
-
-
9:44 - Subprocess: Call `run` with string
import Subprocess let result = try await run( .name("pwd") ) -
10:04 - Subprocess: Call `run` with file path
import Subprocess let swiftPath = FilePath("/usr/bin/swift") let result = try await run( .path(swiftPath), arguments: ["--version"] ) -
10:05 - Subprocess: Accessing standard output
import Subprocess let swiftPath = FilePath("/usr/bin/swift") let result = try await run( .path(swiftPath), arguments: ["--version"] ) let swiftVersion = result.standardOutput -
10:51 - NotificationCenter: Dynamic types
import UIKit @MainActor class KeyboardObserver { func registerObserver(screen: UIScreen) { let center = NotificationCenter.default let token = center.addObserver( forName: UIResponder.keyboardWillShowNotification, object: screen, queue: .main ) { notification in guard let userInfo = notification.userInfo else { return } let startFrame = userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as? CGRect let endFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect guard let startFrame, let endFrame else { return } self.keyboardWillShow(startFrame: startFrame, endFrame: endFrame) } } func keyboardWillShow(startFrame: CGRect, endFrame: CGRect) {} } -
11:34 - NotificationCenter: Concrete types
import UIKit @MainActor class KeyboardObserver { func registerObserver(screen: UIScreen) { let center = NotificationCenter.default let token = center.addObserver( of: screen, for: .keyboardWillShow ) { keyboardState in let startFrame = keyboardState.startFrame let endFrame = keyboardState.endFrame self.keyboardWillShow(startFrame: startFrame, endFrame: endFrame) } } func keyboardWillShow(startFrame: CGRect, endFrame: CGRect) {} } -
12:01 - NotificationCenter: Conformances
extension UIResponder { public struct KeyboardWillShowMessage: NotificationCenter.MainActorMessage } extension HTTPCookieStorage { public struct CookiesChangedMessage: NotificationCenter.AsyncMessage } -
12:48 - Observation: The @Observable macro
import Observation enum Item { case none case banana case star } @Observable class Player { let name: String var score: Int = 0 var item: Item = .none init(name: String) { self.name = name } } -
12:58 - Observation: The Observations type
import Observation enum Item { case none case banana case star } @Observable class Player { let name: String var score: Int = 0 var item: Item = .none init(name: String) { self.name = name } } let player = Player(name: "Holly") let values = Observations { let score = "\(player.score) points" let item = switch player.item { case .none: "no item" case .banana: "a banana" case .star: "a star" } return "\(score) and \(item)" } -
13:56 - Observation: Transactional updates
import Observation enum Item { case none case banana case star } @Observable class Player { let name: String var score: Int = 0 var item: Item = .none init(name: String) { self.name = name } } let player = Player(name: "Holly") let values = Observations { let score = "\(player.score) points" let item = switch player.item { case .none: "no item" case .banana: "a banana" case .star: "a star" } return "\(score) and \(item)" } player.score += 2 player.item = .banana -
14:05 - Observation: AsyncSequence
import Observation enum Item { case none case banana case star } @Observable class Player { let name: String var score: Int = 0 var item: Item = .none init(name: String) { self.name = name } } let player = Player(name: "Holly") let values = Observations { let score = "\(player.score) points" let item = switch player.item { case .none: "no item" case .banana: "a banana" case .star: "a star" } return "\(score) and \(item)" } player.score += 2 player.item = .banana for await value in values { print(value) } -
14:17 - Swift Testing
import Testing import Foundation import EvolutionMetadataModel @Test func validateProposalID() async throws { let (data, _) = try await URLSession.shared.data(from: evolutionJSONMetadataURL) let jsonDecoder = JSONDecoder() let metadata = try jsonDecoder.decode(EvolutionMetadata.self, from: data) for proposal in metadata.proposals { #expect(proposal.id.starts(with: "SE")) } } -
14:54 - Swift Testing: Attachments
import Testing import Foundation import EvolutionMetadataModel @Test func validateProposalID() async throws { let (data, _) = try await URLSession.shared.data(from: evolutionJSONMetadataURL) Attachment.record(data, named: "evolution-metadata.json") let jsonDecoder = JSONDecoder() let metadata = try jsonDecoder.decode(EvolutionMetadata.self, from: data) for proposal in metadata.proposals { #expect(proposal.id.starts(with: "SE")) } } -
15:23 - Exit Tests: Preconditions
extension Proposal { public var number: Int { let components = id.split(separator: "-") precondition( components.count == 2 && components[1].allSatisfy(\.isNumber), "Invalid proposal ID format \(id); expected SE-<Number>" ) return Int(components[1])! } } -
15:34 - Exit Tests: processExitsWith argument
import Testing import EvolutionMetadataModel @Test func invalidProposalPrefix() async throws { await #expect(processExitsWith: .failure) { let proposal = Proposal(id: "SE-NNNN") _ = proposal.number } } -
31:06 - Concurrency: Async function error message
class PhotoProcessor { func extractSticker(data: Data, with id: String?) async -> Sticker? { } } @MainActor final class StickerModel { let photoProcessor = PhotoProcessor() func extractSticker(_ item: PhotosPickerItem) async throws -> Sticker? { guard let data = try await item.loadTransferable(type: Data.self) else { return nil } return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier) } } -
32:06 - Concurrency: Run async functions on the caller's actor
// Run async functions on the caller's actor class PhotoProcessor { func extractSticker(data: Data, with id: String?) async -> Sticker? {} } @MainActor final class StickerModel { let photoProcessor = PhotoProcessor() func extractSticker(_ item: PhotosPickerItem) async throws -> Sticker? { guard let data = try await item.loadTransferable(type: Data.self) else { return nil } return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier) } } -
32:36 - Concurrency: Conformance error
protocol Exportable { func export() } extension StickerModel: Exportable { // error: Conformance of 'StickerModel' to protocol 'Exportable' crosses into main actor-isolated code and can cause data races func export() { photoProcessor.exportAsPNG() } } -
33:04 - Concurrency: Isolated conformances
// Isolated conformances protocol Exportable { func export() } extension StickerModel: @MainActor Exportable { func export() { photoProcessor.exportAsPNG() } } -
33:20 - Concurrency: Isolated conformance use
// Isolated conformances @MainActor struct ImageExporter { var items: [any Exportable] mutating func add(_ item: StickerModel) { items.append(item) } func exportAll() { for item in items { item.export() } } } -
33:31 - Concurrency: Isolated conformance error
// Isolated conformances nonisolated struct ImageExporter { var items: [any Exportable] mutating func add(_ item: StickerModel) { items.append(item) // error: Main actor-isolated conformance of 'StickerModel' to 'Exportable' cannot be used in nonisolated context } func exportAll() { for item in items { item.export() } } } -
33:51 - Concurrency: Unsafe static variable
final class StickerLibrary { static let shared: StickerLibrary = .init() // error: Static property 'shared' is not concurrency-safe because non-'Sendable' type 'StickerLibrary' may have shared mutable state } -
34:01 - Concurrency: Protecting static variables
final class StickerLibrary { @MainActor static let shared: StickerLibrary = .init() } -
34:05 - Concurrency: Protecting classes
@MainActor final class StickerLibrary { static let shared: StickerLibrary = .init() } -
34:15 - Concurrency: A single-threaded program
@MainActor final class StickerLibrary { static let shared: StickerLibrary = .init() } @MainActor final class StickerModel { let photoProcessor: PhotoProcessor var selection: [PhotosPickerItem] } extension StickerModel: @MainActor Exportable { func export() { photoProcessor.exportAsPNG() } } -
34:22 - Concurrency: Mode to infer main actor by default
// Mode to infer main actor by default final class StickerLibrary { static let shared: StickerLibrary = .init() } final class StickerModel { let photoProcessor: PhotoProcessor var selection: [PhotosPickerItem] } extension StickerModel: Exportable { func export() { photoProcessor.exportAsPNG() } } -
35:06 - Concurrency: Explicitly offloading async work
// Explicitly offloading async work class PhotoProcessor { var cachedStickers: [String: Sticker] func extractSticker(data: Data, with id: String) async -> Sticker { if let sticker = cachedStickers[id] { return sticker } let sticker = await Self.extractSubject(from: data) cachedStickers[id] = sticker return sticker } @concurrent static func extractSubject(from data: Data) async -> Sticker {} }
-
-
- 0:00 - Introdução
O que há de novo no Swift 6.2. Os destaques incluem: melhorias no fluxo de trabalho, novas APIs de biblioteca, maior adoção em toda a pilha de software e aprimoramentos nos recursos de concorrência para um código mais produtivo.
- 0:48 - Atualizações da swiftlang
A organização swiftlang no GitHub cresceu abrangendo mais de 50 projetos, incluindo o compilador Swift, o sistema de compilação do Xcode, o Swift Build e o site do Swift.org. O Swift Build, de código aberto, aceita o processo de compilação para os sistemas operacionais da Apple e é adotado pelo Swift Package Manager. Um novo gerenciador de versões, swiftly, criado para Linux, agora aceita o macOS e simplifica o gerenciamento da cadeia de ferramentas do Swift. A página inicial reformulada do Swift.org também ajuda a explorar diferentes áreas.
- 3:06 - Fluxo de trabalho de desenvolvimento: escrever código
A versão mais recente do Swift aprimora os fluxos de trabalho em todas as plataformas, com melhorias específicas para os usuários da extensão Swift do VS Code, incluindo a verificação oficial e distribuição da extensão pelo Swift.org. Há indexação em segundo plano, conclusão de código aprimorado, depuração simplificada com suporte automático ao LLDB, além de um novo painel de projeto e pré-visualizações ao vivo do DocC.
- 4:40 - Fluxo de trabalho de desenvolvimento: compilar
O Swift 6.2 apresenta várias melhorias para aumentar sua produtividade. Os tempos de compilação limpa para projetos que usam APIs baseadas em macros foram melhorados eliminando a necessidade de compilar a biblioteca swift-syntax. Essa otimização, com suporte do Swift PM e do Xcode, pode reduzir os tempos de compilação em minutos. Esta versão também aprimora a documentação de diagnósticos do compilador, oferecendo explicações mais detalhadas sobre avisos e erros comuns, facilitando o entendimento e a resolução. Você tem maior controle sobre os avisos do compilador, pois é possível especificar quais avisos devem ser tratados como erros, um recurso viabilizado pelo feedback da comunidade.
- 7:36 - Fluxo de trabalho de desenvolvimento: depurar
A depuração também foi aprimorada no Swift 6.2 para código assíncrono, com melhorias na funcionalidade do LLDB, nomeação de tarefas e visibilidade em perfis do Instruments. Apresenta tempos de resposta do depurador mais rápidos com módulos explícitos ativados por padrão no Xcode 26.
- 9:14 - Bibliotecas: Subprocess
Esta versão inclui o novo pacote Subprocess, que permite iniciar e gerenciar subprocessos diretamente no código Swift. O pacote oferece controle detalhado sobre a execução de processos, permitindo especificar o caminho do executável. Quando o subprocesso termina, você pode verificar o status de saída, a saída padrão e outras informações sobre a execução do processo. A versão 0.1 já está disponível e pronta para feedback.
- 10:45 - Bibliotecas: Foundation
O Foundation Workgroup melhorou o desenvolvimento de apps iOS com tipos concretos para nomes e cargas de notificação, simplificando o código e aumentando a segurança de threads para notificações framework e personalizadas. Você também pode adicionar tipos de notificação concretos em suas próprias notificações.
- 12:31 - Bibliotecas: Observation
A Biblioteca Observation no Swift usa o padrão observer para rastrear mudanças de estado em um gráfico de objetos. A macro 'Observable' permite o rastreamento de observações. O Swift 6.2 apresenta o tipo 'Observations', que permite criar um 'AsyncSequence' para transmitir mudanças de estado com base em uma fechamento que calcula um valor a partir de propriedades observáveis. As atualizações são transacionais, garantindo estado consistente, e podem ser iteradas usando um loop for-await.
- 14:13 - Bibliotecas: Testing
Com o Swift Testing, uma biblioteca multiplataforma, você pode escrever e organizar testes usando macros. Swift 6.2 aprimora esse recurso com anexos personalizados para melhor diagnóstico de falhas, especialmente em ambientes remotos, e testes de saída para validar código que termina sob condições específicas. Esses recursos aceitam o teste de código Swift portátil, além do código do app.
- 16:08 - Swift em toda a arquitetura: Embedded Swift
O Swift 6.2 aprimora o Embedded Swift, permitindo escrever código para dispositivos incorporados, servidores e componentes de segurança. Agora inclui APIs completas para strings, tipos 'any' do Swift para protocolos restritos a classes e novas APIs como 'InlineArray' e 'Span' para trabalhar com regiões de memória. A Apple utiliza o Embedded Swift em alguns softwares de mais baixo nível do iPhone, e a comunidade criou exemplos disponíveis no repositório swift-embedded-examples no GitHub.
- 18:00 - Swift em toda a arquitetura: segurança
O Swift 6.2 apresenta o modo strict-memory-safety, um recurso que exige confirmação explícita do uso de APIs não seguras, auxiliando na identificação de trechos de código críticos para a segurança. A Apple está implementando esse modo no WebKit e no app Mensagens para lidar com entradas não confiáveis.
- 19:37 - Swift em toda a arquitetura: servidor
O Swift é usado no ecossistema de servidores, em especial na Apple, onde viabiliza serviços back-end que processam milhões de solicitações por segundo. Um exemplo é um serviço de alerta de senhas, antes em Java, que obteve um aumento de 40% na taxa de transferência e uma redução de 50% nos requisitos de hardware após ser reescrito em Swift. Outras empresas, como a Cultured Code, também se beneficiaram ao adotar o Swift. O back-end do Things Cloud, reimplementado em Swift, teve uma redução de 3 vezes nos custos de computação e uma melhoria de 400% no tempo médio de resposta. O ecossistema de pacotes do Swift, a interoperabilidade com C, Objective-C e C++, e novos projetos de código aberto como swift-java e uma biblioteca de conteinerização permitem criar back-ends de servidor eficientes, além de integrar o Swift com bases de código existentes, especialmente em Java.
- 23:23 - Swift em toda a arquitetura: plataformas
O Swift 6.2 oferece suporte oficial ao FreeBSD e WebAssembly (Wasm), permitindo criar apps cliente e servidor para navegadores e outros ambientes de execução. O suporte ao Wasm, que começou como um projeto da comunidade, permite compilar código Swift e executá-lo no navegador, como demonstrado por um app de renderização 3D que usa WebGPU e JavaScriptKit. A segurança, a facilidade de uso e o desempenho do Swift o tornam uma escolha ideal em todas as camadas da pilha de software.
- 26:11 - Evolução da linguagem: desempenho
A nova versão também apresenta dois novos tipos, 'InlineArray' e 'Span', para melhorar o desempenho de código crítico. ‘InlineArray’ é uma matriz de tamanho fixo que armazena os elementos, eliminando a necessidade de alocação no heap. Isso melhora o desempenho em trechos críticos de execução, e permite otimizações adicionais, como a eliminação da verificação de limites. O sistema especifica o tamanho de um 'InlineArray' como parte do tipo e pode inferi-lo a partir de literais de matriz. ‘Span’ oferece acesso rápido e direto à memória contígua sem comprometer a segurança de memória. Permite que funções operem sobre o armazenamento subjacente de vários tipos de contêineres, como Array e InlineArray, de modo seguro e eficiente. ‘Span’ usa verificações em compilação para garantir segurança de memória, evitando problemas típicos de ponteiros.
- 30:28 - Evolução da linguagem: concorrência
A concorrência é um desafio na programação por causa do risco de condições de corrida quando várias tarefas acessam a mesma memória. O Swift 6 incluiu segurança contra corrida de dados, mas resultava em erros do compilador, pois a linguagem delegava trabalho para o plano de fundo, mesmo que não fosse necessário executar o código em paralelo. O Swift 6.2 resolve esse problema mudando a filosofia padrão: o código permanece de thread única, até que você inclua concorrência. Esta recurso garante que o código mais natural seja seguro contra corrida de dados. A linguagem permite que funções assíncronas não vinculadas a um ator específico continuem no mesmo ator de origem da chamada, eliminando a corrida de dados. A versão traz conformidades isoladas, permitindo que tipos do ator principal implementem protocolos com proteção do compilador ao estado do ator. E existe um modo opcional para inferir o ator principal por padrão, reduzindo a necessidade de anotações de concorrência em código de thread única. Quando há necessidade de concorrência para otimização de desempenho, como descarregar tarefas intensivas de CPU para o segundo plano, o Swift 6.2 fornece mecanismos seguros. O atributo concurrent garante que funções específicas sejam executadas no pool de threads concorrentes, liberando o ator atual para realizar tarefas simultaneamente. Essas mudanças atuam em conjunto para tornar a concorrência mais acessível e fácil de implementar em projetos Swift.
- 37:15 - Conclusão
O feedback levou às melhorias na concorrência do Swift, tornando-a mais fácil de usar. A comunidade é convidada a participar dos fóruns em Swift.org para colaborar no desenvolvimento de linguagens e ecossistemas, compartilhar projetos e acompanhar as novidades.