Ao atualizar o código-fonte de um aplicativo iOS para a última versão do Swift, Xcode 7 e iOS 9 me deparei com um erro em todas as requisições para o backend, via HTTPS.

2015-10-14 18:52:35.499 App[11330:6290469] CFNetwork SSLHandshake failed (-9824)
2015-10-14 18:52:35.500 App[11330:6290469] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
Error:An SSL error has occurred and a secure connection to the server cannot be made.

Investigando o problema à fundo, reparei que a Apple anunciou no WWDC 2015 o ATS (App Transport Security), que basicamente prega boas práticas em conexões seguras entre aplicativos e o backend. O ATS não está presente só no iOS 9 mas também no OS X El Captain, e ele prega que, principalmente, o host utilize o TLSv1.2.

Como mexer no host/backend não era uma opção, vi que existem algumas opções para configurar o ATS para verificar uma versão específica do TLS ou até mesmo desativar a verificação, o que não é uma boa prática. Para configurar é necessário acrescentar algumas linhas no arquivo Info.plist. No exemplo abaixo o ATS irá permitir requisições para uma determinada URL, incluindo também subdomínios, definindo a versão 1.1 como a versão mínima do TLS.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>suaurl.com</key>
        <dict>
            <!-- Permite subdomínios -->
            <key>NSIncludesSubdomains</key>
            <true />
            <!-- Define a versão do TLS -->
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.1</string>
        </dict>
    </dict>
</dict>

Se por um acaso for estritamente necessário “burlar” o ATS, então o trecho abaixo pode ser utilizado, ele irá permitir requisições sem a verificação do ATS.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key><true/>
</dict>

Referências

Confira mais informações sobre o ATS, outras opções de configuração e as novidades do iOS 9 nos links abaixo.