Files
LCEssentials/LCEssentials_DOCUMENTATION.md
Daniel Arantes Loverde 27b6b45ee9 Complete documentation
2025-10-23 13:26:03 -03:00

62 KiB

📚 LCEssentials - Documentação Completa

Loverde Co. Essentials Swift Scripts - Biblioteca completa de utilitários Swift para iOS, macOS, tvOS e watchOS

📋 Índice


🔧 Instalação

Swift Package Manager (SPM)

dependencies: [
    .package(url: "https://git.loverde.com.br/Loverde-Company-LTDA/LCEssentials", .upToNextMajor(from: "1.0.0"))
]

Xcode SPM

https://git.loverde.com.br/Loverde-Company-LTDA/LCEssentials

Import

import LCEssentials

🏗️ Classes Principais

LCEssentials - Classe Principal

LCEssentials

Classe principal com métodos utilitários gerais para desenvolvimento iOS.

Propriedades Estáticas

Declaração:

public struct LCEssentials {
    public static let DEFAULT_ERROR_DOMAIN = "LoverdeCoErrorDomain"
    public static let DEFAULT_ERROR_CODE = -99
    public static let DEFAULT_ERROR_MSG = "Error Unknow"
}

Uso:

// Verificar informações do app
let appName = LCEssentials.appDisplayName
let appVersion = LCEssentials.appVersion
let appBuild = LCEssentials.appBuild
let bundleID = LCEssentials.appBundleID

// Verificar informações do dispositivo
let isDebug = LCEssentials.isInDebuggingMode
let isTestFlight = LCEssentials.isInTestFlight
let isSimulator = LCEssentials.isRunningOnSimulator
let isPad = LCEssentials.isPad
let isPhone = LCEssentials.isPhone

// Dimensões da tela
let screenWidth = LCEssentials.screenWidth
let screenHeight = LCEssentials.screenHeight

Métodos Principais

backgroundThread

static func backgroundThread(delay: Double = 0.0, 
                           background: (@Sendable () -> Void)? = nil, 
                           completion: (@Sendable () -> Void)? = nil)

Uso:

LCEssentials.backgroundThread(delay: 0.6, background: {
    // Fazer algo em background
    print("Processando...")
}) {
    // Quando terminar, atualizar UI
    DispatchQueue.main.async {
        self.updateUI()
    }
}

delay

@discardableResult 
static func delay(milliseconds: Double,
                  queue: DispatchQueue = .main,
                  completion: @escaping () -> Void) -> DispatchWorkItem

Uso:

let task = LCEssentials.delay(milliseconds: 2000) {
    print("Executado após 2 segundos")
}
// Para cancelar: task.cancel()

debounce

static func debounce(millisecondsDelay: Int,
                     queue: DispatchQueue = .main,
                     action: @escaping (() -> Void)) -> () -> Void

Uso:

let debouncedAction = LCEssentials.debounce(millisecondsDelay: 500) {
    print("Executado apenas uma vez após 500ms de inatividade")
}

// Chamar múltiplas vezes rapidamente
debouncedAction() // Primeira chamada
debouncedAction() // Segunda chamada (cancela a primeira)
debouncedAction() // Terceira chamada (cancela a segunda)
// Apenas a última será executada após 500ms

getTopViewController

static func getTopViewController(base: UIViewController? = nil, 
                                aboveBars: Bool = true) -> UIViewController?

Uso:

if let topVC = LCEssentials.getTopViewController() {
    // Fazer algo com o view controller do topo
    topVC.present(alert, animated: true)
}

shareApp

static func shareApp(message: String = "", url: String = "")

Uso:

LCEssentials.shareApp(message: "Confira este app!", url: "https://appstore.com/app")

call

static func call(_ number: String!)

Uso:

LCEssentials.call("+5511999999999")

openSafari

static func openSafari(_ urlStr: String)

Uso:

LCEssentials.openSafari("https://loverde.com.br")

downloadFileWithCache

static func downloadFileWithCache(from url: URL, 
                                 completion: @escaping (Result<URL, Error>) -> Void)

Uso:

LCEssentials.downloadFileWithCache(from: imageURL) { result in
    switch result {
    case .success(let localURL):
        print("Arquivo baixado: \(localURL)")
    case .failure(let error):
        print("Erro: \(error)")
    }
}

cleanExpiredCache

static func cleanExpiredCache(expiration: TimeInterval = 7 * 24 * 60 * 60)

Uso:

// Limpar cache com mais de 1 semana
LCEssentials.cleanExpiredCache(expiration: 7 * 24 * 60 * 60)
API - Sistema de Requisições HTTP

API

Sistema completo para requisições HTTP com suporte a certificados, cache e retry automático.

Configuração

Declaração:

@available(iOS 13.0.0, *)
@MainActor
public struct API {
    public static let shared = API()
    public static var defaultParams: [String:Any] = [String: Any]()
    public static var persistConnectionDelay: Double = 3
}

Uso:

// Configurar parâmetros padrão
API.defaultParams = ["api_key": "sua_chave_aqui"]

// Configurar certificado cliente
let certData = Data(contentsOf: Bundle.main.url(forResource: "client", withExtension: "p12")!)
API.shared.setupCertificationRequest(certData: certData, password: "senha_do_certificado")

Método Principal

request

public func request<T: Codable>(url: String,
                               params: Any? = nil,
                               method: httpMethod,
                               headers: [String: String] = [:],
                               jsonEncoding: Bool = true,
                               debug: Bool = true,
                               timeoutInterval: TimeInterval = 30,
                               networkServiceType: URLRequest.NetworkServiceType = .default,
                               persistConnection: Bool = false) async throws -> T

Uso - GET Request:

struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

do {
    let users: [User] = try await API.shared.request(
        url: "https://api.exemplo.com/users",
        method: .get,
        headers: ["Authorization": "Bearer token_aqui"]
    )
    print("Usuários: \(users)")
} catch {
    print("Erro: \(error)")
}

Uso - POST Request:

struct LoginRequest: Codable {
    let email: String
    let password: String
}

struct LoginResponse: Codable {
    let token: String
    let user: User
}

do {
    let loginData = LoginRequest(email: "user@exemplo.com", password: "senha123")
    let response: LoginResponse = try await API.shared.request(
        url: "https://api.exemplo.com/login",
        params: loginData,
        method: .post
    )
    print("Token: \(response.token)")
} catch {
    print("Erro no login: \(error)")
}

Uso - Upload de Arquivo:

let fileURL = URL(fileURLWithPath: "/path/to/image.jpg")
let params = [
    "title": "Minha Imagem",
    "description": "Descrição da imagem",
    "file": fileURL.absoluteString
]

do {
    let response: [String: Any] = try await API.shared.request(
        url: "https://api.exemplo.com/upload",
        params: params,
        method: .post
    )
    print("Upload realizado: \(response)")
} catch {
    print("Erro no upload: \(error)")
}

Uso - Com Retry Automático:

do {
    let data: MyResponse = try await API.shared.request(
        url: "https://api.exemplo.com/data",
        method: .get,
        persistConnection: true // Habilita retry automático
    )
} catch {
    print("Erro após tentativas: \(error)")
}
LCECryptoKitManager - Gerenciador de Criptografia

LCECryptoKitManager

Gerenciador para operações de criptografia usando LCECryptoKit.

