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

3196 lines
62 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 📚 LCEssentials - Documentação Completa
> **Loverde Co. Essentials Swift Scripts** - Biblioteca completa de utilitários Swift para iOS, macOS, tvOS e watchOS
## 📋 Índice
- [🔧 Instalação](#-instalação)
- [🏗️ Classes Principais](#-classes-principais)
- [🎨 Componentes UI](#-componentes-ui)
- [⚡ SwiftUI](#-swiftui)
- [🔗 Extensões](#-extensões)
- [📱 Helpers](#-helpers)
- [🔐 Criptografia](#-criptografia)
- [🌐 API & Networking](#-api--networking)
---
## 🔧 Instalação
### Swift Package Manager (SPM)
```swift
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
```swift
import LCEssentials
```
---
## 🏗️ Classes Principais
<details>
<summary><strong>LCEssentials - Classe Principal</strong></summary>
### LCEssentials
Classe principal com métodos utilitários gerais para desenvolvimento iOS.
#### Propriedades Estáticas
**Declaração:**
```swift
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:**
```swift
// 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**
```swift
static func backgroundThread(delay: Double = 0.0,
background: (@Sendable () -> Void)? = nil,
completion: (@Sendable () -> Void)? = nil)
```
**Uso:**
```swift
LCEssentials.backgroundThread(delay: 0.6, background: {
// Fazer algo em background
print("Processando...")
}) {
// Quando terminar, atualizar UI
DispatchQueue.main.async {
self.updateUI()
}
}
```
**delay**
```swift
@discardableResult
static func delay(milliseconds: Double,
queue: DispatchQueue = .main,
completion: @escaping () -> Void) -> DispatchWorkItem
```
**Uso:**
```swift
let task = LCEssentials.delay(milliseconds: 2000) {
print("Executado após 2 segundos")
}
// Para cancelar: task.cancel()
```
**debounce**
```swift
static func debounce(millisecondsDelay: Int,
queue: DispatchQueue = .main,
action: @escaping (() -> Void)) -> () -> Void
```
**Uso:**
```swift
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**
```swift
static func getTopViewController(base: UIViewController? = nil,
aboveBars: Bool = true) -> UIViewController?
```
**Uso:**
```swift
if let topVC = LCEssentials.getTopViewController() {
// Fazer algo com o view controller do topo
topVC.present(alert, animated: true)
}
```
**shareApp**
```swift
static func shareApp(message: String = "", url: String = "")
```
**Uso:**
```swift
LCEssentials.shareApp(message: "Confira este app!", url: "https://appstore.com/app")
```
**call**
```swift
static func call(_ number: String!)
```
**Uso:**
```swift
LCEssentials.call("+5511999999999")
```
**openSafari**
```swift
static func openSafari(_ urlStr: String)
```
**Uso:**
```swift
LCEssentials.openSafari("https://loverde.com.br")
```
**downloadFileWithCache**
```swift
static func downloadFileWithCache(from url: URL,
completion: @escaping (Result<URL, Error>) -> Void)
```
**Uso:**
```swift
LCEssentials.downloadFileWithCache(from: imageURL) { result in
switch result {
case .success(let localURL):
print("Arquivo baixado: \(localURL)")
case .failure(let error):
print("Erro: \(error)")
}
}
```
**cleanExpiredCache**
```swift
static func cleanExpiredCache(expiration: TimeInterval = 7 * 24 * 60 * 60)
```
**Uso:**
```swift
// Limpar cache com mais de 1 semana
LCEssentials.cleanExpiredCache(expiration: 7 * 24 * 60 * 60)
```
</details>
<details>
<summary><strong>API - Sistema de Requisições HTTP</strong></summary>
### API
Sistema completo para requisições HTTP com suporte a certificados, cache e retry automático.
#### Configuração
**Declaração:**
```swift
@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:**
```swift
// 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**
```swift
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:**
```swift
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:**
```swift
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:**
```swift
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:**
```swift
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)")
}
```
</details>
<details>
<summary><strong>LCECryptoKitManager - Gerenciador de Criptografia</strong></summary>
### LCECryptoKitManager
Gerenciador para operações de criptografia usando LCECryptoKit.
#### Inicialização
**Declaração:**
```swift
public final class LCECryptoKitManager {
public init()
public init(privateKey: String)
}
```
**Uso:**
```swift
// Sem chave privada
let cryptoManager = LCECryptoKitManager()
// Com chave privada
let cryptoManager = LCECryptoKitManager(privateKey: "minha_chave_privada")
```
#### Métodos
**generateKey**
```swift
public static func generateKey() -> String
```
**Uso:**
```swift
let newKey = LCECryptoKitManager.generateKey()
print("Nova chave gerada: \(newKey)")
```
**encodeTP**
```swift
public func encodeTP(email: String, password: String) -> String?
```
**Uso:**
```swift
if let encoded = cryptoManager.encodeTP(email: "user@exemplo.com", password: "senha123") {
print("Dados codificados: \(encoded)")
}
```
**decodeOTP**
```swift
public func decodeOTP(_ otpHash: String) -> String?
```
**Uso:**
```swift
if let decoded = cryptoManager.decodeOTP("hash_codificado") {
print("Dados decodificados: \(decoded)")
}
```
**encodeOTPWithKey**
```swift
public func encodeOTPWithKey(email: String, password: String) -> String?
```
**Uso:**
```swift
if let encoded = cryptoManager.encodeOTPWithKey(email: "user@exemplo.com", password: "senha123") {
print("Dados codificados com chave: \(encoded)")
}
```
**decodeOTPWithKey**
```swift
public func decodeOTPWithKey(_ otpHash: String) -> Bool
```
**Uso:**
```swift
let isValid = cryptoManager.decodeOTPWithKey("hash_codificado")
if isValid {
print("Hash válido!")
} else {
print("Hash inválido!")
}
```
</details>
<details>
<summary><strong>LCSingleton - Protocolo Singleton</strong></summary>
### LCSingleton
Protocolo para implementação de padrão Singleton.
**Declaração:**
```swift
@objc public protocol LCESingletonDelegate: AnyObject {
@objc optional func singleton(object: Any?, withData: Any)
}
```
**Uso:**
```swift
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")
```
</details>
<details>
<summary><strong>GifHelper - Utilitários para GIFs</strong></summary>
### GifHelper
Utilitários para trabalhar com arquivos GIF animados.
#### UIImageView Extensions
**loadGif**
```swift
public func loadGif(name: String)
public func loadGif(asset: String)
```
**Uso:**
```swift
// Carregar GIF do bundle
imageView.loadGif(name: "animacao")
// Carregar GIF do asset catalog
imageView.loadGif(asset: "animacao_gif")
```
#### UIImage Extensions
**gif**
```swift
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:**
```swift
// 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
}
```
</details>
<details>
<summary><strong>Repositorio - Estrutura de Repositório</strong></summary>
### Repositorio
Estrutura básica para repositórios.
**Declaração:**
```swift
struct Repositorio {
var text = "Hello, World!"
private var testBin: [Int] = []
}
```
**Uso:**
```swift
var repo = Repositorio()
print(repo.text) // "Hello, World!"
```
</details>
---
## 🎨 Componentes UI
<details>
<summary><strong>LCSnackBarView - Sistema de Notificações</strong></summary>
### LCSnackBarView
Sistema completo de notificações estilo SnackBar para iOS.
#### Inicialização
**Declaração:**
```swift
public final class LCSnackBarView: UIView {
public init(style: LCSnackBarViewType = .default,
orientation: LCSnackBarOrientation = .top,
delegate: LCSnackBarViewDelegate? = nil)
}
```
**Uso:**
```swift
// 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:)**
```swift
@discardableResult
func configure(text: String) -> Self
```
**Uso:**
```swift
snackBar.configure(text: "Sua mensagem aqui")
```
**configure(textColor:)**
```swift
@discardableResult
func configure(textColor: UIColor) -> Self
```
**Uso:**
```swift
snackBar.configure(textColor: .white)
```
**configure(textFont:alignment:)**
```swift
@discardableResult
func configure(textFont: UIFont, alignment: NSTextAlignment = .center) -> Self
```
**Uso:**
```swift
snackBar.configure(textFont: .boldSystemFont(ofSize: 16), alignment: .left)
```
**configure(backgroundColor:)**
```swift
@discardableResult
func configure(backgroundColor: UIColor) -> Self
```
**Uso:**
```swift
snackBar.configure(backgroundColor: .systemGreen)
```
**configure(exibition:)**
```swift
@discardableResult
func configure(exibition timer: LCSnackBarTimer) -> Self
```
**Uso:**
```swift
snackBar.configure(exibition: .medium) // 5 segundos
snackBar.configure(exibition: .infinity) // Permanece até ser fechado manualmente
```
**configure(imageIconBefore:withTintColor:)**
```swift
@discardableResult
func configure(imageIconBefore icon: UIImageView, withTintColor: UIColor? = nil) -> Self
```
**Uso:**
```swift
let icon = UIImageView(image: UIImage(systemName: "checkmark.circle.fill"))
snackBar.configure(imageIconBefore: icon, withTintColor: .white)
```
**present(completion:)**
```swift
func present(completion: (()->())? = nil)
```
**Uso:**
```swift
snackBar.present {
print("SnackBar apresentado!")
}
```
#### Enums
**LCSnackBarViewType**
```swift
public enum LCSnackBarViewType {
case `default` // Retangular
case rounded // Arredondado
}
```
**LCSnackBarOrientation**
```swift
public enum LCSnackBarOrientation {
case top // Aparece no topo
case bottom // Aparece na parte inferior
}
```
**LCSnackBarTimer**
```swift
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**
```swift
@objc public protocol LCSnackBarViewDelegate {
@objc optional func snackbar(didStartExibition: LCSnackBarView)
@objc optional func snackbar(didTouchOn snackbar: LCSnackBarView)
@objc optional func snackbar(didEndExibition: LCSnackBarView)
}
```
**Uso:**
```swift
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
```swift
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()
}
}
```
</details>
<details>
<summary><strong>ImagePickerController - Seletor de Imagens</strong></summary>
### ImagePickerController
Controlador para seleção de imagens da câmera ou biblioteca de fotos.
#### Inicialização
**Declaração:**
```swift
public class ImagePickerController: UIViewController, UINavigationControllerDelegate {
public weak var delegate: ImagePickerControllerDelegate?
public var isEditable: Bool = false
public init()
}
```
**Uso:**
```swift
let imagePicker = ImagePickerController()
imagePicker.delegate = self
imagePicker.isEditable = true // Permite edição da imagem
```
#### Delegate
**ImagePickerControllerDelegate**
```swift
public protocol ImagePickerControllerDelegate: AnyObject {
func imagePicker(didSelect image: UIImage?)
}
```
**Uso:**
```swift
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**
```swift
public func openImagePicker()
```
**Uso:**
```swift
let imagePicker = ImagePickerController()
imagePicker.delegate = self
imagePicker.openImagePicker() // Abre automaticamente o seletor
```
#### Exemplo Completo
```swift
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!")
}
}
```
</details>
<details>
<summary><strong>ImageZoomController - Visualizador de Imagens com Zoom</strong></summary>
### ImageZoomController
Controlador para visualização de imagens com zoom e pan.
#### Inicialização
**Declaração:**
```swift
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:**
```swift
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**
```swift
@objc public protocol ImageZoomControllerDelegate {
@objc optional func imageZoomController(controller: ImageZoomController, didZoom image: UIImage?)
@objc optional func imageZoomController(controller: ImageZoomController, didClose image: UIImage?)
}
```
**Uso:**
```swift
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:)**
```swift
public func present(completion: (()->())? = nil)
```
**Uso:**
```swift
zoomController.present {
print("Visualizador apresentado!")
}
```
**dismiss(completion:)**
```swift
public func dismiss(completion: (()->())? = nil)
```
**Uso:**
```swift
zoomController.dismiss {
print("Visualizador fechado!")
}
```
#### Exemplo Completo
```swift
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
}
}
```
</details>
---
## ⚡ SwiftUI
<details>
<summary><strong>LCENavigationView - Navegação Customizada SwiftUI</strong></summary>
### LCENavigationView
Componente SwiftUI para navegação customizada com botões e títulos.
#### Inicialização
**Declaração:**
```swift
@available(iOS 15, *)
public struct LCENavigationView<Content: View>: View {
public init(title: (any View) = Text(""),
subTitle: (any View) = Text(""),
@ViewBuilder content: () -> Content)
}
```
**Uso:**
```swift
LCENavigationView {
Text("Conteúdo da tela")
}
```
#### Configuração
**setTitle**
```swift
public func setTitle(text: (any View) = Text(""),
subTitle: (any View)? = nil) -> LCENavigationView
```
**Uso:**
```swift
LCENavigationView {
Text("Conteúdo")
}
.setTitle(text: Text("Meu Título"), subTitle: Text("Subtítulo"))
```
**setLeftButton**
```swift
public func setLeftButton(text: Text = Text(""),
image: (any View)? = nil,
action: @escaping () -> Void) -> LCENavigationView
```
**Uso:**
```swift
LCENavigationView {
Text("Conteúdo")
}
.setLeftButton(text: Text("Voltar")) {
print("Botão esquerdo pressionado")
}
.setLeftButton(image: Image(systemName: "arrow.left")) {
print("Seta esquerda pressionada")
}
```
**setRightButton**
```swift
public func setRightButton(text: Text = Text(""),
image: (any View)? = nil,
action: @escaping () -> Void) -> LCENavigationView
```
**Uso:**
```swift
LCENavigationView {
Text("Conteúdo")
}
.setRightButton(text: Text("Salvar")) {
print("Salvar pressionado")
}
.setRightButton(image: Image(systemName: "checkmark")) {
print("Checkmark pressionado")
}
```
**hideNavigationView**
```swift
public func hideNavigationView(_ hide: Bool) -> LCENavigationView
```
**Uso:**
```swift
LCENavigationView {
Text("Conteúdo")
}
.hideNavigationView(true) // Esconde a barra de navegação
```
#### Exemplo Completo
```swift
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()
}
}
}
```
</details>
<details>
<summary><strong>View+Ext - Extensões SwiftUI</strong></summary>
### View+Ext
Extensões para Views SwiftUI.
#### getTag
**Declaração:**
```swift
@available(iOS 13.0, *)
extension View {
func getTag<TagType: Hashable>() throws -> TagType
func extractTag<TagType: Hashable>(_ closure: (() throws -> TagType) -> Void) -> Self
}
```
**Uso:**
```swift
struct MyView: View {
var body: some View {
Text("Hello")
.tag("myTag")
.extractTag { tag in
print("Tag extraída: \(tag)")
}
}
}
```
</details>
---
## 🔗 Extensões
<details>
<summary><strong>String - Extensões para String</strong></summary>
### String Extensions
Extensões poderosas para manipulação de strings.
#### Validações
**isEmail**
```swift
var isEmail: Bool
```
**Uso:**
```swift
let email = "user@exemplo.com"
if email.isEmail {
print("Email válido!")
}
```
**isCPF**
```swift
var isCPF: Bool
```
**Uso:**
```swift
let cpf = "12345678901"
if cpf.isCPF {
print("CPF válido!")
}
```
**isValidCNPJ**
```swift
var isValidCNPJ: Bool
```
**Uso:**
```swift
let cnpj = "12345678000195"
if cnpj.isValidCNPJ {
print("CNPJ válido!")
}
```
#### Transformações
**urlEncoded**
```swift
var urlEncoded: String
```
**Uso:**
```swift
let text = "Hello World!"
let encoded = text.urlEncoded
print(encoded) // "Hello%20World%21"
```
**urlDecoded**
```swift
var urlDecoded: String
```
**Uso:**
```swift
let encoded = "Hello%20World%21"
let decoded = encoded.urlDecoded
print(decoded) // "Hello World!"
```
**base64Encode**
```swift
var base64Encode: String?
```
**Uso:**
```swift
let text = "Hello World!"
if let encoded = text.base64Encode {
print("Base64: \(encoded)")
}
```
**base64Decode**
```swift
var base64Decode: String?
```
**Uso:**
```swift
let encoded = "SGVsbG8gV29ybGQh"
if let decoded = encoded.base64Decode {
print("Decoded: \(decoded)")
}
```
#### Limpeza e Filtros
**onlyNumbers**
```swift
var onlyNumbers: String
```
**Uso:**
```swift
let phone = "+55 (11) 99999-9999"
let numbers = phone.onlyNumbers
print(numbers) // "5511999999999"
```
**removeSpecialChars**
```swift
var removeSpecialChars: String
```
**Uso:**
```swift
let text = "Hello@#$%World!"
let clean = text.removeSpecialChars
print(clean) // "HelloWorld"
```
**removeHTMLTags**
```swift
var removeHTMLTags: String
```
**Uso:**
```swift
let html = "<p>Hello <strong>World</strong>!</p>"
let text = html.removeHTMLTags
print(text) // "Hello World!"
```
**removeEmoji**
```swift
var removeEmoji: String
```
**Uso:**
```swift
let text = "Hello 😀 World 🌍!"
let clean = text.removeEmoji
print(clean) // "Hello World !"
```
#### Conversões
**int**
```swift
var int: Int?
```
**Uso:**
```swift
let numberString = "123"
if let number = numberString.int {
print("Número: \(number)")
}
```
**double**
```swift
var double: Double?
```
**Uso:**
```swift
let numberString = "123.45"
if let number = numberString.double {
print("Número: \(number)")
}
```
**bool**
```swift
var bool: Bool?
```
**Uso:**
```swift
let boolString = "true"
if let value = boolString.bool {
print("Valor: \(value)")
}
```
#### Formatação
**applyMask**
```swift
func applyMask(toText: String, mask: String) -> String
```
**Uso:**
```swift
let phone = "11999999999"
let masked = "".applyMask(toText: phone, mask: "(##) #####-####")
print(masked) // "(11) 99999-9999"
```
**currencyStringToDouble**
```swift
var currencyStringToDouble: Double
```
**Uso:**
```swift
let currency = "R$ 1.234,56"
let value = currency.currencyStringToDouble
print(value) // 1234.56
```
#### Data e Hora
**date**
```swift
func date(withCurrFormatt: String = "yyyy-MM-dd HH:mm:ss",
localeIdentifier: String = "pt-BR",
timeZone: TimeZone? = TimeZone.current) -> Date?
```
**Uso:**
```swift
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
```swift
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
}
}
```
</details>
<details>
<summary><strong>Date - Extensões para Date</strong></summary>
### Date Extensions
Extensões completas para manipulação de datas.
#### Propriedades
**year, month, day, hour, minute, second**
```swift
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:**
```swift
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**
```swift
var isInToday: Bool
var isInYesterday: Bool
var isInTomorrow: Bool
```
**Uso:**
```swift
let date = Date()
if date.isInToday {
print("É hoje!")
} else if date.isInYesterday {
print("É ontem!")
} else if date.isInTomorrow {
print("É amanhã!")
}
```
**isInFuture, isInPast**
```swift
var isInFuture: Bool
var isInPast: Bool
```
**Uso:**
```swift
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**
```swift
func adding(_ component: Calendar.Component, value: Int) -> Date
```
**Uso:**
```swift
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**
```swift
func changing(_ component: Calendar.Component, value: Int) -> Date?
```
**Uso:**
```swift
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**
```swift
func string(withFormat format: String = "dd/MM/yyyy HH:mm") -> String
```
**Uso:**
```swift
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**
```swift
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:**
```swift
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**
```swift
func dayName(ofStyle style: DayNameStyle = .full) -> String
func monthName(ofStyle style: MonthNameStyle = .full) -> String
```
**Uso:**
```swift
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**
```swift
func secondsSince(_ date: Date) -> Double
func minutesSince(_ date: Date) -> Double
func hoursSince(_ date: Date) -> Double
func daysSince(_ date: Date) -> Double
```
**Uso:**
```swift
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**
```swift
func isBetween(_ startDate: Date, _ endDate: Date, includeBounds: Bool = false) -> Bool
```
**Uso:**
```swift
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
```swift
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
}
}
```
</details>
<details>
<summary><strong>UIView - Extensões para UIView</strong></summary>
### UIView Extensions
Extensões poderosas para manipulação de views.
#### Propriedades
**borderColor, borderWidth, cornerRadius**
```swift
var borderColor: UIColor? { get set }
var borderWidth: CGFloat { get set }
var cornerRadius: CGFloat { get set }
```
**Uso:**
```swift
let view = UIView()
view.borderColor = .systemBlue
view.borderWidth = 2.0
view.cornerRadius = 8.0
```
**screenshot**
```swift
var screenshot: UIImage?
```
**Uso:**
```swift
if let screenshot = view.screenshot {
// Usar screenshot da view
imageView.image = screenshot
}
```
#### Constraint Helpers
**setConstraintsTo**
```swift
@discardableResult
func setConstraintsTo(parentView: UIView, anchorType: AnchorType, value: CGFloat, safeArea: Bool = false) -> Self
```
**Uso:**
```swift
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**
```swift
@discardableResult
func setHeight(size: CGFloat) -> Self
@discardableResult
func setWidth(size: CGFloat) -> Self
```
**Uso:**
```swift
view.setHeight(size: 100)
.setWidth(size: 200)
```
#### Efeitos Visuais
**applyShadow**
```swift
func applyShadow(color: UIColor, offSet: CGSize, radius: CGFloat, opacity: Float, shouldRasterize: Bool = true, rasterizationScaleTo: CGFloat = UIScreen.main.scale)
```
**Uso:**
```swift
view.applyShadow(color: .black, offSet: CGSize(width: 0, height: 2), radius: 4, opacity: 0.3)
```
**insertBlurView**
```swift
func insertBlurView(style: UIBlurEffect.Style, color: UIColor = .black, alpha: CGFloat = 0.9)
```
**Uso:**
```swift
view.insertBlurView(style: .dark, color: .black, alpha: 0.8)
```
#### Animações
**fadeIn, fadeOut**
```swift
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:**
```swift
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**
```swift
func addSubviews(_ subviews: [UIView], translatesAutoresizingMaskIntoConstraints: Bool = false)
```
**Uso:**
```swift
let views = [view1, view2, view3]
parentView.addSubviews(views)
```
**subviews(ofType:)**
```swift
func subviews<T>(ofType _: T.Type) -> [T]
```
**Uso:**
```swift
let buttons = view.subviews(ofType: UIButton.self)
let labels = view.subviews(ofType: UILabel.self)
```
#### Exemplo Completo
```swift
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()
}
}
}
```
</details>
<details>
<summary><strong>UIImage - Extensões para UIImage</strong></summary>
### UIImage Extensions
Extensões para manipulação de imagens.
#### Criação
**init(base64String:scale:)**
```swift
convenience init?(base64String: String, scale: CGFloat = 1.0)
```
**Uso:**
```swift
let base64String = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
if let image = UIImage(base64String: base64String) {
imageView.image = image
}
```
**init(view:)**
```swift
@MainActor
convenience init(view: UIView)
```
**Uso:**
```swift
let image = UIImage(view: myView)
```
#### Transformações
**tintImage**
```swift
func tintImage(color: UIColor) -> UIImage
```
**Uso:**
```swift
let originalImage = UIImage(systemName: "heart.fill")
let tintedImage = originalImage?.tintImage(color: .red)
```
**resizeImage**
```swift
func resizeImage(newWidth: CGFloat) -> UIImage
```
**Uso:**
```swift
let resizedImage = originalImage.resizeImage(newWidth: 200)
```
**createThumbnail**
```swift
func createThumbnail(_ maxPixelSize: UInt) -> UIImage
```
**Uso:**
```swift
let thumbnail = originalImage.createThumbnail(150)
```
#### Utilitários
**isAnimated**
```swift
func isAnimated() -> Bool
```
**Uso:**
```swift
if image.isAnimated() {
print("É uma imagem animada (GIF)")
}
```
**imageWithColor**
```swift
func imageWithColor(color: UIColor) -> UIImage
```
**Uso:**
```swift
let coloredImage = UIImage().imageWithColor(color: .systemBlue)
```
#### Exemplo Completo
```swift
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)
}
}
```
</details>
<details>
<summary><strong>UIColor - Extensões para UIColor</strong></summary>
### UIColor Extensions
Extensões para manipulação de cores.
#### Inicialização
**init(hex:)**
```swift
convenience init(hex: String)
```
**Uso:**
```swift
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**
```swift
var hexString: String?
```
**Uso:**
```swift
let color = UIColor.red
if let hex = color.hexString {
print("Hex: \(hex)") // "#FF0000"
}
```
**redValue, greenValue, blueValue, alphaValue**
```swift
var redValue: CGFloat
var greenValue: CGFloat
var blueValue: CGFloat
var alphaValue: CGFloat
```
**Uso:**
```swift
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
```swift
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
}
}
```
</details>
<details>
<summary><strong>Array - Extensões para Array</strong></summary>
### Array Extensions
Extensões para manipulação de arrays.
#### Remoção de Duplicatas
**unique**
```swift
var unique: [Element]
```
**Uso:**
```swift
let numbers = [1, 2, 2, 3, 3, 3, 4]
let uniqueNumbers = numbers.unique
print(uniqueNumbers) // [1, 2, 3, 4]
```
**removeDuplicates**
```swift
@discardableResult
mutating func removeDuplicates() -> [Element]
```
**Uso:**
```swift
var numbers = [1, 2, 2, 3, 3, 3, 4]
numbers.removeDuplicates()
print(numbers) // [1, 2, 3, 4]
```
**withoutDuplicates**
```swift
func withoutDuplicates() -> [Element]
```
**Uso:**
```swift
let numbers = [1, 2, 2, 3, 3, 3, 4]
let uniqueNumbers = numbers.withoutDuplicates()
print(uniqueNumbers) // [1, 2, 3, 4]
```
#### Remoção de Elementos
**removeAll**
```swift
@discardableResult
mutating func removeAll(_ item: Element) -> [Element]
@discardableResult
mutating func removeAll(_ items: [Element]) -> [Element]
```
**Uso:**
```swift
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**
```swift
mutating func prepend(_ newElement: Element)
```
**Uso:**
```swift
var numbers = [2, 3, 4]
numbers.prepend(1)
print(numbers) // [1, 2, 3, 4]
```
#### Troca
**safeSwap**
```swift
mutating func safeSwap(from index: Index, to otherIndex: Index)
```
**Uso:**
```swift
var numbers = [1, 2, 3, 4, 5]
numbers.safeSwap(from: 0, to: 4)
print(numbers) // [5, 2, 3, 4, 1]
```
#### Exemplo Completo
```swift
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
}
}
```
</details>
<details>
<summary><strong>Data - Extensões para Data</strong></summary>
### Data Extensions
Extensões para manipulação de dados.
#### Conversões
**toHexString**
```swift
var toHexString: String
```
**Uso:**
```swift
let data = "Hello".data(using: .utf8)!
let hex = data.toHexString
print(hex) // "48656c6c6f"
```
**init(hexString:)**
```swift
init?(hexString: String)
```
**Uso:**
```swift
if let data = Data(hexString: "48656c6c6f") {
let string = String(data: data, encoding: .utf8)
print(string) // "Hello"
}
```
**bool**
```swift
var bool: Bool
```
**Uso:**
```swift
let trueData = Data([1])
let falseData = Data([0])
print(trueData.bool) // true
print(falseData.bool) // false
```
#### Hash e Criptografia
**SHA256**
```swift
func SHA256() -> Data
```
**Uso:**
```swift
let data = "Hello World".data(using: .utf8)!
let hash = data.SHA256()
print(hash.toHexString)
```
**SHA512**
```swift
func SHA512() -> Data
```
**Uso:**
```swift
let data = "Hello World".data(using: .utf8)!
let hash = data.SHA512()
print(hash.toHexString)
```
**HMACSHA512**
```swift
@available(iOS 13.0, *)
func HMACSHA512(key: Data) -> Data
```
**Uso:**
```swift
let data = "Hello World".data(using: .utf8)!
let key = "secret".data(using: .utf8)!
let hmac = data.HMACSHA512(key: key)
print(hmac.toHexString)
```
**XOR**
```swift
func XOR(with other: Data) -> Data
```
**Uso:**
```swift
let data1 = "Hello".data(using: .utf8)!
let data2 = "World".data(using: .utf8)!
let xor = data1.XOR(with: data2)
```
#### JSON
**prettyJson**
```swift
var prettyJson: String?
```
**Uso:**
```swift
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**
```swift
var toDictionay: Dictionary<String, Any>?
```
**Uso:**
```swift
let jsonData = """
{"name": "John", "age": 30}
""".data(using: .utf8)!
if let dict = jsonData.toDictionay {
print(dict["name"]) // "John"
print(dict["age"]) // 30
}
```
**object**
```swift
func object<T: Codable>() -> T?
```
**Uso:**
```swift
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
```swift
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)
}
}
```
</details>
<details>
<summary><strong>UIButton - Extensões para UIButton</strong></summary>
### UIButton Extensions
Extensões para manipulação de botões.
#### Propriedades por Estado
**imageForNormal, imageForHighlighted, imageForSelected, imageForDisabled**
```swift
var imageForNormal: UIImage? { get set }
var imageForHighlighted: UIImage? { get set }
var imageForSelected: UIImage? { get set }
var imageForDisabled: UIImage? { get set }
```
**Uso:**
```swift
let button = UIButton()
button.imageForNormal = UIImage(systemName: "heart")
button.imageForHighlighted = UIImage(systemName: "heart.fill")
button.imageForSelected = UIImage(systemName: "heart.fill")
```
**titleForNormal, titleForHighlighted, titleForSelected, titleForDisabled**
```swift
var titleForNormal: String? { get set }
var titleForHighlighted: String? { get set }
var titleForSelected: String? { get set }
var titleForDisabled: String? { get set }
```
**Uso:**
```swift
button.titleForNormal = "Normal"
button.titleForHighlighted = "Highlighted"
button.titleForSelected = "Selected"
button.titleForDisabled = "Disabled"
```
**titleColorForNormal, titleColorForHighlighted, titleColorForSelected, titleColorForDisabled**
```swift
var titleColorForNormal: UIColor? { get set }
var titleColorForHighlighted: UIColor? { get set }
var titleColorForSelected: UIColor? { get set }
var titleColorForDisabled: UIColor? { get set }
```
**Uso:**
```swift
button.titleColorForNormal = .systemBlue
button.titleColorForHighlighted = .systemRed
button.titleColorForSelected = .systemGreen
button.titleColorForDisabled = .systemGray
```
#### Métodos
**setImageForAllStates**
```swift
func setImageForAllStates(_ image: UIImage)
```
**Uso:**
```swift
let image = UIImage(systemName: "star.fill")
button.setImageForAllStates(image)
```
**setTitleForAllStates**
```swift
func setTitleForAllStates(_ title: String)
```
**Uso:**
```swift
button.setTitleForAllStates("Botão")
```
**setTitleColorForAllStates**
```swift
func setTitleColorForAllStates(_ color: UIColor)
```
**Uso:**
```swift
button.setTitleColorForAllStates(.white)
```
**centerTextAndImage**
```swift
func centerTextAndImage(spacing: CGFloat)
```
**Uso:**
```swift
button.centerTextAndImage(spacing: 8)
```
#### Exemplo Completo
```swift
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"
}
}
```
</details>
---
## 📱 Helpers
<details>
<summary><strong>Funções de Log</strong></summary>
### Funções de Log
Sistema completo de logging com diferentes níveis.
#### printLog
```swift
public func printLog(title: String, msg: Any, prettyPrint: Bool = false)
```
**Uso:**
```swift
printLog(title: "DEBUG", msg: "Mensagem de debug")
printLog(title: "USER", msg: userData, prettyPrint: true)
```
#### printInfo
```swift
public func printInfo(title: String, msg: Any, prettyPrint: Bool = false, function: String = #function, file: String = #file, line: Int = #line, column: Int = #column)
```
**Uso:**
```swift
printInfo(title: "API", msg: "Requisição realizada com sucesso")
```
#### printWarn
```swift
public func printWarn(title: String, msg: Any, prettyPrint: Bool = false, function: String = #function, file: String = #file, line: Int = #line, column: Int = #column)
```
**Uso:**
```swift
printWarn(title: "DEPRECATED", msg: "Este método será removido na próxima versão")
```
#### printError
```swift
public func printError(title: String, msg: Any, prettyPrint: Bool = false, function: String = #function, file: String = #file, line: Int = #line, column: Int = #column)
```
**Uso:**
```swift
printError(title: "NETWORK", msg: "Falha na conexão com o servidor")
```
#### Exemplo Completo
```swift
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")
}
}
}
}
```
</details>
<details>
<summary><strong>Operador de Potência</strong></summary>
### Operador de Potência
Operador customizado para cálculos de potência.
#### Declaração
```swift
precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence }
infix operator ^^ : PowerPrecedence
public func ^^ (radix: Float, power: Float) -> Float
```
#### Uso
```swift
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)")
```
</details>
---
## 🔐 Criptografia
<details>
<summary><strong>LCECryptoKitManager - Gerenciador de Criptografia</strong></summary>
### LCECryptoKitManager
Sistema completo de criptografia usando LCECryptoKit.
#### Inicialização
```swift
// Sem chave privada
let cryptoManager = LCECryptoKitManager()
// Com chave privada
let cryptoManager = LCECryptoKitManager(privateKey: "minha_chave_privada")
```
#### Métodos
**generateKey**
```swift
public static func generateKey() -> String
```
**Uso:**
```swift
let newKey = LCECryptoKitManager.generateKey()
print("Nova chave: \(newKey)")
```
**encodeTP**
```swift
public func encodeTP(email: String, password: String) -> String?
```
**Uso:**
```swift
if let encoded = cryptoManager.encodeTP(email: "user@exemplo.com", password: "senha123") {
print("Dados codificados: \(encoded)")
}
```
**decodeOTP**
```swift
public func decodeOTP(_ otpHash: String) -> String?
```
**Uso:**
```swift
if let decoded = cryptoManager.decodeOTP("hash_codificado") {
print("Dados decodificados: \(decoded)")
}
```
**encodeOTPWithKey**
```swift
public func encodeOTPWithKey(email: String, password: String) -> String?
```
**Uso:**
```swift
if let encoded = cryptoManager.encodeOTPWithKey(email: "user@exemplo.com", password: "senha123") {
print("Dados codificados com chave: \(encoded)")
}
```
**decodeOTPWithKey**
```swift
public func decodeOTPWithKey(_ otpHash: String) -> Bool
```
**Uso:**
```swift
let isValid = cryptoManager.decodeOTPWithKey("hash_codificado")
if isValid {
print("Hash válido!")
} else {
print("Hash inválido!")
}
```
#### Exemplo Completo
```swift
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()
}
}
```
</details>
---
## 🌐 API & Networking
<details>
<summary><strong>API - Sistema de Requisições HTTP</strong></summary>
### API
Sistema completo para requisições HTTP com suporte a certificados, cache e retry automático.
#### Configuração
```swift
// 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**
```swift
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:**
```swift
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:**
```swift
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:**
```swift
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:**
```swift
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
```swift
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"
}
}
```
</details>
---
## 📝 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.](https://loverde.com.br)**
*Para dúvidas ou sugestões, entre em contato: daniel@loverde.com.br*