Dispatch_once em Swift: principais erros e alternativas corretas

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Dispatch_once em Swift: por que isso é um erro e como escrever um singleton correto

\n\n

Se você já se perguntou "Como fazer um singleton em Swift usando dispatch_once?" — você não está sozinho. No Stack Overflow, essa pergunta acumulou milhares de visualizações, e no código de muitos projetos ainda existem construções estranhas tentando emular a antiga abordagem do Objective-C. Mas a boa notícia é que em Swift existe uma solução muito mais elegante e segura. A má notícia: muitos desenvolvedores continuam cometendo os mesmos erros ao tentar transferir hábitos do Objective-C para o Swift.

\n\n

Neste artigo, analisaremos os 5 principais erros ao usar dispatch_once em Swift, mostraremos como evitá-los e forneceremos um modelo pronto para um singleton correto. Vamos lá!

\n\n

O que é dispatch_once e por que ele não é necessário em Swift?

\n\n

dispatch_once é uma função do Grand Central Dispatch (GCD) que garante que um bloco de código seja executado exatamente uma vez durante toda a vida útil do aplicativo. Em Objective-C, essa era a maneira padrão de criar singletons thread-safe:

\n\n
+ (instancetype)sharedInstance {\n    static MyClass *sharedInstance = nil;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        sharedInstance = [[MyClass alloc] init];\n    });\n    return sharedInstance;\n}
\n\n

No entanto, em Swift, a partir da versão 1.0, o dispatch_once não é suportado para uso em código do usuário. Sim, você pode importar o Dispatch e tentar chamá-lo, mas o compilador não permitirá. Por quê? Porque o Swift oferece recursos integrados que tornam o dispatch_once desnecessário.

\n\n

Os 5 principais erros ao usar dispatch_once em Swift

\n\n

Erro 1: Tentar chamar dispatch_once diretamente

\n\n

O erro mais comum é tentar escrever algo como:

\n\n
class MySingleton {\n    static var shared: MySingleton = {\n        let instance = MySingleton()\n        // configuração\n        return instance\n    }()\n    \n    private init() {}\n}
\n\n

À primeira vista, isso funciona. Mas isso não é dispatch_once. É apenas uma variável global que é inicializada de forma lazy na primeira vez que é acessada. O Swift garante thread-safety para essas propriedades estáticas, mas não é a mesma coisa que dispatch_once.

\n\n

Por que isso é ruim? Porque você perde o controle sobre o momento da inicialização. Se o seu singleton depende de recursos externos (como banco de dados ou rede), eles podem ainda não estar prontos.

\n\n

Erro 2: Usar dispatch_once através de um wrapper em Objective-C

\n\n

Alguns desenvolvedores criam uma ponte em Objective-C para chamar dispatch_once a partir do Swift:

\n\n
// Arquivo Objective-C\n@interface OnceHelper : NSObject\n+ (void)performOnce:(void(^)(void))block;\n@end\n\n@implementation OnceHelper\nstatic dispatch_once_t onceToken;\n+ (void)performOnce:(void(^)(void))block {\n    dispatch_once(&onceToken, block);\n}\n@end
\n\n

Depois, em Swift:

\n\n
class MySingleton {\n    static var shared: MySingleton = {\n        var instance: MySingleton!\n        OnceHelper.performOnce {\n            instance = MySingleton()\n        }\n        return instance\n    }()\n}
\n\n

Qual é o problema? Primeiro, é uma gambiarra. Segundo, dispatch_once_t é uma variável global, e se você esquecer de redefinir o token (por exemplo, durante testes), o singleton não será recriado. Terceiro, a Apple recomenda explicitamente não usar dispatch_once em Swift.

\n\n

Erro 3: Esquecer a thread-safety

\n\n

Alguns escrevem o singleton assim:

\n\n
class MySingleton {\n    static var shared: MySingleton?\n    \n    private init() {}\n    \n    static func getInstance() -> MySingleton {\n        if shared == nil {\n            shared = MySingleton()\n        }\n        return shared!\n    }\n}<                

Blogs

Book Recommendations