📷 Camera App

Referências Técnicas

Documentação técnica aprofundada sobre implementação, performance e decisões de arquitetura.


📚 Documentos Disponíveis

🔄 Fluxo de Dados

Como os dados fluem através da aplicação, diagramas de sequência e ciclos de vida.

Ver documentação →

⚡ Performance

Otimizações aplicadas, benchmarks e best practices para manter a app performática.

Ver documentação →

🎯 Escolhas Técnicas

Decisões de arquitetura, trade-offs e justificativas técnicas.

Ver documentação →

🐛 Troubleshooting

Guia completo de debugging e solução de problemas comuns.

Ver documentação →

🎓 Tópicos Avançados

AVFoundation

SwiftUI + UIKit

Core Image


🧵 Threading Deep Dive

Queues Utilizadas

Queue Label Tipo Uso
Main com.apple.main-thread Serial UI updates, @Published
Session camera.session.queue Serial AVFoundation config
UserInitiated .userInitiated Concurrent Thumbnails
Utility .utility Concurrent Video export

Sincronização

// ViewModel → Controller (async)
controller.setZoomFactor(2.0, animated: true)

// Controller → ViewModel (main thread callback)
DispatchQueue.main.async {
    self.isSessionRunning = true
}

// Heavy work → Main thread
DispatchQueue.global(qos: .userInitiated).async {
    let thumbnail = generateThumbnail()
    DispatchQueue.main.async {
        self.segments.append(segment)
    }
}

📊 Performance Metrics

Configuração Inicial

Operação Tempo Típico Thread
Request Permissions ~100ms Main
Configure Session ~300ms sessionQueue
Start Session ~200ms sessionQueue
Total ~600ms Mixed

Gravação

Operação Tempo Thread
Start Recording ~50ms sessionQueue
Stop Recording ~100ms sessionQueue
Generate Thumbnail ~150ms Background
Append to UI ~10ms Main

Export

Operação Tempo (30s vídeo) Thread
Create Composition ~50ms Main
Export (sem filtro) ~5s Background
Export (com filtro) ~15s Background
Save to Photos ~500ms Main

🔧 Extensibilidade

Adicionar Novo Filtro

// 1. Adicionar case no enum
enum VideoFilter: String, CaseIterable {
    case none
    case mono
    case sepia  // ← Novo
}

// 2. Implementar no applyFilter
switch filterType {
case .sepia:
    let filter = CIFilter.sepiaTone()
    filter.intensity = 0.8
    filter.inputImage = src
    output = filter.outputImage
// ...
}

Adicionar Nova Feature de Câmera

// 1. Propriedade no ViewModel
@Published var isGridEnabled: Bool = false

// 2. Método de controle
func toggleGrid() {
    isGridEnabled.toggle()
}

// 3. UI na ContentView
if model.isGridEnabled {
    GridOverlay()
}

📈 Benchmarking

Como Medir Performance

import os.signpost

let log = OSLog(subsystem: "com.pedro.Camera", category: "Performance")

// Iniciar medição
let signpostID = OSSignpostID(log: log)
os_signpost(.begin, log: log, name: "VideoExport", signpostID: signpostID)

// Operação...
exporter.exportAsynchronously { ... }

// Terminar medição
os_signpost(.end, log: log, name: "VideoExport", signpostID: signpostID)

Ver resultados: Instruments → Points of Interest


🏗️ Padrões Arquiteturais

MVVM

Vantagens:

Trade-offs:

Delegation

Quando usar:

Alternativa: Closures para callbacks simples

Coordinator Pattern

Quando usar:


🔍 Debugging Tips

AVFoundation Issues

// Print todos os formatos disponíveis
for format in device.formats {
    print("Format: \(format)")
    print("FPS ranges: \(format.videoSupportedFrameRateRanges)")
}

// Print configuração atual
print("Active format: \(device.activeFormat)")
print("Active frame rate: \(device.activeVideoMaxFrameDuration)")
print("Zoom factor: \(device.videoZoomFactor)")

Threading Issues

// Assert main thread
dispatchPrecondition(condition: .onQueue(.main))

// Assert background thread
dispatchPrecondition(condition: .notOnQueue(.main))

// Print current thread
print("Thread: \(Thread.current)")

Memory Leaks

// Use weak self em closures
controller.configureSession { [weak self] error in
    guard let self = self else { return }
    // ...
}

// Instruments → Leaks para detectar

📚 Recursos Adicionais

Apple Documentation

WWDC Sessions


← Guias Fluxo de Dados →