Inicialização

Declaração:

public final class LCECryptoKitManager {
    public init()
    public init(privateKey: String)
}

Uso:

// Sem chave privada
let cryptoManager = LCECryptoKitManager()

// Com chave privada
let cryptoManager = LCECryptoKitManager(privateKey: "minha_chave_privada")

Métodos

generateKey

public static func generateKey() -> String

Uso:

let newKey = LCECryptoKitManager.generateKey()
print("Nova chave gerada: \(newKey)")

encodeTP

public func encodeTP(email: String, password: String) -> String?

Uso:

if let encoded = cryptoManager.encodeTP(email: "user@exemplo.com", password: "senha123") {
    print("Dados codificados: \(encoded)")
}

decodeOTP

public func decodeOTP(_ otpHash: String) -> String?

Uso:

if let decoded = cryptoManager.decodeOTP("hash_codificado") {
    print("Dados decodificados: \(decoded)")
}

encodeOTPWithKey

public func encodeOTPWithKey(email: String, password: String) -> String?

Uso:

if let encoded = cryptoManager.encodeOTPWithKey(email: "user@exemplo.com", password: "senha123") {
    print("Dados codificados com chave: \(encoded)")
}

decodeOTPWithKey

public func decodeOTPWithKey(_ otpHash: String) -> Bool

Uso:

let isValid = cryptoManager.decodeOTPWithKey("hash_codificado")
if isValid {
    print("Hash válido!")
} else {
    print("Hash inválido!")
}
LCSingleton - Protocolo Singleton

LCSingleton

Protocolo para implementação de padrão Singleton.

Declaração:

@objc public protocol LCESingletonDelegate: AnyObject {
    @objc optional func singleton(object: Any?, withData: Any)
}

Uso:

class MySingleton: LCESingletonDelegate {
    static let shared = MySingleton()
    
    private init() {}
    
    func singleton(object: Any?, withData: Any) {
        print("Singleton chamado com dados: \(withData)")
    }
}

// Uso
MySingleton.shared.singleton(object: nil, withData: "dados_importantes")
GifHelper - Utilitários para GIFs

GifHelper

Utilitários para trabalhar com arquivos GIF animados.

UIImageView Extensions

loadGif

public func loadGif(name: String)
public func loadGif(asset: String)

Uso:

// Carregar GIF do bundle
imageView.loadGif(name: "animacao")

// Carregar GIF do asset catalog
imageView.loadGif(asset: "animacao_gif")

UIImage Extensions

gif

public class func gif(data: Data) -> UIImage?
public class func gif(url: String) -> UIImage?
public class func gif(name: String) -> UIImage?
public class func gif(asset: String) -> UIImage?

Uso:

// Criar GIF a partir de Data
if let gifData = Data(contentsOf: gifURL) {
    let gifImage = UIImage.gif(data: gifData)
    imageView.image = gifImage
}

// Criar GIF a partir de URL
if let gifImage = UIImage.gif(url: "https://exemplo.com/animacao.gif") {
    imageView.image = gifImage
}

// Criar GIF a partir do bundle
if let gifImage = UIImage.gif(name: "animacao") {
    imageView.image = gifImage
}

// Criar GIF a partir do asset catalog
if let gifImage = UIImage.gif(asset: "animacao_gif") {
    imageView.image = gifImage
}
Repositorio - Estrutura de Repositório

Repositorio

Estrutura básica para repositórios.

Declaração:

struct Repositorio {
    var text = "Hello, World!"
    private var testBin: [Int] = []
}

Uso:

var repo = Repositorio()
print(repo.text) // "Hello, World!"

🎨 Componentes UI

LCSnackBarView - Sistema de Notificações

LCSnackBarView

Sistema completo de notificações estilo SnackBar para iOS.

Inicialização

Declaração:

public final class LCSnackBarView: UIView {
    public init(style: LCSnackBarViewType = .default,
               orientation: LCSnackBarOrientation = .top,
               delegate: LCSnackBarViewDelegate? = nil)
}

Uso:

// Básico
let snackBar = LCSnackBarView()
snackBar.configure(text: "Operação realizada com sucesso!")
    .present()

// Com delegate
let snackBar = LCSnackBarView(delegate: self)
snackBar.configure(text: "Mensagem importante!")
    .present()

// Com estilo e orientação
let snackBar = LCSnackBarView(style: .rounded, orientation: .bottom)
snackBar.configure(text: "Mensagem no bottom!")
    .present()

Configuração

configure(text:)

@discardableResult
func configure(text: String) -> Self

Uso:

snackBar.configure(text: "Sua mensagem aqui")

configure(textColor:)

@discardableResult
func configure(textColor: UIColor) -> Self

Uso:

snackBar.configure(textColor: .white)

configure(textFont:alignment:)

@discardableResult
func configure(textFont: UIFont, alignment: NSTextAlignment = .center) -> Self

Uso:

snackBar.configure(textFont: .boldSystemFont(ofSize: 16), alignment: .left)

configure(backgroundColor:)

@discardableResult
func configure(backgroundColor: UIColor) -> Self

Uso:

snackBar.configure(backgroundColor: .systemGreen)

configure(exibition:)

@discardableResult
func configure(exibition timer: LCSnackBarTimer) -> Self

Uso:

snackBar.configure(exibition: .medium) // 5 segundos
snackBar.configure(exibition: .infinity) // Permanece até ser fechado manualmente

configure(imageIconBefore:withTintColor:)

@discardableResult
func configure(imageIconBefore icon: UIImageView, withTintColor: UIColor? = nil) -> Self

Uso:

let icon = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
snackBar.configure(imageIconBefore: icon, withTintColor: .white)

present(completion:)

func present(completion: (()->())? = nil)

Uso:

snackBar.present {
    print("SnackBar apresentado!")
}

Enums

LCSnackBarViewType

public enum LCSnackBarViewType {
    case `default`    // Retangular
    case rounded      // Arredondado
}

LCSnackBarOrientation

public enum LCSnackBarOrientation {
    case top          // Aparece no topo
    case bottom       // Aparece na parte inferior
}

LCSnackBarTimer

public enum LCSnackBarTimer: CGFloat {
    case infinity = 0    // Permanece até ser fechado
    case minimum = 2     // 2 segundos
    case medium = 5      // 5 segundos
    case maximum = 10    // 10 segundos
}

Delegate

LCSnackBarViewDelegate

@objc public protocol LCSnackBarViewDelegate {
    @objc optional func snackbar(didStartExibition: LCSnackBarView)
    @objc optional func snackbar(didTouchOn snackbar: LCSnackBarView)
    @objc optional func snackbar(didEndExibition: LCSnackBarView)
}

Uso:

class MyViewController: UIViewController, LCSnackBarViewDelegate {
    
    func showNotification() {
        let snackBar = LCSnackBarView(delegate: self)
        snackBar.configure(text: "Notificação importante!")
            .present()
    }
    
    func snackbar(didStartExibition: LCSnackBarView) {
        print("SnackBar começou a ser exibido")
    }
    
    func snackbar(didTouchOn snackbar: LCSnackBarView) {
        print("Usuário tocou no SnackBar")
    }
    
    func snackbar(didEndExibition: LCSnackBarView) {
        print("SnackBar foi fechado")
    }
}

Exemplo Completo

