Mudanças no iOS 9 e Swift 2.0

Posted by rlecheta on janeiro 18, 2016
iOS, Livros

Olá pessoal

Este post visa esclarecer algumas coisas que mudaram no Xcode 7 e Swift 2.0.

O objetivo é ajudar os leitores do meu livro de iOS 3a edição que foi feito para iOS 8, Xcode 6 e Swift 1.1, na época.

Com a atualização do iOS 9 e Swift 2, a Apple mudou algumas coisas na sintaxe da linguagem e na assinatura de alguns métodos. Este post visa explicar alguns destes problemas, espero que ajude 🙂

Para deixar claro:

  • livro iphone 3 edição: iOS 8, Xcode 6 e Swift 1.1
  • lirvo iphone 4 edição (quando for lançado): iOS 9, Xcode 7 e Swift 2

Vamos ser rápidos, então bora pro código:

1) Wizard de migração

Se você abrir um projeto no Xcode que utiliza Swift 1, verá este wizard de migração. Recomendo clicar em Convert e ver o resultado. A função print() é uma das mudanças simples que você pode automatizar com este wizard.

Screen Shot 2016-01-10 at 9.04.13 PM

2) Sobrescrevendo o construtor.

A notação a seguir para sobrescrever o construtor:

override init() { … }

Mudou para (não precisa colocar a palavra override):

init() { … }

O construtor que recebe NSCode utiliza a sintaxe init? (failable initializer)

init?(coder aDecoder: NSCoder)

Portanto, caso for sobrescrevê-lo, não esqueça de colocar a ?:

required init?(coder aDecoder: NSCoder) {  super.init(coder: aDecoder) }

3) Função print() virou println().

Essa é simples, é só alterar no código e boa.

4) as, as! e as?

No swift 1.0 somente existia a palavra chave as para fazer cast. Mas no Swift 2.0 foram criadas mais algumas opções.

·       as: utilizado para fazer upcasting (cast para o tipo superior);

·       as?: faz o cast (downcasting) e retorna um tipo opcional ?, portanto você deve utilizar esta maneira se possui alguma dúvida do tipo do objeto. Se o objeto não é do tipo correto é retornado nil.

·       as!: faz o cast (downcasting) quando você tem certeza que é o tipo correto, e já faz o unwrapping da variável. Mas tome cuidado, pois se não for o tipo correto o aplicativo vai travar (crash);

Exemplo de código que mostra o cast com as!:

Screen Shot 2016-01-10 at 4.13.49 PMNeste código, altere a sintaxe do cast de as! para as? para ver a diferença. O compilador vai acusar erro ao utilizar a variável c pois ela é do tipo opcional. Neste caso teria que inicializá-la ou utilizar a sintaxe c!.nome. Ou ainda, se preferir a sintaxe if let como você aprendeu no livro.

Screen Shot 2016-01-10 at 4.13.58 PM

5) var vs let

Você já sabe que var é uma variável e let uma constante. No Xcode 7, o compilador mostra um warning caso você utilize var em uma variável que nunca é alterada, pois nestes casos é recomendado usar let.

Um exemplo deste warning, é a figura abaixo:

Variable ‘url’ was never mutated; consider changing to ‘let’ constant

Screen Shot 2016-01-10 at 11.39.26 AMPara corrigir, troque por let. @Dica, faça isso pelo assistente de código.

Screen Shot 2016-01-10 at 11.39.34 AM

6) Mudança na assinatura dos métodos de vários protocolos.

No cap 8 sobre WebView implementamos logo no início alguns métodos do protocolo UIWebViewDelegate.

A Apple já mudou algumas vezes a assinatura dos métodos. Antes não tinha o ! antes dos parâmetros, depois colocaram o ! e agora resolveram tirar de novo. Mas o compilador te ajuda nestes casos e ele avisa do erro.

Screen Shot 2016-01-10 at 11.32.24 AM

