Um pouco de Swift

Use esta página apenas como referência, pois o foco está em Hotwire Native e Rails, não em Swift.

É imprescindível ter o XCode instalado para criar aplicações para dispositivos Apple. Esta orientação utiliza a versão 16.1. Antes de prosseguir, alguns aspectos do desenvolvimento com Swift serão destacados, sempre com foco no Hotwire Native.

Delegates

Delegates são um dos padrões de design mais importantes no iOS. Eles permitem que um objeto (o "delegado") receba e responda a eventos de outro objeto. No contexto do Hotwire Native, os delegates são usados frequentemente para gerenciar eventos da WebView e outros componentes do UIKit.

Imagine que você tem um botão que precisa informar a outro objeto quando foi clicado. Vamos criar um exemplo simples para demonstrar isso.

Exemplo:

protocol ButtonDelegate {
    func buttonWasClicked()
}

class Button {
    var delegate: ButtonDelegate?

    func click() {
        print("Botão foi clicado!")
        delegate?.buttonWasClicked() // Notifica o delegate
    }
}

class ButtonHandler: ButtonDelegate {
    func buttonWasClicked() {
        print("O delegado foi notificado: botão clicado!")
    }
}

Dessa forma, podemos fazer algo do tipo:

let button = Button()
let handler = ButtonHandler()

button.delegate = handler // Define o delegate
button.click() // Simula o clique no botão

Scenes

Scenes são responsáveis por gerenciar janelas e o ciclo de vida das telas no iOS. Com a introdução no iOS 13, elas permitem que os apps suportem multitarefa (especialmente em iPads). O SceneDelegate é o ponto onde configuramos a interface principal do app.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = ViewController()
        self.window = window
        window.makeKeyAndVisible()
    }
}

Neste ponto, o ViewController é configurado como a tela principal do aplicativo no método scene(_:willConnectTo:).

Controllers

Controllers, como o UIViewController, são a base para criar telas no iOS. Eles gerenciam o conteúdo da tela e respondem a eventos do ciclo de vida, como o momento em que a tela aparece ou desaparece.

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        print("Tela carregada!")
    }
}

Aqui, o método viewDidLoad é chamado quando a tela é carregada pela primeira vez, e configuramos o fundo da tela como branco.

Classes

Classes são tipos de referência, ou seja, quando você cria um objeto a partir de uma classe, ele é compartilhado entre diferentes partes do código. Classes permitem herança (uma classe pode herdar propriedades e métodos de outra).

class Person {
    var name: String

    init(name: String) {
        self.name = name
    }

    func sayHello() {
        print("Hello, \(name)!")
    }
}

// Create a Person object 
let person = Person(name: "Mary")
person.sayHello() // Output: Hello, Mary!

Structs

Structs são tipos por valor, ou seja, quando você copia uma struct, cada cópia tem seus próprios valores independentes. Elas são muito usadas em Swift para representar dados simples.

struct Person {
    var name: String

    func sayHello() {
        print("Hello, \(name)!")
    }
}

// Create an instance of the struct
var person = Person(nome: "John")
person.sayHello() // Output: Hello, John!

Se você copiar a struct e alterar a cópia, o original não será alterado:

var anotherPerson = person
anotherPerson.name = "Ana"

print(person.name)         // Output: John
print(anotherPerson.name)  // Output: Ana

Diferenças entre Classes e Structs

Aspecto Classe Struct
Tipo Referência Valor
Copiabilidade Compartilha o mesmo objeto Cada cópia é independente
Herança Suporta herança Não suporta herança
Usos Comuns Objetos complexos com estado mutável Dados simples e imutáveis

Extensions

Extensions permitem adicionar novas funcionalidades a classes, structs, enums ou protocolos já existentes, sem precisar alterar o código original. Você pode, por exemplo, estender o tipo String para adicionar novos métodos.

extension String {
    func greeting() {
        print("Hello, \(self)!")
    }
}

// Usando a extensão
let name = "Charles"
name.greeting() // Output: Hello, Charles!

Utilize extensions para organizar o código.

struct Rectangle {
    var width: Double
    var height: Double
}

// Adicionando um método com extension
extension Rectangle {
    func calculateArea() -> Double {
        return width * height
    }
}

let rectangle = Rectangle(width: 5, height: 10)
print(rectangle.calculateArea()) // Output: 50.0

Resumo sobre Classes, Structs e Extensions

Quando usar Classes, Structs e Extensions.

Variáveis

Tipos de variáveis

Podemos definir vari'áveis com as palavras chave var e let, vars são variáveis mutáveis, enquanto lets são imutáveis.

var nome = "John"
let age = 30

Inferência de tipos ou declaração explícita do tipo

var message = "Hello World"

let pi: Double = 3.14159

Variáveis opcionais

Swift utiliza opcionais (Optional) para representar variáveis que podem ou não ter um valor (ou seja, podem ser nil). Isso ajuda a evitar erros de execução por acessar valores inexistentes.

Para acessar o valor de um opcional, é necessário "extraí-lo":

var name: String? = "Emily"

if let extractedName = name {
    print("Hello, \(extractedName)!")
} else {
    print("Name is nil.")
}

Forçar a extração (!): Use apenas se tiver certeza de que o opcional possui um valor.

let name: String? = "Emily"
print(name!)

Lazy

Variáveis declaradas com lazy só são inicializadas quando são acessadas pela primeira vez. Útil para economizar memória em cálculos ou operações pesadas.

class Person {
    lazy var details: String = "Loading info..."
}

let person = Person()
print(person.details) // Inicializa e acessa a variável

Resumo

Estes são os conceitos que acredito serem interessantes saber quando estamos trabalhando com projetos iOS/Swift e Hotwire Native.

De novo, use esta parte do livro mais como referência, o nosso foco não é Swift e sim Hotwire Native e Rails.