class ViewController: UIViewController, LCSnackBarViewDelegate {
    
    @IBAction func showSuccessNotification() {
        let snackBar = LCSnackBarView(style: .rounded, orientation: .top, delegate: self)
        
        let icon = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
        
        snackBar
            .configure(text: "Dados salvos com sucesso!")
            .configure(textColor: .white)
            .configure(backgroundColor: .systemGreen)
            .configure(exibition: .medium)
            .configure(imageIconBefore: icon, withTintColor: .white)
            .present()
    }
    
    @IBAction func showErrorNotification() {
        let snackBar = LCSnackBarView(style: .default, orientation: .bottom)
        
        snackBar
            .configure(text: "Erro ao salvar dados. Tente novamente.")
            .configure(textColor: .white)
            .configure(backgroundColor: .systemRed)
            .configure(exibition: .maximum)
            .present()
    }
}
ImagePickerController - Seletor de Imagens

ImagePickerController

Controlador para seleção de imagens da câmera ou biblioteca de fotos.

Inicialização

Declaração:

public class ImagePickerController: UIViewController, UINavigationControllerDelegate {
    public weak var delegate: ImagePickerControllerDelegate?
    public var isEditable: Bool = false
    public init()
}

Uso:

let imagePicker = ImagePickerController()
imagePicker.delegate = self
imagePicker.isEditable = true // Permite edição da imagem

Delegate

ImagePickerControllerDelegate

public protocol ImagePickerControllerDelegate: AnyObject {
    func imagePicker(didSelect image: UIImage?)
}

Uso:

class MyViewController: UIViewController, ImagePickerControllerDelegate {
    
    @IBAction func selectImage() {
        let imagePicker = ImagePickerController()
        imagePicker.delegate = self
        imagePicker.isEditable = true
        present(imagePicker, animated: true)
    }
    
    func imagePicker(didSelect image: UIImage?) {
        if let selectedImage = image {
            imageView.image = selectedImage
            print("Imagem selecionada: \(selectedImage.size)")
        } else {
            print("Seleção cancelada")
        }
    }
}

Método Principal

openImagePicker

public func openImagePicker()

Uso:

let imagePicker = ImagePickerController()
imagePicker.delegate = self
imagePicker.openImagePicker() // Abre automaticamente o seletor

Exemplo Completo

class ProfileViewController: UIViewController, ImagePickerControllerDelegate {
    
    @IBOutlet weak var profileImageView: UIImageView!
    
    @IBAction func changeProfileImage() {
        let imagePicker = ImagePickerController()
        imagePicker.delegate = self
        imagePicker.isEditable = true
        present(imagePicker, animated: true)
    }
    
    func imagePicker(didSelect image: UIImage?) {
        dismiss(animated: true) {
            if let selectedImage = image {
                self.profileImageView.image = selectedImage
                self.saveProfileImage(selectedImage)
            }
        }
    }
    
    private func saveProfileImage(_ image: UIImage) {
        // Implementar lógica de salvamento
        print("Imagem do perfil atualizada!")
    }
}
ImageZoomController - Visualizador de Imagens com Zoom

ImageZoomController

Controlador para visualização de imagens com zoom e pan.

Inicialização

Declaração:

public class ImageZoomController: UIViewController {
    public init(_ withImage: UIImage)
    public weak var delegate: ImageZoomControllerDelegate?
    public var minimumZoomScale: CGFloat = 1.0
    public var maximumZoomScale: CGFloat = 6.0
    public var addGestureToDismiss: Bool = true
}

Uso:

let image = UIImage(named: "minha_imagem")!
let zoomController = ImageZoomController(image)
zoomController.delegate = self
zoomController.minimumZoomScale = 0.5
zoomController.maximumZoomScale = 8.0
zoomController.addGestureToDismiss = true

Delegate

ImageZoomControllerDelegate

@objc public protocol ImageZoomControllerDelegate {
    @objc optional func imageZoomController(controller: ImageZoomController, didZoom image: UIImage?)
    @objc optional func imageZoomController(controller: ImageZoomController, didClose image: UIImage?)
}

Uso:

class MyViewController: UIViewController, ImageZoomControllerDelegate {
    
    @IBAction func showImageZoom() {
        guard let image = imageView.image else { return }
        
        let zoomController = ImageZoomController(image)
        zoomController.delegate = self
        zoomController.present()
    }
    
    func imageZoomController(controller: ImageZoomController, didZoom image: UIImage?) {
        print("Usuário fez zoom na imagem")
    }
    
    func imageZoomController(controller: ImageZoomController, didClose image: UIImage?) {
        print("Visualizador foi fechado")
    }
}

Métodos

present(completion:)

public func present(completion: (()->())? = nil)

Uso:

zoomController.present {
    print("Visualizador apresentado!")
}

dismiss(completion:)

public func dismiss(completion: (()->())? = nil)

Uso:

zoomController.dismiss {
    print("Visualizador fechado!")
}

Exemplo Completo

class GalleryViewController: UIViewController, ImageZoomControllerDelegate {
    
    @IBOutlet weak var collectionView: UICollectionView!
    var images: [UIImage] = []
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let selectedImage = images[indexPath.item]
        showImageZoom(selectedImage)
    }
    
    private func showImageZoom(_ image: UIImage) {
        let zoomController = ImageZoomController(image)
        zoomController.delegate = self
        zoomController.minimumZoomScale = 0.5
        zoomController.maximumZoomScale = 10.0
        zoomController.addGestureToDismiss = true
        zoomController.present()
    }
    
    func imageZoomController(controller: ImageZoomController, didZoom image: UIImage?) {
        // Opcional: implementar lógica quando usuário faz zoom
    }
    
    func imageZoomController(controller: ImageZoomController, didClose image: UIImage?) {
        // Opcional: implementar lógica quando visualizador é fechado
    }
}

SwiftUI

LCENavigationView - Navegação Customizada SwiftUI

LCENavigationView

Componente SwiftUI para navegação customizada com botões e títulos.

Inicialização

Declaração:

@available(iOS 15, *)
public struct LCENavigationView<Content: View>: View {
    public init(title: (any View) = Text(""),
                subTitle: (any View) = Text(""),
                @ViewBuilder content: () -> Content)
}

Uso:

LCENavigationView {
    Text("Conteúdo da tela")
}

Configuração

setTitle

public func setTitle(text: (any View) = Text(""),
                    subTitle: (any View)? = nil) -> LCENavigationView

Uso:

LCENavigationView {
    Text("Conteúdo")
}
.setTitle(text: Text("Meu Título"), subTitle: Text("Subtítulo"))

setLeftButton

public func setLeftButton(text: Text = Text(""),
                         image: (any View)? = nil,
                         action: @escaping () -> Void) -> LCENavigationView

Uso:

LCENavigationView {
    Text("Conteúdo")
}
.setLeftButton(text: Text("Voltar")) {
    print("Botão esquerdo pressionado")
}
.setLeftButton(image: Image(systemName: "arrow.left")) {
    print("Seta esquerda pressionada")
}

setRightButton

public func setRightButton(text: Text = Text(""),
                          image: (any View)? = nil,
                          action: @escaping () -> Void) -> LCENavigationView

Uso:

LCENavigationView {
    Text("Conteúdo")
}
.setRightButton(text: Text("Salvar")) {
    print("Salvar pressionado")
}
.setRightButton(image: Image(systemName: "checkmark")) {
    print("Checkmark pressionado")
}