Tirando o ! do parâmetro UIWebView resolve o problema. O mesmo acontece com outros protocolos, como o UITableViewDegate, etc.

Screen Shot 2016-01-10 at 11.32.39 AM

7) HTTP vs HTTPs

A partir do iOS 9, requisições HTTP (mesmo com WebView) são bloqueadas pois não são seguras. A Apple recomenda o uso de HTTPS.

No app dos Carros que mostro no livro, o WebView pode falhar e mostrar o seguinte erro:

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app’s Info.plist file.

Para solucionar este problema no iOS 9, abra o arquivo Info.plist e adicione o item App Transport Security Settings. Dentro deste item adicione um sub-item chamado Allow Arbitrary Loads com o valor YES.

Feito isso a conexão HTTP será permitida e o exemplo com WebView que mostrei no app dos carros vai funcionar. Lembrando que isso é necessário para iOS >=9 .

Screen Shot 2016-01-10 at 5.31.16 PM

8) Método supportedInterfaceOrientations()

Controle de telas na vertical e horizontal foi o assunto do capítulo 10. Na revisão do livro encontrei essa mudança.

Até o iOS 8 o método supportedInterfaceOrientations() utilizado para controlar a orientação (vertical/horizontal) da tela do view controller retornava um Int.

Screen Shot 2016-01-10 at 8.44.29 PM

Agora a função ficou com uma assinatura mais esperta, e retorna direto alguma das constantes da estrutura UIInterfaceOrientationMask:


Screen Shot 2016-01-10 at 8.44.18 PM

9) UILabel, a propriedade text e String vs NString

A propriedade text da classe UILabel é do tipo String.

Screen Shot 2016-01-10 at 9.23.57 PM

No capítulo 10 onde estudamos o acelerômetro, tinha um código que formatava a String utilizando o construtor de NSString.

Para o código compilar foi necessário fazer o cast para String, com a notação (as String).

Isso é preciso pois o NSString é uma classe do Obj-C e a classe String é do Swift. Mas como a classe NSString contém mais métodos que a String, muitas vezes ainda utilizamos elas para fazer algumas tarefas como essa (até você descobrir outro jeito rsrs):

Screen Shot 2016-01-10 at 9.25.20 PM

10) Projeto sem Launch Screen.

Ao revistar alguns projetos para iOS 9, me deparei com algumas telas com a nav bar e tab bar pretas assim:

Screen Shot 2016-01-10 at 9.28.49 PM

Isso acontece porque o projeto não possui um arquivo de Launch Screen. Para solucionar crie o arquivo com o wizard > iOS > User Interface > Launch Screen e associe este arquivo nas propriedades do projeto em Target.

Por mais bizarro que isso pode ser, faça isso que vai resolver :-). Veja resultado abaixo:

Screen Shot 2016-01-10 at 9.29.38 PM

11) Assinatura dos métodos do protocolo NSXMLParserDelegate

No capítulo 11 sobre XML/JSON, teve outra alteração, referente a sintaxe dos métodos do protocolo NSXMLParserDelegate.

Recomendo ver os métodos aqui:

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/NSXMLParserDelegate_Protocol/

Mas basicamente a Apple trocou de ! para ? (opcionais) alguns parâmetros. Então quando o compilador reclamar no Xcode é só trocar. Qualquer dúvida avise.

12) Obter a quantidade de elementos de um array.

No Swift 1.1 tinha a estranha função countElements(array) que agora virou array.count, algo mais comum em linguagens de programação.

Veja como ficou a sintaxe:

//Array<Carro>: array de carros…
let carros = parserXML_SAX(data)

// Swift 1
var count = countElements(carros)

// Swift 2
let count = carros.count

13) Idem com a classe String.

Já que falamos de como obter a quantidade de elementos, com a classe String também mudou.

Antes era countElements(string), depois virou count(string) e agora é string.characters.count.

