### Observable: Reactive Programming with Property Wrappers in Swift Source: https://context7.com/pffan91/apputils/llms.txt Illustrates the use of the `Observable` property wrapper for implementing reactive programming patterns in Swift. It showcases observing changes to properties like `username`, `isLoggedIn`, and `userCount`, including options for observing on the main thread. Also includes an example of manual observation using the `Observer` class for events. ```swift import AppUtils import Foundation class UserViewModel { // Observable property that notifies observers on change @Observable var username: String = "" @Observable var isLoggedIn: Bool = false @Observable var userCount: Int = 0 private var observations: [Observation] = [] func setupObservers() { // Observe username changes (called immediately with current value) $username.observe { newUsername in print("Username changed to: \(newUsername)") }.dispose(in: &observations) // Observe on main thread $isLoggedIn.observeOnMain { loggedIn in print("Login status: \(loggedIn)") }.dispose(in: &observations) // Using function call syntax $userCount { count in print("User count: \(count)") }.dispose(in: &observations) } func updateUser() { username = "john_doe" // Triggers observers isLoggedIn = true // Triggers observers userCount += 1 // Triggers observers } } // Manual observer without property wrapper class EventManager { let buttonTapped = Observer() let dataReceived = Observer() private var observations: [Observation] = [] func setup() { // Observe void events buttonTapped.observe { print("Button was tapped") }.dispose(in: &observations) // Observe data events dataReceived.observe { data in print("Received \(data.count) bytes") }.dispose(in: &observations) } func triggerEvents() { buttonTapped.notify() // or buttonTapped() dataReceived.notify(Data([1, 2, 3])) // or dataReceived(Data([1, 2, 3])) } } ``` -------------------------------- ### Swift JSON Decoding with Configurable Date Strategies Source: https://context7.com/pffan91/apputils/llms.txt Provides examples of decoding JSON data into Swift objects using `AppUtils.Decoders`. It demonstrates decoding with millisecond timestamps, ISO8601 formatted dates, and custom date decoding strategies. Dependencies include the `AppUtils` and `Foundation` frameworks. ```swift import AppUtils import Foundation struct Event: Codable { let id: String let timestamp: Date let data: [String: String] } class SerializationExamples { func decodingExamples() throws { // Using milliseconds timestamp decoder let jsonMillis = """ {"id": "123", "timestamp": 1609459200000, "data": {}} """ let event1 = try Decoders.jsonDecoder.decode(Event.self, from: jsonMillis.data(using: .utf8)!) // Event with milliseconds timestamp // Using ISO8601 date decoder let jsonISO = """ {"id": "456", "timestamp": "2021-01-01T00:00:00Z", "data": {}} """ let event2 = try Decoders.jsonISO8601Decoder.decode(Event.self, from: jsonISO.data(using: .utf8)!) // Event with ISO8601 timestamp // Create custom decoder let customDecoder = Decoders.newJSONDecoder(dateDecodingStrategy: .secondsSince1970) let event3 = try customDecoder.decode(Event.self, from: jsonMillis.data(using: .utf8)!) // Custom decoder with secondsSince1970 strategy } // ... encodingExamples omitted for brevity ... } ``` -------------------------------- ### CoreData Query Building with AppUtils Swift Source: https://context7.com/pffan91/apputils/llms.txt Demonstrates type-safe CoreData query building using the AppUtils library. Supports predicates, sorting, limiting, and typed predicates via KeyPath. Requires CoreData and AppUtils frameworks. ```swift import CoreData import AppUtils // Define CoreData entity class Person: NSManagedObject { @NSManaged var name: String @NSManaged var age: Int16 @NSManaged var createdAt: Date } class DataManager { let context: NSManagedObjectContext init(context: NSManagedObjectContext) { self.context = context } func basicQueries() { // Fetch all persons let allPersons = Query.all(in: context) // Fetch with predicate let predicate = NSPredicate(format: "age >= %d", 18) let adults = Query.all(predicate: predicate, in: context) // Fetch with sorting let sortDescriptor = NSSortDescriptor(key: "name", ascending: true) let sorted = Query.all(sort: [sortDescriptor], in: context) // Fetch with limit let first10 = Query.all(limit: 10, in: context) // Fetch first matching let person = Query.any(predicate: predicate, in: context) // Count entities let count = Query.count(in: context) let adultCount = Query.count(predicate: predicate, in: context) } func typedQueries() { // Fetch sorted by KeyPath let byAge = Query.all(by: \Person.age, desc: true, in: context) // Fetch first by KeyPath let youngest = Query.any(by: \Person.age, desc: false, in: context) // Create fetch request with KeyPath sorting let request = Query.request(by: \Person.createdAt, desc: true, limit: 5) let recentPersons = Query.all(request: request, in: context) } func deleteOperations() { // Delete with predicate let oldPredicate = NSPredicate(format: "age < %d", 13) let deleted = Query.delete(predicate: oldPredicate, in: context) print("Deleted \(deleted.count) persons") // Save context after deletion try? context.save() } func customPredicates() { // Complex predicate example let predicate = NSPredicate(format: "name BEGINSWITH[c] %@ AND age BETWEEN {\d, \d}", "J", 20, 30) let filtered = Query.all(predicate: predicate, sort: [NSSortDescriptor(key: "age", ascending: false)], limit: 20, in: context) } } ``` -------------------------------- ### Swift JSON Encoding with Configurable Date Strategies Source: https://context7.com/pffan91/apputils/llms.txt Illustrates encoding Swift objects into JSON data using `AppUtils.Encoders`. It covers encoding with millisecond timestamps, ISO8601 formatted dates, and custom date encoding strategies. Requires the `AppUtils` and `Foundation` frameworks. ```swift import AppUtils import Foundation struct Event: Codable { let id: String let timestamp: Date let data: [String: String] } class SerializationExamples { // ... decodingExamples omitted for brevity ... func encodingExamples() throws { let event = Event(id: "789", timestamp: Date(), data: ["key": "value"]) // Encode with milliseconds timestamp and pretty printing let encodedMillis = try Encoders.jsonEncoder.encode(event) print(String(data: encodedMillis, encoding: .utf8)!) // Encode with ISO8601 dates let encodedISO = try Encoders.jsonISO8601Encoder.encode(event) print(String(data: encodedISO, encoding: .utf8)!) // Create custom encoder let customEncoder = Encoders.newJSONEncoder(dateEncodingStrategy: .secondsSince1970) let customEncoded = try customEncoder.encode(event) } } ``` -------------------------------- ### Data Formatting Utilities with Formatters Source: https://context7.com/pffan91/apputils/llms.txt A collection of static utility methods for common data formatting tasks. This includes JSON encoding/decoding with different strategies (milliseconds timestamp, ISO8601), formatting prices, phone numbers, time durations, and version strings. It also includes date formatting using a predefined short date formatter. ```swift import AppUtils import Foundation struct User: Codable { let name: String let createdAt: Date } class FormattingExamples { func jsonFormatting() throws { // Decode JSON with milliseconds timestamp let jsonString = """ {"name": "John", "createdAt": 1609459200000} """ let user = try Formatters.jsonDecoder.decode(User.self, from: jsonString.data(using: .utf8)!) // Decode with ISO8601 dates let isoUser = try Formatters.jsonISO8601Decoder.decode(User.self, from: jsonString.data(using: .utf8)!) // Encode to JSON with pretty printing let encoded = try Formatters.jsonEncoder.encode(user) print(String(data: encoded, encoding: .utf8)!) } func priceFormatting() { // Format prices intelligently (whole numbers without decimals) let price1 = Formatters.formatPrice("99.00") // Returns: "99" let price2 = Formatters.formatPrice("99.99") // Returns: "99.99" let price3 = Formatters.formatPrice("1234.5") // Returns: "1234.50" } func phoneFormatting() { // Format phone number with country code let formatted = Formatters.formattedPhoneNumber("14155551234") // Returns: "+1 (415) 555-12-34" } func timeFormatting() { // Format seconds as human-readable time with units let time1 = Formatters.formattedTime(for: 3665, includeUnits: true, hoursShortString: "h", minutesShortString: "m") // Returns: "1 h 1 m" // Format as digital time let time2 = Formatters.formattedTime(for: 3665, includeUnits: false, hoursShortString: "", minutesShortString: "") // Returns: "1:01:05" // Parse time string back to seconds let seconds = Formatters.seconds(from: "1:30:00") // Returns: 5400 } func versionFormatting() { // Convert version and build to server format let serverVersion = Formatters.convertVersionToServerString(version: "1.2.3", build: "45") // Returns: "123000045" (padded and concatenated) } func dateFormatting() { let date = Date() let formatted = Formatters.shortDateFormatter.string(from: date) // Returns short date and time string in current locale } } ``` -------------------------------- ### Unicode Character Constants with AppUtils Swift Source: https://context7.com/pffan91/apputils/llms.txt Illustrates the usage of predefined Unicode character constants from the AppUtils library for consistent UI text display. These constants simplify the inclusion of common symbols and special characters in Swift applications. Requires AppUtils and UIKit frameworks. ```swift import AppUtils import UIKit class CharacterExamples { func displaySymbols() -> String { // Use predefined characters in UI let appleIcon = Char.apple // "" Apple logo let notAvailable = Char.na // "n/a" let noValue = Char.noValue // "–" En Dash let bullet = Char.point // "•" let checkmark = Char.check // "✓" let multiply = Char.multiply // "×" // Direction arrows let up = Char.arrowUp // "↑" let down = Char.arrowDown // "↓" let right = Char.arrowRight // "→" let clockwise = Char.arrowClockwise // "↻" // Build formatted string return "\(checkmark) Task completed \(Char.threeDots)" } func formatTableCell(label: UILabel, value: String?) { // Display value or placeholder label.text = value ?? Char.noValue } func formatPercentageChange(change: Double) -> String { let symbol = change >= 0 ? Char.valueUp : Char.valueDown let arrow = change >= 0 ? Char.arrowUp : Char.arrowDown return "\(symbol) \(arrow) \(abs(change))%" } func formatStatus(completed: Bool) -> String { return completed ? Char.check : Char.multiply } func formatList(items: [String]) -> String { // Create bulleted list return items.map { "\(Char.point) \($0)" }.joined(separator: "\n") } func useSpecialSpacing() -> String { // Use narrow no-break space for better typography return "100\(Char.narrowSpace)km/h" } } ``` -------------------------------- ### iOS Haptic Feedback with HapticFeedbackHelper Source: https://context7.com/pffan91/apputils/llms.txt Provides a singleton class to easily trigger various haptic feedback types on iOS devices. It supports impact styles (light, medium, heavy), notification feedback (success, error, warning), selection feedback, and custom intensity impacts for iOS 13+. ```swift import AppUtils import UIKit class InteractiveViewController: UIViewController { @IBAction func buttonTapped(_ sender: UIButton) { // Light impact feedback for button taps HapticFeedbackHelper.shared.impact(style: .light) } @IBAction func successAction(_ sender: UIButton) { // Success notification feedback HapticFeedbackHelper.shared.notification(type: .success) } @IBAction func errorAction(_ sender: UIButton) { // Error notification feedback HapticFeedbackHelper.shared.notification(type: .error) } @IBAction func warningAction(_ sender: UIButton) { // Warning notification feedback HapticFeedbackHelper.shared.notification(type: .warning) } func pickerValueChanged() { // Selection feedback for pickers and segmented controls HapticFeedbackHelper.shared.selection() } func sliderValueChanged(intensity: CGFloat) { // Custom intensity feedback (iOS 13+) HapticFeedbackHelper.shared.customImpact(intensity: intensity) } func heavyImpact() { // Heavy impact for significant actions HapticFeedbackHelper.shared.impact(style: .heavy) } } ``` -------------------------------- ### GrayscaleImageCache: Async Image Processing and Caching in Swift Source: https://context7.com/pffan91/apputils/llms.txt Demonstrates asynchronous grayscale conversion of images using `GrayscaleImageCache`. It utilizes `NSCache` for caching processed images to enhance performance. The code shows how to process an image from a URL and display it, with automatic caching handled by the `GrayscaleImageCache`. ```swift import AppUtils import UIKit class ImageViewController: UIViewController { @IBOutlet weak var imageView: UIImageView! func displayGrayscaleImage(url: String, originalImage: UIImage) async { let cacheKey = GrayscaleImageCache.CustomKey(string: url) // Process image asynchronously with custom lightening if let grayscale = await GrayscaleImageCache.shared.grayscaleImage( for: cacheKey, original: originalImage, amount: 0.05 ) { imageView.image = grayscale } } func loadAndProcessImage(urlString: String) { guard let url = URL(string: urlString) else { return } // Load original image URLSession.shared.dataTask(with: url) { [weak self] data, _, error in guard let data = data, let image = UIImage(data: data) else { return } Task { let key = GrayscaleImageCache.CustomKey(string: urlString) // Convert to grayscale (cached automatically) if let grayscaleImage = await GrayscaleImageCache.shared.grayscaleImage( for: key, original: image, amount: 0.1 ) { await MainActor.run { self?.imageView.image = grayscaleImage } } } }.resume() } } ``` -------------------------------- ### DataCache: Save and Retrieve Codable Objects and JSON Source: https://context7.com/pffan91/apputils/llms.txt Demonstrates saving and retrieving various data types, including Codable objects and JSON strings, to a Realm-based cache. Supports default and custom expiration intervals. Requires the AppUtils and Foundation frameworks. ```swift import AppUtils import Foundation struct UserProfile: Codable { let id: Int let name: String let email: String } class CacheExamples { func savingAndRetrieving() { // Save JSON string with default 1-day expiration let jsonString = """ {"id": 1, "name": "John", "email": "john@example.com"} """ DataCache.save(json: jsonString, searchKey: "user_profile_1") // Save with custom expiration (1 hour) DataCache.save(json: jsonString, searchKey: "user_profile_1", expirationInterval: 3600) // Save Codable object directly let user = UserProfile(id: 1, name: "John", email: "john@example.com") DataCache.save(content: user, searchKey: "user_profile_1", expirationInterval: .oneDay) // Retrieve cached data if let cache = DataCache.cacheFor(searchKey: "user_profile_1") { let cachedJSON = cache.content // Decode cached data if let data = cachedJSON.data(using: .utf8), let cachedUser = try? JSONDecoder().decode(UserProfile.self, from: data) { print("Cached user: (cachedUser.name)") } } else { print("Cache expired or not found") } } func networkCaching() { let apiKey = "users_list" // Check cache first if let cache = DataCache.cacheFor(searchKey: apiKey) { print("Using cached data") return } // Fetch from network fetchUsersFromAPI { jsonResponse in // Save response to cache DataCache.save(json: jsonResponse, searchKey: apiKey, expirationInterval: 300) // 5 minutes } } func fetchUsersFromAPI(completion: (String) -> Void) { // Simulated network call completion("\n{"users": []}\n") } } ``` -------------------------------- ### ModuleLog: Advanced Logging in Swift Source: https://context7.com/pffan91/apputils/llms.txt ModuleLog offers a structured logging system with multiple levels, emoji indicators, file logging, and per-module log level control. It allows for detailed debugging and monitoring of application events. ```swift import AppUtils class NetworkManager { // Create a module-specific logger let log = ModuleLog(moduleName: "NetworkManager", level: .debug) init() { // Enable file logging at app launch ModuleLog.enableFileLogging(appLaunchCount: 1) } func fetchData() { log.request("GET /api/users") // Simulate network response let responseData = ["users": ["John", "Jane"]] log.response("Received users: \(responseData)") log.debug("Processing user data") log.info("Successfully fetched 2 users") } func performAction() { log.user("User tapped refresh button") log.state("State changed to loading") log.time("Request took 234ms") } func handleError() { let error = NSError(domain: "NetworkError", code: 404, userInfo: nil) log.error(error) log.warn("Retrying request...") } // Static logging methods available static func staticLogging() { ModuleLog.verbose("Verbose debug information") ModuleLog.star("Important milestone reached") ModuleLog.url("https://api.example.com/endpoint") ModuleLog.error("Critical error occurred") } // Access log files func getLogContent() -> String? { let content = ModuleLog.currentLogContent() let allLogPaths = ModuleLog.allLogFilePaths() return content } deinit { ModuleLog.disableFileLogging() } } ``` -------------------------------- ### Loadable Protocol: Show and Hide Activity Indicators in UIViewController Source: https://context7.com/pffan91/apputils/llms.txt An extension for UIViewController that provides convenient methods to display and dismiss activity indicators. It supports different indicator styles and ensures automatic memory management for the loader. Requires UIKit and AppUtils. ```swift import UIKit import AppUtils class DataViewController: UIViewController, Loadable { override func viewDidLoad() { super.viewDidLoad() loadData() } func loadData() { // Show loading indicator with medium style showLoader(style: .medium) // Simulate async operation DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { // Hide loader when done self.hideLoader() } } func refreshData() { // Show large loading indicator showLoader(style: .large) performNetworkRequest { self.hideLoader() if success { print("Data refreshed") } } } func performNetworkRequest(completion: @escaping (Bool) -> Void) { // Simulated network request DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { completion(true) } } } ``` -------------------------------- ### Reusable Protocol for Table/Collection View Cell Registration and Dequeuing (Swift) Source: https://context7.com/pffan91/apputils/llms.txt Simplifies UITableView and UICollectionView cell registration and dequeuing by automatically generating reuse identifiers from class names. This protocol requires `UIKit` and `AppUtils`. It takes a table or collection view and an index path as input, returning the correctly dequeued and typed cell. ```swift import UIKit import AppUtils // Define a custom table view cell conforming to Reusable class CustomTableViewCell: UITableViewCell, Reusable { // Cell implementation } // Define a custom collection view cell class CustomCollectionViewCell: UICollectionViewCell, Reusable { // Cell implementation } // In your view controller class MyViewController: UIViewController { let tableView = UITableView() let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) override func viewDidLoad() { super.viewDidLoad() // Register cells using the Reusable protocol CustomTableViewCell.registerCell(in: tableView) CustomCollectionViewCell.registerCell(in: collectionView) } } // UITableViewDataSource implementation extension MyViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Dequeue with automatic type casting let cell = CustomTableViewCell.dequeueReusableCell(from: tableView, for: indexPath) // Configure cell return cell } } // UICollectionViewDataSource implementation extension MyViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = CustomCollectionViewCell.dequeueReusableCell(from: collectionView, for: indexPath) return cell } } ``` -------------------------------- ### ShakeDetectingWindow: Shake Gesture Detection in Swift Source: https://context7.com/pffan91/apputils/llms.txt ShakeDetectingWindow is a custom UIWindow subclass that detects device shake gestures. It notifies a delegate, typically the AppDelegate, allowing for actions like showing debug menus or clearing cache when a shake is detected. ```swift import UIKit import AppUtils @main class AppDelegate: UIResponder, UIApplicationDelegate { var window: ShakeDetectingWindow? // Use ShakeDetectingWindow func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Create shake-detecting window window = ShakeDetectingWindow(frame: UIScreen.main.bounds) window?.shakeDelegate = self window?.rootViewController = MainViewController() window?.makeKeyAndVisible() return true } } extension AppDelegate: ShakeDetectionDelegate { func didDetectShake(from viewController: UIViewController?) { // Show debug menu when device is shaken let alert = UIAlertController(title: "Shake Detected", message: "Debug menu from \(String(describing: viewController))", preferredStyle: .actionSheet) alert.addAction(UIAlertAction(title: "View Logs", style: .default) { _ in // Show logs }) alert.addAction(UIAlertAction(title: "Clear Cache", style: .destructive) { _ in DataCache.clearAll() }) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel)) viewController?.present(alert, animated: true) } } ``` -------------------------------- ### DataCache: Management Operations Source: https://context7.com/pffan91/apputils/llms.txt Provides functionalities for managing the DataCache, including disabling/enabling caching, removing specific entries, clearing all data, and retrieving cache statistics like total count and all keys. This is useful for debugging and controlling cache behavior. ```swift import AppUtils import Foundation class CacheExamples { func cacheManagement() { // Disable caching globally (for debugging/testing) DataCache.isDisabled = true // Remove specific cache entry DataCache.remove(forKey: "user_profile_1") // Clear all cached data DataCache.clearAll() // Get cache statistics let totalCached = DataCache.count() let allKeys = DataCache.allKeys() print("Total cached entries: (totalCached)") print("Cache keys: (allKeys)") // Re-enable caching DataCache.isDisabled = false } } ``` -------------------------------- ### Intrinsic Views for Auto-sizing UI Components (Swift) Source: https://context7.com/pffan91/apputils/llms.txt Provides custom UITableView, UICollectionView, and UITextView subclasses that automatically calculate their intrinsic content size for seamless integration with Auto Layout. These components require `UIKit` and `AppUtils`. They eliminate the need for manual height constraints by adapting to their content. ```swift import UIKit import AppUtils class MyViewController: UIViewController { // Create an intrinsic table view that sizes itself based on content let tableView = IntrinsicTableView() // Create an intrinsic collection view let collectionView = IntrinsicCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) // Create an intrinsic text view let textView = IntrinsicTextView() override func viewDidLoad() { super.viewDidLoad() // Add constraints - the views will size themselves automatically view.addSubview(tableView) tableView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor) // No height constraint needed - it sizes itself! ]) // Set text and it automatically resizes textView.text = "This text view will automatically resize based on its content" // For table views with dynamic height calculations let autoHeightTableView = IntrinsicWithAutomaticHeightTableView() // This variant recalculates height after data loads } } ``` -------------------------------- ### Throttle Function Execution - Swift Throttler Source: https://context7.com/pffan91/apputils/llms.txt The Throttler utility from AppUtils limits function execution to ensure a minimum time interval between calls. It's useful for scenarios like debouncing search input or throttling notifications. It operates on a specified dispatch queue. ```swift import AppUtils import Foundation class SearchViewController: UIViewController { private let searchThrottler = Throttler(delay: 0.5, queue: .main) @IBOutlet weak var searchTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() searchTextField.addTarget(self, action: #selector(searchTextChanged), for: .editingChanged) } @objc func searchTextChanged() { // Throttle search requests to avoid overwhelming the server searchThrottler.throttle { guard let query = self?.searchTextField.text else { return } self?.performSearch(query: query) } } func performSearch(query: String) { print("Searching for: (query)") // Actual search implementation } } // Using with Observable pattern class ObservableExample { let observer = Observer() func setup() { // Throttle observer notifications observer.throttle(0.3) { print("Throttled value: \(value)") } // These rapid notifications will be throttled observer.notify("a") observer.notify("b") observer.notify("c") // Only this will likely execute } } ``` -------------------------------- ### Dismiss Keyboard on Tap - Swift KeyboardHideManager Source: https://context7.com/pffan91/apputils/llms.txt The KeyboardHideManager utility from AppUtils manages tap gestures to dismiss the keyboard when tapping outside text input fields. It supports scroll views to prevent interference with scrolling gestures. It can manage multiple target views. ```swift import AppUtils import UIKit class FormViewController: UIViewController { @IBOutlet weak var containerView: UIView! @IBOutlet weak var scrollView: UIScrollView! private let keyboardManager = KeyboardHideManager() override func viewDidLoad() { super.viewDidLoad() setupKeyboardDismissal() } func setupKeyboardDismissal() { // Add keyboard dismissal to container view keyboardManager.targets = [containerView] // Enable scroll support (doesn't interfere with scrolling) keyboardManager.scrollSupport = true // Can manage multiple views keyboardManager.targets = [containerView, scrollView] } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // Swift // Clean up by removing targets keyboardManager.targets = [] } } ``` -------------------------------- ### Delay Function Execution - Swift Debouncer Source: https://context7.com/pffan91/apputils/llms.txt The Debouncer utility from AppUtils delays function execution until after a period of inactivity, canceling previous pending executions on new calls. It's ideal for features like autosave or handling rapid user input. It can also accept a custom interval per call. ```swift import AppUtils import UIKit class AutosaveViewController: UIViewController { private let autosaveDebouncer = Debouncer(interval: 2.0) private let dispatchDebouncer = DispatchDebouncer(interval: 1.5) @IBOutlet weak var textView: UITextView! override func viewDidLoad() { super.viewDidLoad() textView.delegate = self } deinit { autosaveDebouncer.cancel() } } extension AutosaveViewController: UITextViewDelegate { func textViewDidChange(_ textView: UITextView) { // Debounce autosave - only saves after user stops typing for 2 seconds autosaveDebouncer.debounce { self?.saveDocument() } // Can override interval per call autosaveDebouncer.debounce(interval: 3.0) { self?.saveDocument() } } func saveDocument() { print("Saving document...") // Save implementation } } // Using DispatchDebouncer for better performance class PerformanceViewController: UIViewController { private let debouncer = DispatchDebouncer(interval: 0.5) func handleRapidEvents() { // Uses GCD for more efficient debouncing debouncer.debounce { print("Event processed") } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.