hideNavigationView

public func hideNavigationView(_ hide: Bool) -> LCENavigationView

Uso:

LCENavigationView {
    Text("Conteúdo")
}
.hideNavigationView(true) // Esconde a barra de navegação

Exemplo Completo

struct ContentView: View {
    @State private var isEditing = false
    
    var body: some View {
        LCENavigationView {
            VStack {
                Text("Conteúdo da tela")
                    .padding()
                
                if isEditing {
                    Text("Modo de edição ativo")
                        .foregroundColor(.blue)
                }
            }
        }
        .setTitle(text: Text("Minha App"), subTitle: Text("Tela Principal"))
        .setLeftButton(image: Image(systemName: "line.horizontal.3")) {
            print("Menu pressionado")
        }
        .setRightButton(text: Text(isEditing ? "Concluir" : "Editar")) {
            isEditing.toggle()
        }
    }
}
View+Ext - Extensões SwiftUI

View+Ext

Extensões para Views SwiftUI.

getTag

Declaração:

@available(iOS 13.0, *)
extension View {
    func getTag<TagType: Hashable>() throws -> TagType
    func extractTag<TagType: Hashable>(_ closure: (() throws -> TagType) -> Void) -> Self
}

Uso:

struct MyView: View {
    var body: some View {
        Text("Hello")
            .tag("myTag")
            .extractTag { tag in
                print("Tag extraída: \(tag)")
            }
    }
}

🔗 Extensões

String - Extensões para String

String Extensions

Extensões poderosas para manipulação de strings.

Validações

isEmail

var isEmail: Bool

Uso:

let email = "user@exemplo.com"
if email.isEmail {
    print("Email válido!")
}

isCPF

var isCPF: Bool

Uso:

let cpf = "12345678901"
if cpf.isCPF {
    print("CPF válido!")
}

isValidCNPJ

var isValidCNPJ: Bool

Uso:

let cnpj = "12345678000195"
if cnpj.isValidCNPJ {
    print("CNPJ válido!")
}

Transformações

urlEncoded

var urlEncoded: String

Uso:

let text = "Hello World!"
let encoded = text.urlEncoded
print(encoded) // "Hello%20World%21"

urlDecoded

var urlDecoded: String

Uso:

let encoded = "Hello%20World%21"
let decoded = encoded.urlDecoded
print(decoded) // "Hello World!"

base64Encode

var base64Encode: String?

Uso:

let text = "Hello World!"
if let encoded = text.base64Encode {
    print("Base64: \(encoded)")
}

base64Decode

var base64Decode: String?

Uso:

let encoded = "SGVsbG8gV29ybGQh"
if let decoded = encoded.base64Decode {
    print("Decoded: \(decoded)")
}

Limpeza e Filtros

onlyNumbers

var onlyNumbers: String

Uso:

let phone = "+55 (11) 99999-9999"
let numbers = phone.onlyNumbers
print(numbers) // "5511999999999"

removeSpecialChars

var removeSpecialChars: String

Uso:

let text = "Hello@#$%World!"
let clean = text.removeSpecialChars
print(clean) // "HelloWorld"

removeHTMLTags

var removeHTMLTags: String

Uso:

let html = "<p>Hello <strong>World</strong>!</p>"
let text = html.removeHTMLTags
print(text) // "Hello World!"

removeEmoji

var removeEmoji: String

Uso:

let text = "Hello 😀 World 🌍!"
let clean = text.removeEmoji
print(clean) // "Hello  World !"

Conversões

int

var int: Int?

Uso:

let numberString = "123"
if let number = numberString.int {
    print("Número: \(number)")
}

double

var double: Double?

Uso:

let numberString = "123.45"
if let number = numberString.double {
    print("Número: \(number)")
}

bool

var bool: Bool?

Uso:

let boolString = "true"
if let value = boolString.bool {
    print("Valor: \(value)")
}

Formatação

applyMask

func applyMask(toText: String, mask: String) -> String

Uso:

let phone = "11999999999"
let masked = "".applyMask(toText: phone, mask: "(##) #####-####")
print(masked) // "(11) 99999-9999"

currencyStringToDouble

var currencyStringToDouble: Double

Uso:

let currency = "R$ 1.234,56"
let value = currency.currencyStringToDouble
print(value) // 1234.56

Data e Hora

date

func date(withCurrFormatt: String = "yyyy-MM-dd HH:mm:ss",
          localeIdentifier: String = "pt-BR",
          timeZone: TimeZone? = TimeZone.current) -> Date?

Uso:

let dateString = "2023-12-25 15:30:00"
if let date = dateString.date(withCurrFormatt: "yyyy-MM-dd HH:mm:ss") {
    print("Data: \(date)")
}

Exemplo Completo

class StringUtils {
    
    static func validateUserInput(_ input: String) -> Bool {
        // Remover caracteres especiais
        let cleanInput = input.removeSpecialChars
        
        // Verificar se não está vazio
        guard !cleanInput.isEmpty else { return false }
        
        // Verificar se contém apenas letras e espaços
        let lettersOnly = cleanInput.lettersWithWhiteSpace
        return lettersOnly == cleanInput
    }
    
    static func formatPhoneNumber(_ phone: String) -> String {
        let numbers = phone.onlyNumbers
        return "".applyMask(toText: numbers, mask: "(##) #####-####")
    }
    
    static func validateEmail(_ email: String) -> Bool {
        return email.isEmail
    }
    
    static func validateCPF(_ cpf: String) -> Bool {
        return cpf.isCPF
    }
}
Date - Extensões para Date

Date Extensions

Extensões completas para manipulação de datas.

Propriedades

year, month, day, hour, minute, second

var year: Int { get set }
var month: Int { get set }
var day: Int { get set }
var hour: Int { get set }
var minute: Int { get set }
var second: Int { get set }

Uso:

let now = Date()
print("Ano: \(now.year)")
print("Mês: \(now.month)")
print("Dia: \(now.day)")
print("Hora: \(now.hour)")
print("Minuto: \(now.minute)")
print("Segundo: \(now.second)")

// Modificar data
var tomorrow = Date()
tomorrow.day += 1
print("Amanhã: \(tomorrow)")

Verificações

isInToday, isInYesterday, isInTomorrow

var isInToday: Bool
var isInYesterday: Bool
var isInTomorrow: Bool

Uso:

let date = Date()
if date.isInToday {
    print("É hoje!")
} else if date.isInYesterday {
    print("É ontem!")
} else if date.isInTomorrow {
    print("É amanhã!")
}

isInFuture, isInPast

var isInFuture: Bool
var isInPast: Bool

Uso:

let futureDate = Date().adding(.day, value: 1)
if futureDate.isInFuture {
    print("Data futura!")
}

let pastDate = Date().adding(.day, value: -1)
if pastDate.isInPast {
    print("Data passada!")
}

Operações

adding

func adding(_ component: Calendar.Component, value: Int) -> Date

Uso:

let tomorrow = Date().adding(.day, value: 1)
let nextWeek = Date().adding(.weekOfYear, value: 1)
let nextMonth = Date().adding(.month, value: 1)
let nextYear = Date().adding(.year, value: 1)

changing

func changing(_ component: Calendar.Component, value: Int) -> Date?