Basicamente você acessa o array de caracteres dentro da classe String e obtem a quantidade por meio do array.

14) Try/Catch

Na explicação de parser de XML com DOM a classe SMXMLDocument era usada assim:

let document = SMXMLDocument(data: data, error:nil)

O 2º parâmetro era do tipo NSError, que inclusive nem usei no código rsrs. Isso era usado para obter o erro do método que faz o parser .

Mas no Swift 2 apareceu o try/catch e o tratamento de exceções, então o construtor deste método mudou e agora ele lança uma exceção. O Legal é usar a sintaxe try? que abrevia o try/cach e tenta executar o código que pode lançar uma exceção. Se funcionar ele retorna uma variável opcional, senão retorna nulo.

O código atualizado é assim:

let document = try? SMXMLDocument(data: data)
if(document == nil) {
print(“Erro ao ler os dados”);
return carros
}
// Continue usando o document aqui…

Como o retorno é uma variável opcional ‘?’, depois temos que fazer o unwrapping ou usar o document!. Para maiores detalhes veja no livro 🙂

15) Parser de JSON

Ainda no capítulo sobre XML/JSON, o jeito de fazer o parser de JSON com a classe NSJSONSerialization também mudou. Na verdade é porque novamente antes usava o NSError como parâmetro para obter o erro no parser, e agora é usado as exceções com try/catch.

Novamente gosto de usar o try?. Podemos até usar o if let para inicializar o dicionário do json.

Segue código atualizado:

// Faz a leitura do JSON, converte para dictionary
let dictOp = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
if let dict = dictOp {
// usar o dicionário para ler os dados do carro aqui…
} else {
// erro
}

16) Threads e Web Services

Neste capítulo não encontrei grandes mudanças, então é só para constar.

Tem pequenas coisas de ! e ? na assinatura do método dataTaskWithURLpara variar, mas nada que você não vai conseguir resolver.

17) Estilo do botão na nav bar.

No capítulo de web services, foi adicionado um botão “Atualizar” na navigation bar. Esse botão faz a atualização da lista de carros. No iOS9 o estilo Bordered ficou deprecated. Agora recomenda-se utilizar o estilo Plain.

let btAtualizar = UIBarButtonItem(title: “Atualizar”, style: UIBarButtonItemStyle.Plain,target: self, action: “atualizar”)

self.navigationItem.rightBarButtonItem = btAtualizar

18) Conversão de String para Int

No capítulo de persistência de dados, a classe Prefs tem uma pequena mudança.

let valorInt = valorString.toInt()

Isso mudou para:

let valorInt = Int(valorString)

19) SQLite

Na parte de SQLite teve poucas mudanças. Nada que trocar uns ! por ? e fazer cast com as! não resolva.

Se alguém tiver problemas é só me informar aqui neste post.

20) Mapas

Na parte de mapas não teve grandes mudanças.

Teve esse construtor do UIButton que mudou de:

let btPin = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIView

Para:

let btPin = UIButton(type: UIButtonType.DetailDisclosure) as UIView

No exemplo de Geocoding a assinatura do método mudou. Para auxiliar, veja trecho do código atualizado mostrado no livro.

Screen Shot 2016-01-13 at 2.00.58 PM

21) Video

No capítulo de multimídia, a classe VideoUtil teve um problema no iOS9, pois a classe MPMoviePlayerController ficou deprecated. No iOS9, A Apple recomenda usar a AVPlayerViewController.

Para ajudar o pessoal que comprou a 3ª edição, segue classe atualizada 😉

VideoUtil.swift

Como no iOS 9 utiliza-se a classe AVPlayerItem, devemos utilizar as suas constantes de notificação para monitorar os eventos do player de vídeo. No exemplo que mostro para interceptar o evento do fim do vídeo, basta trocar a constante por esta:

NSNotificationCenter.defaultCenter().addObserver(self, selector: “videoFim”,name:”AVPlayerItemDidPlayToEndTimeNotification“, object: nil)

