Escrito por Reinder de Vries, em 10 de janeiro de 2019 em Desenvolvimento de aplicativos, o Swift

Um singleton é uma classe do que exatamente uma instância existe, que pode ser acessado globalmente. Como você cria um singleton no Swift? E por que você deveria ou não deveria?

neste tutorial, vamos mergulhar em singletons em Swift. Você aprende o que é o padrão de design singleton e por que é útil. Discutiremos a sintaxe para criar singletons no Swift. E vamos entrar em casos de uso bons e ruins para singletons.

pronto? Vamos.

  1. O Que É Um Singleton?
  2. Codificando Um Singleton Em Swift
  3. Quando Usar Singletons
  4. Leitura Adicional

O Que É Um Singleton?

um singleton é uma classe da qual existe apenas uma instância. Alguns exemplos:

  • Uma empresa tem somente um CEO
  • Uma API de classe tem apenas uma série de fila de solicitação de
  • Um sistema operacional tem apenas um sistema de arquivos
  • Um corpo do sistema solar gira em torno de um ponto gravitacional
  • Um aplicativo que faz e/S tem apenas um padrão FileManager
  • Um avião tem apenas um convés de vôo

O segundo atributo de um singleton é que ele tem um ponto global de acesso. Você pode acessar um singleton, por exemplo. funções de chamada nele, de qualquer lugar no código do seu aplicativo.

então, para resumir:

  1. um singleton é uma classe que tem apenas uma instância
  2. pode ser acessada globalmente, ou seja, em qualquer lugar do seu código

no desenvolvimento prático do iOS, você usa singletons com frequência. Classes típicas como NotificationCenter, UserDefaults, SKPaymentQueue e FileManager tem shared ou default propriedades que são singletons.

em outros momentos, você pode querer criar um singleton você mesmo. Um bom caso de uso é uma classe API que expõe a instância singleton por meio de sua propriedade shared. Você usa API.shared.makeAPICall() para acessar a API por meio de uma única instância unificada. Isso permite que você, por exemplo, gerencie chamadas de API em série.

antes de discutirmos quando os singletons são melhor usados (e quando não), vamos descobrir como codificar um singleton no Swift.

seja contratado como desenvolvedor iOS

Aprenda a criar aplicativos iOS 14 com Swift 5

Inscreva-se no meu curso de desenvolvimento iOS e aprenda como iniciar sua carreira como desenvolvedor profissional de iOS.

codificando um Singleton em Swift

esta é a melhor maneira de criar um singleton em Swift:

class API{ static let shared = API() private init() { // Set up API instance }}

e veja como você usa o singleton:

API.shared.doSomething()

estamos criando uma classe API que tem uma propriedade estática chamada shared. Essa propriedade não pode ser alterada uma vez definida, porque é uma constante e é declarada estaticamente.

isso significa que podemos acessar a propriedade sharedpor meio da classe API. Isso geralmente é chamado de propriedade de classe. Compare isso com uma propriedade de instância normal, que só pode ser acessada por meio de uma instância de uma classe.

o que é interessante é que a propriedade shared inicializa uma instância de API dentro da classe API. Estamos criando um objeto API que pode ser acessado por meio da classe API. Mas há mais …

o inicializador de classe init() está marcado com private. Esta palavra-chave private garante que a classe API só possa ser inicializada dentro da classe API.

em outras palavras, você não pode criar uma instância de API fora da classe API! Isso garante que o objeto API que criamos seja a única instância em nosso código. Afinal, você não pode criar mais disso.

e agora garantimos que a classe API está em conformidade com os dois atributos de um singleton:

  1. Graças à propriedade estática shared, o API instância pode ser acessado globalmente
  2. Graças a private init(), o API classe não pode ser inicializado fora do API classe

Isso tudo pode parecer um pouco abstrato para você, então vamos expandir o exemplo anterior, com um pouco mais de código prático. Aqui está o que:

a classe API é principalmente a mesma. Ainda é um singleton e ainda usa esses bits de código static let shared = API() e private init().

aqui está o que mudou:

  • a classe API agora tem uma propriedade isRequestPending. É aqui que o perigo começa… veja como o booleano isRequestPending garante que apenas uma solicitação de API possa ser feita de cada vez? (Observe que isRequestPending é uma propriedade de instância.)
  • a classe API também tem uma função makeAPIRequest(). Imagine que podemos usar essa função para recuperar alguns dados de uma API de webservice, como a do Twitter. na função, você pode ver que uma solicitação só pode ser feita quando nenhuma outra solicitação estiver pendente no momento.
  • a classe API também tem uma função onReturnAPIRequest(). Esta função é invocada quando a solicitação da API retorna, ou seja, os dados on-line foram baixados para o aplicativo. O booleano isRequestPending é definido como false novamente e os dados da solicitação são processados.

e veja como podemos usar o singleton API em qualquer lugar em nosso código:

API.shared.makeAPIRequest()

há outra coisa que precisamos discutir. A classe API agora gerencia algo chamado state. Você pode ver “Estado” como um sentimento: você é feliz ou está triste, ou está com raiva, e assim por diante. Você pode mudar de um estado para o outro.

a classe API pode alternar entre dois estados:

  • Um estado em que isRequestPending é false
  • Um estado em que isRequestPending é true

Como você aprenderá na próxima seção, estado e singletons pode causar todos os tipos de estragos no seu código. Gerenciar o estado mal é a maior razão para o uso indevido de singleton.

quando usar Singletons

quando você usa singletons? O livro Design Patterns: Elements of Reusable Object-Oriented Software by the Gang of Four tem o seguinte a dizer. Use o padrão singleton quando:

  • deve haver exatamente uma instância de uma classe, e deve ser acessível a clientes de um conhecido ponto de acesso
  • quando a única instância deve ser extensível por subclasses, e os clientes devem ser capazes de usar um longo instância, sem modificar o código

isso é complicado, mas o que ferve para baixo é:

  • Usar um singleton quando o código não requer mais do que uma instância de uma classe (por exemplo, o CEO da empresa)
  • E quando ele deve ser acessível a partir de qualquer lugar no seu código (i.e., o sistema de arquivos)

outro caso de uso é a subclassificação. Uma variável global em seu código não pode ser facilmente subclassificada, então é por isso que você usa uma classe singleton. Além disso, os singletons podem ser testados por unidade usando injeção de dependência. Você substitui a instância API por uma instância APIMock e obtém a capacidade de acionar chamadas de API de teste sem fazer as solicitações de rede reais.

e quando você não usa singletons? Para responder a essa pergunta, teremos que voltar ao princípio do Estado que discutimos anteriormente.

uma armadilha comum para Desenvolvedores iOS iniciantes é gerenciar o estado e suas dependências mal. Imagine que você está construindo um aplicativo que usa a classe API com a qual trabalhamos anteriormente.

toda vez que você expande a classe API, você usa cada vez mais propriedades, como:

  • Um userID propriedade que mantém o controle do usuário em sessão, uma vez que o login() chamada de API foi feita
  • Um tweets propriedade com o Twitter de dados, uma vez que o getTweets() chamada foi feita
  • Um spinner propriedade UIActivityIndicatorView que você adicionar a um controlador de visualização quando uma solicitação começou

Em primeiro lugar, isso faz muito sentido. Afinal, a classe API pode ser acessada em qualquer lugar do seu código. Portanto, no controlador Tweet View, você pode usar a matriz API.shared.tweets e, no controlador de Configurações, pode usar userID para informar rapidamente à API cujas configurações devem ser alteradas.

infelizmente, seu estado está agora em todo o lugar. A classe API tem dependências para um monte de classes que não estão relacionadas à responsabilidade única da classe API. Seu código se tornou uma tigela de espaguete, tudo emaranhado. O código pode funcionar bem, mas é impossível manter e estender.

vejamos um exemplo. O onReturnAPIRequest() função é definida anteriormente está à beira de se tornar fortemente acoplado…

Aqui está o que nós estamos considerando:

  • O onReturnAPIRequest() é chamado quando uma API webservice solicitação retorna, i.e. quando vem os dados para o aplicativo. Esses dados precisam ir a algum lugar – um controlador de visualização de Tweet, por exemplo. Como você passa os dados do API para o controlador de visualização?
  • uma escolha óbvia é apenas criar uma referência ao viewController na classe API. Quando os dados entram, você pode codificar algo como viewController.tweets = tweetsData. Esta é uma arquitetura ruim, infelizmente, porque agora o API e o controlador de visualização estão fortemente acoplados. É impossível (ou difícil) testar a unidade e provavelmente criará problemas ao estender qualquer classe.
  • é melhor escolher um mecanismo que não combine firmemente as duas classes. Uma opção seria passar um encerramento para onReturnAPIRequest(), que é executado quando a solicitação retorna. Esse fechamento pode então conter código para lidar com os dados recebidos. Outra opção seria usar NotificationCenter para passar os dados para o controlador de visualização ou usar uma classe Database para lidar com os dados.

o padrão de design singleton ganhou alguma controvérsia, simplesmente porque é fácil usar mal. Ao usar singletons, esteja atento ao estado e às dependências. Só porque é fácil ter acesso global ao Estado, isso não significa que seja uma boa ideia.

seja contratado como desenvolvedor iOS

Aprenda a criar aplicativos iOS 14 com Swift 5

Inscreva-se no meu curso de desenvolvimento iOS e aprenda como iniciar sua carreira como desenvolvedor profissional de iOS.

Leitura Adicional

e isso é tudo o que há para isso! Conhecer singletons é um objetivo que vale a pena, especialmente se você estiver interessado em arquitetura de aplicativos e design de sistemas.

Deixe uma resposta

O seu endereço de email não será publicado.