Uso:

let newDate = Date().changing(.hour, value: 15) // Muda para 15:00
let newDate2 = Date().changing(.day, value: 25) // Muda para dia 25

Formatação

string

func string(withFormat format: String = "dd/MM/yyyy HH:mm") -> String

Uso:

let date = Date()
print(date.string(withFormat: "dd/MM/yyyy")) // "25/12/2023"
print(date.string(withFormat: "HH:mm")) // "15:30"
print(date.string(withFormat: "EEEE, dd 'de' MMMM 'de' yyyy")) // "Segunda-feira, 25 de dezembro de 2023"

dateString, timeString, dateTimeString

func dateString(ofStyle style: DateFormatter.Style = .medium) -> String
func timeString(ofStyle style: DateFormatter.Style = .medium) -> String
func dateTimeString(ofStyle style: DateFormatter.Style = .medium) -> String

Uso:

let date = Date()
print(date.dateString()) // "25 de dez de 2023"
print(date.timeString()) // "15:30:00"
print(date.dateTimeString()) // "25 de dez de 2023 às 15:30:00"

Nomes

dayName, monthName

func dayName(ofStyle style: DayNameStyle = .full) -> String
func monthName(ofStyle style: MonthNameStyle = .full) -> String

Uso:

let date = Date()
print(date.dayName()) // "Segunda-feira"
print(date.dayName(ofStyle: .threeLetters)) // "Seg"
print(date.monthName()) // "Dezembro"
print(date.monthName(ofStyle: .threeLetters)) // "Dez"

Comparações

secondsSince, minutesSince, hoursSince, daysSince

func secondsSince(_ date: Date) -> Double
func minutesSince(_ date: Date) -> Double
func hoursSince(_ date: Date) -> Double
func daysSince(_ date: Date) -> Double

Uso:

let startDate = Date()
// ... alguma operação ...
let endDate = Date()

let seconds = endDate.secondsSince(startDate)
let minutes = endDate.minutesSince(startDate)
let hours = endDate.hoursSince(startDate)
let days = endDate.daysSince(startDate)

print("Passaram \(seconds) segundos")
print("Passaram \(minutes) minutos")
print("Passaram \(hours) horas")
print("Passaram \(days) dias")

isBetween

func isBetween(_ startDate: Date, _ endDate: Date, includeBounds: Bool = false) -> Bool

Uso:

let startDate = Date().adding(.day, value: -7)
let endDate = Date().adding(.day, value: 7)
let checkDate = Date()

if checkDate.isBetween(startDate, endDate) {
    print("Data está no intervalo!")
}

Exemplo Completo

class DateUtils {
    
    static func formatRelativeDate(_ date: Date) -> String {
        let now = Date()
        
        if date.isInToday {
            return "Hoje às \(date.string(withFormat: "HH:mm"))"
        } else if date.isInYesterday {
            return "Ontem às \(date.string(withFormat: "HH:mm"))"
        } else if date.isInTomorrow {
            return "Amanhã às \(date.string(withFormat: "HH:mm"))"
        } else if date.isInCurrentWeek {
            return date.dayName(ofStyle: .full)
        } else {
            return date.string(withFormat: "dd/MM/yyyy")
        }
    }
    
    static func getAge(from birthDate: Date) -> Int {
        let now = Date()
        let age = now.year - birthDate.year
        return age
    }
    
    static func isWeekend(_ date: Date) -> Bool {
        return date.isInWeekend
    }
    
    static func getBusinessDaysBetween(_ startDate: Date, and endDate: Date) -> Int {
        var currentDate = startDate
        var businessDays = 0
        
        while currentDate <= endDate {
            if !currentDate.isInWeekend {
                businessDays += 1
            }
            currentDate = currentDate.adding(.day, value: 1)
        }
        
        return businessDays
    }
}
UIView - Extensões para UIView

UIView Extensions

Extensões poderosas para manipulação de views.

Propriedades

borderColor, borderWidth, cornerRadius

var borderColor: UIColor? { get set }
var borderWidth: CGFloat { get set }
var cornerRadius: CGFloat { get set }

Uso:

let view = UIView()
view.borderColor = .systemBlue
view.borderWidth = 2.0
view.cornerRadius = 8.0

screenshot

var screenshot: UIImage?

Uso:

if let screenshot = view.screenshot {
    // Usar screenshot da view
    imageView.image = screenshot
}

Constraint Helpers

setConstraintsTo

@discardableResult
func setConstraintsTo(parentView: UIView, anchorType: AnchorType, value: CGFloat, safeArea: Bool = false) -> Self

Uso:

let childView = UIView()
parentView.addSubview(childView)

// Configurar constraints
childView.setConstraintsTo(parentView, .top, 20, true) // 20pt do topo da safe area
    .setConstraints(.leading, 16)
    .setConstraints(.trailing, -16)
    .setConstraints(.bottom, -20)

setHeight, setWidth

@discardableResult
func setHeight(size: CGFloat) -> Self
@discardableResult
func setWidth(size: CGFloat) -> Self

Uso:

view.setHeight(size: 100)
    .setWidth(size: 200)

Efeitos Visuais

applyShadow

func applyShadow(color: UIColor, offSet: CGSize, radius: CGFloat, opacity: Float, shouldRasterize: Bool = true, rasterizationScaleTo: CGFloat = UIScreen.main.scale)

Uso:

view.applyShadow(color: .black, offSet: CGSize(width: 0, height: 2), radius: 4, opacity: 0.3)

insertBlurView

func insertBlurView(style: UIBlurEffect.Style, color: UIColor = .black, alpha: CGFloat = 0.9)

Uso:

view.insertBlurView(style: .dark, color: .black, alpha: 0.8)

Animações

fadeIn, fadeOut

func fadeIn(withDuration duration: TimeInterval = 1.0, withDelay delay: TimeInterval = 0, completionHandler: @escaping (Bool) -> ())
func fadeOut(withDuration duration: TimeInterval = 1.0, withDelay delay: TimeInterval = 0, completionHandler: @escaping (Bool) -> ())

Uso:

view.fadeIn(withDuration: 0.5) { finished in
    print("Fade in concluído!")
}

view.fadeOut(withDuration: 0.3) { finished in
    print("Fade out concluído!")
}

Utilitários

addSubviews

func addSubviews(_ subviews: [UIView], translatesAutoresizingMaskIntoConstraints: Bool = false)

Uso:

let views = [view1, view2, view3]
parentView.addSubviews(views)

subviews(ofType:)

func subviews<T>(ofType _: T.Type) -> [T]

Uso:

let buttons = view.subviews(ofType: UIButton.self)
let labels = view.subviews(ofType: UILabel.self)

Exemplo Completo

class CustomCardView: UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupCard()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupCard()
    }
    
    private func setupCard() {
        // Configurar aparência
        backgroundColor = .systemBackground
        cornerRadius = 12
        borderWidth = 1
        borderColor = .systemGray4
        
        // Aplicar sombra
        applyShadow(color: .black, offSet: CGSize(width: 0, height: 2), radius: 8, opacity: 0.1)
        
        // Configurar constraints se necessário
        setHeight(size: 200)
    }
    
    func showWithAnimation() {
        alpha = 0
        fadeIn(withDuration: 0.3) { finished in
            print("Card apareceu!")
        }
    }
    
    func hideWithAnimation() {
        fadeOut(withDuration: 0.3) { finished in
            self.removeFromSuperview()
        }
    }
}
UIImage - Extensões para UIImage