22) Áudio

Novamente devido ao novo tratamento de exceções e o uso de try/catch, temos algumas mudanças em outras classes, pois não é mais usado aquele NSError como parâmetro.

Um exemplo desta alteração, é no exemplo que mostra como tocar e gravar músicas com a  classe AVAudioPlayer.

do {
// Inicializa o player com a URL do arquivo
self.player = try AVAudioPlayer(contentsOfURL: url)
} catch let error as NSError {
self.player = nil
print(“Error \(error)”)
return
}

23) Câmera e galeria de fotos

Na parte da câmera e tirar fotos não teve mudanças.

Mas no exemplo que mostra como acessar a galeria de fotos, os métodos do protocolo UIImagePickerControllerDelegate mudaram um pouco. Segue trecho atualizado:

// Delegate UINavigationControllerDelegate

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {

print(“didFinishPickingMediaWithInfo”)

let image = info[UIImagePickerControllerOriginalImage] as! UIImage

self.imageView.image = image

self.imagePicker.dismissViewControllerAnimated(true, completion:nil)

}

func imagePickerControllerDidCancel(picker: UIImagePickerController) {

print(“imagePickerControllerDidCancel”)

self.imagePicker.dismissViewControllerAnimated(true, completion:nil)

}

24) IPad e Popover

No iOS9 mudou a forma de mostrar Popovers.

Para facilitar, criei a classe PopoverUtil.swif.

Para usá-la é simples assim:

PopoverUtil.show(self, viewController: vc, source: view, width: 400, height: 800)

25) Tratamento de eventos de Touch

No capítulos sobre Quartz e Views customizadas, foi mostrado como tratar o evento de touch. Como a assinatura do método mudou, segue aqui o código atualizado:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

if let touch = touches.first {

// Lê a posicão do touch

let point = touch.locationInView(self)

self.x = Int(point.x)

self.y = Int(point.y)

self.setNeedsDisplay()

}

super.touchesBegan(touches , withEvent:event)

}

É isso pessoal 🙂

Espero que este post tenha ajudado os leitores do livro do meu livro de iOS 3a edição. Com estas explicações fica mais fácil migrar para o iOS 9.

 

 

Tags:

11 Comments to Mudanças no iOS 9 e Swift 2.0

  • Obrigada pelas dicas. Comprei o livro e estou estudando, mas como uso o Xcode 7.2 alguns exercícios não rodavam direito, agora entendo porquê.
    Quando sai a nova edição do livro?
    Ela terá novos capítulos?
    Abs

    • Oi Janaína, obrigado pelo feedback, que bom que as dicas ajudaram. A nova versão do livro deve sair em 1 mês. Mas não terá capítulos novos, eu apenas ajustei a sintaxe dos exemplos para o Swift 2.0.

  • Caro Ricardo Lecheta
    Comprei seu livro 3a. Edição e estou estudando iOS.
    Excelente conteúdo. Porém tenho uma dúvida que não consigo resolvê-la.
    Vc propõe que a função: … application.applicationIconBadgeNumber = 1 … coloca o número no ícone da aplicação. Mas não estou conseguindo este resultado. Como devo proceder para que isto aconteça?

  • Olá!! Parabéns pela obra!!! Sei que as mudanças estão cada vez mais rápidas em todas as linguagens de programação. Mas gostaria de saber se há alguma previsão para um lançamento do livro Swift 3. Obrigado.

    • Oi Marcus, no momento nao tenho previsao. O livro está bem completo e se ler nao terá problemas para se adaptar ao swift 3 🙂

  • Não seria interessante um livro digital, com assinatura anual, onde o mesmo estivesse sempre atualizado e com um capítulo específico com as alterações de cada versão do Swift e suas novidades? O que acha?! Faria a assinatura de olhos vendados não só do Swift como também do Android, já que conheço suas obras impressas, o seu potencial e sua didática. Um abraço!!