Você está precisando entender como funciona e como responder aos eventos do ciclo de vida do seu aplicativo? Bom, então já está num bom caminho. Estarei mostrando duas formas no qual você vai poder ter esse controle. A escolha de qual implementar vai depender da aquele que melhor resolveria o problema da sua aplicação. Más antes de mostrar essas duas formas, acho importante entender como funciona o ciclo de vida do watchOS, no qual veremos em seguida.
Ciclo de vida do watchOS
Estado | State | Descrição |
---|---|---|
Não esta em execução | Not running | O aplicativo watchOS não está em execução. O usuário não iniciou o aplicativo watchOS ou o sistema suspendeu e depois limpou o aplicativo. |
Inativo | Inactive | O aplicativo watchOS está sendo executado em primeiro plano, mas não está recebendo ações de controles ou gestos; no entanto, ele pode estar executando outro código. Um aplicativo recém-lançado geralmente permanece nesse estado por um brevemente momento enquanto faz a transição para o estado ativo. Um aplicativo ativo que faz a transição para esse estado deve se silenciar e se preparar para a transição ao segundo plano. |
Ativo | Active | O aplicativo watchOS está sendo executado em primeiro plano e recebendo ações de controles e gestos. Este é o modo normal para aplicativos em execução na tela. |
Segundo Plano | Background | O sistema deu ao aplicativo watchOS uma pequena quantidade de tempo de execução em segundo plano. O sistema fornece tempo de execução em segundo plano aos aplicativos ao executar uma sessão em segundo plano, executar tarefas em segundo plano e antes de suspender o aplicativo. |
Suspendido | Suspended | O aplicativo está na memória, mas não está executando o código. O sistema suspende aplicativos que estão em segundo plano e não têm tarefas pendentes para serem concluídas. |
1ª forma usando WKExtensionDelegate do WatchKit
WKExtensionDelegate
Serve para responder aos eventos do ciclo de vida do seu aplicativo, como a ativação e desativação do seu aplicativo. Você também pode implementar métodos delegados para responder a tarefas em segundo plano, intenções de Siri, sessões de treino ou atividade de Handoff de outros dispositivos. Mas para nós, estamos mais interessados nos métodos de ciclo de vida.
Como implementar
Para utilizar WKExtensionDelegate
corretamente primeiro precisamos criar uma classe nova que conforma com NSObject
, WKExtensionDelegate
e ObservableObject
import WatchKit
class ExtensionDelegate: NSObject, WKExtensionDelegate, ObservableObject {
}
E depois implementamos os métodos que vão responder aos eventos de ciclo de vida do nosso aplicativo.
import WatchKit
class ExtensionDelegate: NSObject, WKExtensionDelegate, ObservableObject {
func applicationDidFinishLaunching() {
print("Application did finish launching 🤟")
}
func applicationWillEnterForeground() {
print("Application will enter foreground 😉")
}
func applicationDidBecomeActive() {
print("Application did become active 🥳")
}
func applicationWillResignActive() {
print("Application will resign active (About to deactive app)😉")
}
func applicationDidEnterBackground() {
print("Application did enter Background 👻")
}
}
Em seguida, use o wrapper de propriedade WKExtensionDelegateAdaptor
dentro da declaração do aplicativo para informar ao SwiftUI sobre o tipo de delegado
@main
struct MyApp: App {
@WKExtensionDelegateAdaptor private var extensionDelegate: ExtensionDelegate
@SceneBuilder var body: some Scene {
WindowGroup {
NavigationView {
ContentView()
}
}
}
}
Se o seu delegado de extensão estiver em conformidade com o protocolo ObservableObject
, como no exemplo acima, o SwiftUI colocará o delegado que ele cria no Environment
. Você pode acessar o delegado de qualquer cena ou visualização em sua extensão usando o wrapper de propriedade EnvironmentObject
:
@EnvironmentObject private var extensionDelegate: MyExtensionDelegate
Isso permite que você use o prefixo de dólar 💵 ($) para obter uma associação às propriedades @Published
que você declara no delegado.
Mas em que ordem são chamados esses métodos?
Na figura:
- Transição A: Quando o app muda de não está em execução para o estado inativo ou segundo plano, **o sistema vai chamar o método do delegate
applicationDidFinishLaunching()
. - Transição B: Quando o app faz a transição para o estado ativo, o sistema chama o método
applicationDidBecomeActive()
e quando faz a transição para o inativo ele chama oapplicationWillResignActive()
- Transição C: Ao fazer a transição entre os estados em segundo plano e inativo, o sistema chama o método
applicationWillEnterForeground()
ouapplicationDidEnterBackground()
.
Essa explicação foi dada pela a própria documentação da apple, más pra mim foi um pouco confuso entender de primeira. Então para explicar melhor, vamos imaginar numa situação onde o app não está em execução, e o usuário decide abrir ele e logo em seguida fecha ele. o métodos seriam chamados na seguinte ordem respetivamente:
Abrindo o app:
applicationDidFinishLaunching()
applicationWillEnterForeground()
applicationDidBecomeActive()
Fechando o app:
applicationWillResignActive()
applicationDidEnterBackground()
2ª usando ScenePhase do SwiftUI
Outra forma de determinar o estado do ciclo de vida é usando o valor scenePhase
no Environment
no qual é possível observar se a sena está ativa, inativa ou em segundo plano.
@Environment(\.scenePhase) private var scenePhase
Para observar a mudança do estado é simplesmente utilizar o método onChange(of:perform:)
como mostra no exemplo em seguida:
@main
struct MyApp: App {
@Environment(\.scenePhase) private var scenePhase
var body: some Scene {
WindowGroup {
MyRootView()
}
.onChange(of: scenePhase) { phase in
if phase == .background {
// Executar limpeza quando todas as cenas dentro do
// MyApp forem para segundo plano.
}
}
}
}
Bibliografia
https://developer.apple.com/documentation/watchkit/wkextensiondelegate
https://developer.apple.com/documentation/swiftui/wkextensiondelegateadaptor
https://developer.apple.com/documentation/swiftui/scenephase