UIImage Extensions

Extensões para manipulação de imagens.

Criação

init(base64String:scale:)

convenience init?(base64String: String, scale: CGFloat = 1.0)

Uso:

let base64String = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
if let image = UIImage(base64String: base64String) {
    imageView.image = image
}

init(view:)

@MainActor
convenience init(view: UIView)

Uso:

let image = UIImage(view: myView)

Transformações

tintImage

func tintImage(color: UIColor) -> UIImage

Uso:

let originalImage = UIImage(systemName: "heart.fill")
let tintedImage = originalImage?.tintImage(color: .red)

resizeImage

func resizeImage(newWidth: CGFloat) -> UIImage

Uso:

let resizedImage = originalImage.resizeImage(newWidth: 200)

createThumbnail

func createThumbnail(_ maxPixelSize: UInt) -> UIImage

Uso:

let thumbnail = originalImage.createThumbnail(150)

Utilitários

isAnimated

func isAnimated() -> Bool

Uso:

if image.isAnimated() {
    print("É uma imagem animada (GIF)")
}

imageWithColor

func imageWithColor(color: UIColor) -> UIImage

Uso:

let coloredImage = UIImage().imageWithColor(color: .systemBlue)

Exemplo Completo

class ImageProcessor {
    
    static func processImage(_ image: UIImage) -> UIImage {
        // Redimensionar se muito grande
        var processedImage = image
        if image.size.width > 1000 {
            processedImage = image.resizeImage(newWidth: 1000)
        }
        
        // Criar thumbnail
        let thumbnail = processedImage.createThumbnail(200)
        
        return thumbnail
    }
    
    static func createColoredIcon(systemName: String, color: UIColor, size: CGSize) -> UIImage? {
        let config = UIImage.SymbolConfiguration(pointSize: size.width, weight: .medium)
        let image = UIImage(systemName: systemName, withConfiguration: config)
        return image?.tintImage(color: color)
    }
    
    static func convertViewToImage(_ view: UIView) -> UIImage {
        return UIImage(view: view)
    }
}
UIColor - Extensões para UIColor

UIColor Extensions

Extensões para manipulação de cores.

Inicialização

init(hex:)

convenience init(hex: String)

Uso:

let color1 = UIColor(hex: "#FF0000") // Vermelho
let color2 = UIColor(hex: "#00FF00") // Verde
let color3 = UIColor(hex: "#0000FF") // Azul
let color4 = UIColor(hex: "#FF0000FF") // Vermelho com alpha

Propriedades

hexString

var hexString: String?

Uso:

let color = UIColor.red
if let hex = color.hexString {
    print("Hex: \(hex)") // "#FF0000"
}

redValue, greenValue, blueValue, alphaValue

var redValue: CGFloat
var greenValue: CGFloat
var blueValue: CGFloat
var alphaValue: CGFloat

Uso:

let color = UIColor(red: 0.5, green: 0.3, blue: 0.8, alpha: 1.0)
print("Red: \(color.redValue)")
print("Green: \(color.greenValue)")
print("Blue: \(color.blueValue)")
print("Alpha: \(color.alphaValue)")

Exemplo Completo

class ColorUtils {
    
    static func randomColor() -> UIColor {
        let red = CGFloat.random(in: 0...1)
        let green = CGFloat.random(in: 0...1)
        let blue = CGFloat.random(in: 0...1)
        return UIColor(red: red, green: green, blue: blue, alpha: 1.0)
    }
    
    static func hexToColor(_ hex: String) -> UIColor? {
        return UIColor(hex: hex)
    }
    
    static func colorToHex(_ color: UIColor) -> String? {
        return color.hexString
    }
    
    static func createGradientColors(from startColor: UIColor, to endColor: UIColor, steps: Int) -> [UIColor] {
        var colors: [UIColor] = []
        
        for i in 0..<steps {
            let ratio = CGFloat(i) / CGFloat(steps - 1)
            let red = startColor.redValue + (endColor.redValue - startColor.redValue) * ratio
            let green = startColor.greenValue + (endColor.greenValue - startColor.greenValue) * ratio
            let blue = startColor.blueValue + (endColor.blueValue - startColor.blueValue) * ratio
            let alpha = startColor.alphaValue + (endColor.alphaValue - startColor.alphaValue) * ratio
            
            let color = UIColor(red: red, green: green, blue: blue, alpha: alpha)
            colors.append(color)
        }
        
        return colors
    }
}
Array - Extensões para Array

Array Extensions

Extensões para manipulação de arrays.

Remoção de Duplicatas

unique

var unique: [Element]

Uso:

let numbers = [1, 2, 2, 3, 3, 3, 4]
let uniqueNumbers = numbers.unique
print(uniqueNumbers) // [1, 2, 3, 4]

removeDuplicates

@discardableResult
mutating func removeDuplicates() -> [Element]

Uso:

var numbers = [1, 2, 2, 3, 3, 3, 4]
numbers.removeDuplicates()
print(numbers) // [1, 2, 3, 4]

withoutDuplicates

func withoutDuplicates() -> [Element]

Uso:

let numbers = [1, 2, 2, 3, 3, 3, 4]
let uniqueNumbers = numbers.withoutDuplicates()
print(uniqueNumbers) // [1, 2, 3, 4]

Remoção de Elementos

removeAll

@discardableResult
mutating func removeAll(_ item: Element) -> [Element]
@discardableResult
mutating func removeAll(_ items: [Element]) -> [Element]

Uso:

var numbers = [1, 2, 2, 3, 4, 5]
numbers.removeAll(2)
print(numbers) // [1, 3, 4, 5]

var letters = ["a", "b", "c", "a", "b"]
letters.removeAll(["a", "b"])
print(letters) // ["c"]

Inserção

prepend

mutating func prepend(_ newElement: Element)

Uso:

var numbers = [2, 3, 4]
numbers.prepend(1)
print(numbers) // [1, 2, 3, 4]

Troca

safeSwap

mutating func safeSwap(from index: Index, to otherIndex: Index)

Uso:

var numbers = [1, 2, 3, 4, 5]
numbers.safeSwap(from: 0, to: 4)
print(numbers) // [5, 2, 3, 4, 1]

Exemplo Completo

class ArrayUtils {
    
    static func removeDuplicates<T: Equatable>(from array: [T]) -> [T] {
        return array.unique
    }
    
    static func shuffle<T>(_ array: [T]) -> [T] {
        var shuffled = array
        for i in 0..<shuffled.count {
            let randomIndex = Int.random(in: 0..<shuffled.count)
            shuffled.safeSwap(from: i, to: randomIndex)
        }
        return shuffled
    }
    
    static func chunk<T>(_ array: [T], size: Int) -> [[T]] {
        var chunks: [[T]] = []
        for i in stride(from: 0, to: array.count, by: size) {
            let chunk = Array(array[i..<min(i + size, array.count)])
            chunks.append(chunk)
        }
        return chunks
    }
}
Data - Extensões para Data

Data Extensions

Extensões para manipulação de dados.

Conversões

toHexString

var toHexString: String

Uso:

let data = "Hello".data(using: .utf8)!
let hex = data.toHexString
print(hex) // "48656c6c6f"

init(hexString:)

init?(hexString: String)

Uso:

if let data = Data(hexString: "48656c6c6f") {
    let string = String(data: data, encoding: .utf8)
    print(string) // "Hello"
}

bool

var bool: Bool

Uso:

let trueData = Data([1])
let falseData = Data([0])
print(trueData.bool) // true
print(falseData.bool) // false

Hash e Criptografia

SHA256

func SHA256() -> Data

Uso:

let data = "Hello World".data(using: .utf8)!
let hash = data.SHA256()
print(hash.toHexString)

SHA512

func SHA512() -> Data

Uso:

let data = "Hello World".data(using: .utf8)!
let hash = data.SHA512()
print(hash.toHexString)

HMACSHA512

@available(iOS 13.0, *)
func HMACSHA512(key: Data) -> Data

Uso:

let data = "Hello World".data(using: .utf8)!
let key = "secret".data(using: .utf8)!
let hmac = data.HMACSHA512(key: key)
print(hmac.toHexString)

XOR

func XOR(with other: Data) -> Data

Uso:

let data1 = "Hello".data(using: .utf8)!
let data2 = "World".data(using: .utf8)!
let xor = data1.XOR(with: data2)

JSON

prettyJson

var prettyJson: String?

Uso:

let jsonData = """
{"name": "John", "age": 30, "city": "New York"}
""".data(using: .utf8)!

if let pretty = jsonData.prettyJson {
    print(pretty)
    // {
    //   "name" : "John",
    //   "age" : 30,
    //   "city" : "New York"
    // }
}

toDictionay

var toDictionay: Dictionary<String, Any>?

Uso:

let jsonData = """
{"name": "John", "age": 30}
""".data(using: .utf8)!

if let dict = jsonData.toDictionay {
    print(dict["name"]) // "John"
    print(dict["age"]) // 30
}

object

func object<T: Codable>() -> T?

Uso:

struct User: Codable {
    let name: String
    let age: Int
}

let jsonData = """
{"name": "John", "age": 30}
""".data(using: .utf8)!

if let user: User = jsonData.object() {
    print("Nome: \(user.name), Idade: \(user.age)")
}

Exemplo Completo

class DataUtils {
    
    static func hashString(_ string: String) -> String {
        let data = string.data(using: .utf8)!
        let hash = data.SHA256()
        return hash.toHexString
    }
    
    static func createHMAC(message: String, key: String) -> String {
        let messageData = message.data(using: .utf8)!
        let keyData = key.data(using: .utf8)!
        let hmac = messageData.HMACSHA512(key: keyData)
        return hmac.toHexString
    }
    
    static func encryptData(_ data: Data, with key: Data) -> Data {
        return data.XOR(with: key)
    }
    
    static func decryptData(_ encryptedData: Data, with key: Data) -> Data {
        return encryptedData.XOR(with: key)
    }
}
UIButton - Extensões para UIButton

UIButton Extensions

Extensões para manipulação de botões.

Propriedades por Estado

imageForNormal, imageForHighlighted, imageForSelected, imageForDisabled

var imageForNormal: UIImage? { get set }
var imageForHighlighted: UIImage? { get set }
var imageForSelected: UIImage? { get set }
var imageForDisabled: UIImage? { get set }

Uso:

let button = UIButton()
button.imageForNormal = UIImage(systemName: "heart")
button.imageForHighlighted = UIImage(systemName: "heart.fill")
button.imageForSelected = UIImage(systemName: "heart.fill")

titleForNormal, titleForHighlighted, titleForSelected, titleForDisabled

var titleForNormal: String? { get set }
var titleForHighlighted: String? { get set }
var titleForSelected: String? { get set }
var titleForDisabled: String? { get set }

Uso:

button.titleForNormal = "Normal"
button.titleForHighlighted = "Highlighted"
button.titleForSelected = "Selected"
button.titleForDisabled = "Disabled"

titleColorForNormal, titleColorForHighlighted, titleColorForSelected, titleColorForDisabled

var titleColorForNormal: UIColor? { get set }
var titleColorForHighlighted: UIColor? { get set }
var titleColorForSelected: UIColor? { get set }
var titleColorForDisabled: UIColor? { get set }

Uso:

button.titleColorForNormal = .systemBlue
button.titleColorForHighlighted = .systemRed
button.titleColorForSelected = .systemGreen
button.titleColorForDisabled = .systemGray

Métodos

setImageForAllStates

func setImageForAllStates(_ image: UIImage)

Uso:

let image = UIImage(systemName: "star.fill")
button.setImageForAllStates(image)

setTitleForAllStates

func setTitleForAllStates(_ title: String)

Uso:

button.setTitleForAllStates("Botão")

setTitleColorForAllStates

func setTitleColorForAllStates(_ color: UIColor)

Uso:

button.setTitleColorForAllStates(.white)

centerTextAndImage

func centerTextAndImage(spacing: CGFloat)

Uso:

button.centerTextAndImage(spacing: 8)

Exemplo Completo

class CustomButton: UIButton {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupButton()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupButton()
    }
    
    private func setupButton() {
        // Configurar imagem para todos os estados
        let image = UIImage(systemName: "heart")
        setImageForAllStates(image)
        
        // Configurar título
        setTitleForAllStates("Curtir")
        
        // Configurar cores
        titleColorForNormal = .systemBlue
        titleColorForHighlighted = .systemRed
        titleColorForSelected = .systemGreen
        
        // Centralizar texto e imagem
        centerTextAndImage(spacing: 8)
        
        // Configurar aparência
        backgroundColor = .systemBackground
        layer.cornerRadius = 8
        layer.borderWidth = 1
        layer.borderColor = UIColor.systemBlue.cgColor
    }
    
    func setLiked(_ isLiked: Bool) {
        isSelected = isLiked
        titleForSelected = isLiked ? "Curtido" : "Curtir"
    }
}

📱 Helpers

Funções de Log

Funções de Log

Sistema completo de logging com diferentes níveis.

printLog

public func printLog(title: String, msg: Any, prettyPrint: Bool = false)

Uso:

printLog(title: "DEBUG", msg: "Mensagem de debug")
printLog(title: "USER", msg: userData, prettyPrint: true)

printInfo

public func printInfo(title: String, msg: Any, prettyPrint: Bool = false, function: String = #function, file: String = #file, line: Int = #line, column: Int = #column)

Uso:

printInfo(title: "API", msg: "Requisição realizada com sucesso")

printWarn

public func printWarn(title: String, msg: Any, prettyPrint: Bool = false, function: String = #function, file: String = #file, line: Int = #line, column: Int = #column)

Uso:

printWarn(title: "DEPRECATED", msg: "Este método será removido na próxima versão")

printError

public func printError(title: String, msg: Any, prettyPrint: Bool = false, function: String = #function, file: String = #file, line: Int = #line, column: Int = #column)

Uso:

printError(title: "NETWORK", msg: "Falha na conexão com o servidor")

Exemplo Completo

class NetworkManager {
    
    func fetchData() {
        printInfo(title: "NETWORK", msg: "Iniciando requisição")
        
        // Simular requisição
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            let success = Bool.random()
            
            if success {
                printLog(title: "SUCCESS", msg: "Dados carregados com sucesso")
            } else {
                printError(title: "ERROR", msg: "Falha ao carregar dados")
            }
        }
    }
}
Operador de Potência

Operador de Potência

Operador customizado para cálculos de potência.

Declaração

precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
infix operator ^^ : PowerPrecedence
public func ^^ (radix: Float, power: Float) -> Float

Uso

let result1 = 2.0 ^^ 3.0  // 8.0 (2³)
let result2 = 5.0 ^^ 2.0  // 25.0 (5²)
let result3 = 10.0 ^^ 0.5 // 3.16... (√10)

print("2³ = \(result1)")
print("5² = \(result2)")
print("√10 = \(result3)")

🔐 Criptografia

LCECryptoKitManager - Gerenciador de Criptografia

LCECryptoKitManager

Sistema completo de criptografia usando LCECryptoKit.

Inicialização

// Sem chave privada
let cryptoManager = LCECryptoKitManager()

// Com chave privada
let cryptoManager = LCECryptoKitManager(privateKey: "minha_chave_privada")

Métodos

generateKey

public static func generateKey() -> String

Uso:

let newKey = LCECryptoKitManager.generateKey()
print("Nova chave: \(newKey)")

encodeTP

public func encodeTP(email: String, password: String) -> String?

Uso:

if let encoded = cryptoManager.encodeTP(email: "user@exemplo.com", password: "senha123") {
    print("Dados codificados: \(encoded)")
}

decodeOTP

public func decodeOTP(_ otpHash: String) -> String?

Uso:

if let decoded = cryptoManager.decodeOTP("hash_codificado") {
    print("Dados decodificados: \(decoded)")
}

encodeOTPWithKey

public func encodeOTPWithKey(email: String, password: String) -> String?

Uso:

if let encoded = cryptoManager.encodeOTPWithKey(email: "user@exemplo.com", password: "senha123") {
    print("Dados codificados com chave: \(encoded)")
}

decodeOTPWithKey

public func decodeOTPWithKey(_ otpHash: String) -> Bool

Uso:

let isValid = cryptoManager.decodeOTPWithKey("hash_codificado")
if isValid {
    print("Hash válido!")
} else {
    print("Hash inválido!")
}

Exemplo Completo

class CryptoService {
    private let cryptoManager: LCECryptoKitManager
    
    init(privateKey: String? = nil) {
        if let key = privateKey {
            cryptoManager = LCECryptoKitManager(privateKey: key)
        } else {
            cryptoManager = LCECryptoKitManager()
        }
    }
    
    func encryptUserData(email: String, password: String) -> String? {
        return cryptoManager.encodeTP(email: email, password: password)
    }
    
    func decryptUserData(_ hash: String) -> String? {
        return cryptoManager.decodeOTP(hash)
    }
    
    func validateHash(_ hash: String) -> Bool {
        return cryptoManager.decodeOTPWithKey(hash)
    }
    
    static func generateNewKey() -> String {
        return LCECryptoKitManager.generateKey()
    }
}

🌐 API & Networking

API - Sistema de Requisições HTTP

API

Sistema completo para requisições HTTP com suporte a certificados, cache e retry automático.

Configuração

// Configurar parâmetros padrão
API.defaultParams = ["api_key": "sua_chave_aqui"]

// Configurar certificado cliente
let certData = Data(contentsOf: Bundle.main.url(forResource: "client", withExtension: "p12")!)
API.shared.setupCertificationRequest(certData: certData, password: "senha_do_certificado")

Método Principal

request

public func request<T: Codable>(url: String,
                               params: Any? = nil,
                               method: httpMethod,
                               headers: [String: String] = [:],
                               jsonEncoding: Bool = true,
                               debug: Bool = true,
                               timeoutInterval: TimeInterval = 30,
                               networkServiceType: URLRequest.NetworkServiceType = .default,
                               persistConnection: Bool = false) async throws -> T

Exemplos de Uso

GET Request:

struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

do {
    let users: [User] = try await API.shared.request(
        url: "https://api.exemplo.com/users",
        method: .get,
        headers: ["Authorization": "Bearer token_aqui"]
    )
    print("Usuários: \(users)")
} catch {
    print("Erro: \(error)")
}

POST Request:

struct LoginRequest: Codable {
    let email: String
    let password: String
}

struct LoginResponse: Codable {
    let token: String
    let user: User
}

do {
    let loginData = LoginRequest(email: "user@exemplo.com", password: "senha123")
    let response: LoginResponse = try await API.shared.request(
        url: "https://api.exemplo.com/login",
        params: loginData,
        method: .post
    )
    print("Token: \(response.token)")
} catch {
    print("Erro no login: \(error)")
}

Upload de Arquivo:

let fileURL = URL(fileURLWithPath: "/path/to/image.jpg")
let params = [
    "title": "Minha Imagem",
    "description": "Descrição da imagem",
    "file": fileURL.absoluteString
]

do {
    let response: [String: Any] = try await API.shared.request(
        url: "https://api.exemplo.com/upload",
        params: params,
        method: .post
    )
    print("Upload realizado: \(response)")
} catch {
    print("Erro no upload: \(error)")
}

Com Retry Automático:

do {
    let data: MyResponse = try await API.shared.request(
        url: "https://api.exemplo.com/data",
        method: .get,
        persistConnection: true // Habilita retry automático
    )
} catch {
    print("Erro após tentativas: \(error)")
}

Exemplo Completo

class APIService {
    
    func fetchUsers() async throws -> [User] {
        return try await API.shared.request(
            url: "https://api.exemplo.com/users",
            method: .get,
            headers: ["Authorization": "Bearer \(getToken())"]
        )
    }
    
    func createUser(_ user: User) async throws -> User {
        return try await API.shared.request(
            url: "https://api.exemplo.com/users",
            params: user,
            method: .post
        )
    }
    
    func uploadImage(_ imageData: Data, filename: String) async throws -> [String: Any] {
        let params = [
            "filename": filename,
            "data": imageData.base64EncodedString()
        ]
        
        return try await API.shared.request(
            url: "https://api.exemplo.com/upload",
            params: params,
            method: .post
        )
    }
    
    private func getToken() -> String {
        // Implementar lógica de obtenção de token
        return "seu_token_aqui"
    }
}

📝 Conclusão

O LCEssentials é uma biblioteca completa e poderosa que oferece:

  • 50+ Extensões para tipos fundamentais do Swift/UIKit
  • Componentes UI prontos para uso (SnackBar, ImagePicker, ImageZoom)
  • Suporte SwiftUI com componentes customizados
  • Sistema de API completo com retry automático e certificados
  • Criptografia integrada com LCECryptoKit
  • Helpers e utilitários para desenvolvimento iOS
  • Logging avançado com diferentes níveis
  • Cache inteligente para downloads
  • Validações para CPF, CNPJ, Email, etc.

🚀 Começando

  1. Instale via Swift Package Manager
  2. Importe import LCEssentials
  3. Use as extensões e componentes conforme necessário

📚 Recursos Adicionais

  • Documentação completa com exemplos práticos
  • Suporte para iOS 13+, macOS 10.15+, tvOS 13+, watchOS 6+
  • Código aberto e mantido pela Loverde Co.
  • Atualizações regulares com novas funcionalidades

Desenvolvido com ❤️ pela Loverde Co.

Para dúvidas ou sugestões, entre em contato: daniel@loverde.com.br