### Setup LifetimeTracker in AppDelegate (Swift) Source: https://github.com/krzysztofzablocki/lifetimetracker/blob/master/README.md Initialize LifetimeTracker with a dashboard integration in your AppDelegate for debugging builds. This setup provides visual feedback on memory issues. ```swift #if DEBUG LifetimeTracker.setup( onUpdate: LifetimeTrackerDashboardIntegration( visibility: .alwaysVisible, style: .bar, textColorForNoIssues: .systemGreen, textColorForLeakDetected: .systemRed ).refreshUI ) #endif ``` -------------------------------- ### Setup LifetimeTracker in AppDelegate (Objective-C) Source: https://github.com/krzysztofzablocki/lifetimetracker/blob/master/README.md Integrate LifetimeTracker in your Objective-C application by setting up the dashboard integration. This allows for visual monitoring of memory issues during development. ```objectivec LifetimeTrackerDashboardIntegration *dashboardIntegration = [LifetimeTrackerDashboardIntegration new]; [dashboardIntegration setVisibleWhenIssueDetected]; [dashboardIntegration useBarStyle]; [LifetimeTracker setupOnUpdate:^(NSDictionary * groups) { [dashboardIntegration refreshUIWithTrackedGroups: groups]; }]; ``` -------------------------------- ### Bootstrap LifetimeTracker with Setup Source: https://context7.com/krzysztofzablocki/lifetimetracker/llms.txt Initializes the LifetimeTracker singleton. Call this once during app startup. Configure leak detection callbacks and UI updates. The `onUpdate` closure drives the visual overlay, and `onLeakDetected` fires when an object count exceeds its maximum. ```swift import LifetimeTracker func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { #if DEBUG // Full setup: visual dashboard + leak-detected logging let dashboard = LifetimeTrackerDashboardIntegration( visibility: .visibleWithIssuesDetected, // .alwaysVisible | .alwaysHidden style: .bar, // .bar | .circular textColorForNoIssues: .systemGreen, textColorForLeakDetected: .systemRed ) LifetimeTracker.setup( onLeakDetected: { entry, group in // Called every time count exceeds maxCount for an entry print("⚠️ LEAK: \(entry.name) — alive: \(entry.count), max: \(entry.maxCount)") // Send to analytics, crash reporter, etc. }, onUpdate: dashboard.refreshUI // drives the on-screen overlay ) #endif return true } ``` -------------------------------- ### Setup LifetimeTracker with Leak Detection Callback (Swift) Source: https://github.com/krzysztofzablocki/lifetimetracker/blob/master/README.md Configures LifetimeTracker with a closure to be executed upon detecting a leak. This enables custom handling of leak events, such as logging or triggering alerts. ```swift LifetimeTracker.setup(onLeakDetected: { entity, _ in log.warning("POSSIBLE LEAK ALERT: \(entity.name) - current count: \(entity.count), max count: \(entity.maxCount)") }, onUpdate: LifetimeTrackerDashboardIntegration(visibility: .alwaysVisible, style: .bar).refreshUI) ``` -------------------------------- ### Dangerfile for Lifetime Tracking Checks Source: https://github.com/krzysztofzablocki/lifetimetracker/blob/master/README.md Integrate LifetimeTracker with Danger by adding checks to your Dangerfile. This example demonstrates how to ensure modified Views implement `LifetimeTrackable`. ```ruby # # ** FILE CHECKS ** # Checks for certain rules and warns if needed. # Some rules can be disabled by using // danger:disable rule_name # # Rules: # - Check if the modified file is a View and doesn't implement LifetimeTrackable (lifetime_tracking) ``` -------------------------------- ### Setup LifetimeTracker with Leak Detection Callback (Objective-C) Source: https://github.com/krzysztofzablocki/lifetimetracker/blob/master/README.md Configures LifetimeTracker to execute a block of code when a potential memory leak is detected. This allows for custom logging or reporting of leak information. ```objective-c [LifetimeTracker setupOnLeakDetected:^(Entry * entry, EntriesGroup * group) { NSLog(@"POSSIBLE LEAK ALERT: %@ - current count %li, max count %li", entry.name, (long)entry.count, (long)entry.maxCount); } onUpdate:^(NSDictionary * groups) { [dashboardIntegration refreshUIWithTrackedGroups: groups]; }]; ``` -------------------------------- ### Configure LifetimeTracker with Grouping (Swift) Source: https://github.com/krzysztofzablocki/lifetimetracker/blob/master/README.md Demonstrates how to group tracked objects using `groupName` and optionally override the group's maximum count with `groupMaxCount`. This is useful for managing related objects that have individual limits but a combined constraint. ```swift // DetailPage: UIViewController // VideoDetailPage: DetailItem LifetimeConfiguration(maxCount: 3, groupName: "Detail Page") // ImageDetailPage: DetailItem LifetimeConfiguration(maxCount: 3, groupName: "Detail Page") => Group warning if 7 DetailPage objects are alive // VideoDetailPage: DetailItem LifetimeConfiguration(maxCount: 3, groupName: "Detail Page", groupMaxCount: 3) // ImageDetailPage: DetailItem LifetimeConfiguration(maxCount: 3, groupName: "Detail Page", groupMaxCount: 3) => Group warning if 4 DetailPage object are alive ``` -------------------------------- ### Add LifetimeTracker to Package.swift Source: https://github.com/krzysztofzablocki/lifetimetracker/blob/master/README.md Integrate LifetimeTracker into your project by adding it to the dependencies in your Package.swift file. This ensures the library is available for use. ```swift dependencies: [ .package(url: "https://github.com/krzysztofzablocki/LifetimeTracker.git", .upToNextMajor(from: "1.8.0")) ] ``` -------------------------------- ### Configure LifetimeTracker Dashboard Integration Source: https://context7.com/krzysztofzablocki/lifetimetracker/llms.txt Configure the visual overlay for LifetimeTracker. Use `Style` to control widget shape and `Visibility` to manage appearance. Custom text colors can match your app's design system. The instance exposes `refreshUI(trackedGroups:)` as the `UpdateClosure` passed to `LifetimeTracker.setup`. ```swift import LifetimeTracker // Full Swift configuration let dashboard = LifetimeTrackerDashboardIntegration( visibility: .visibleWithIssuesDetected, style: .circular, textColorForNoIssues: UIColor(named: "brandGreen")!, textColorForLeakDetected: UIColor(named: "brandRed")! ) LifetimeTracker.setup(onUpdate: dashboard.refreshUI) // Swap styles at runtime (e.g. based on a debug settings toggle) dashboard.style = .bar // Change visibility at runtime dashboard.visibility = .alwaysVisible // Update closure can be replaced after setup (e.g. swap dashboards) LifetimeTracker.configure(updateClosure: dashboard.refreshUI) ``` ```objc // Objective-C equivalent LifetimeTrackerDashboardIntegration *dashboard = [LifetimeTrackerDashboardIntegration new]; [dashboard setVisibleWhenIssueDetected]; // .visibleWithIssuesDetected [dashboard useBarStyle]; // .bar [LifetimeTracker setupOnUpdate:^(NSDictionary *groups) { [dashboard refreshUIWithTrackedGroups:groups]; }]; // Change visibility later [dashboard setAlwaysVisible]; [dashboard useCircularStyle]; ``` -------------------------------- ### Swift: Configure Lifetime Tracking Rules with LifetimeConfiguration Source: https://context7.com/krzysztofzablocki/lifetimetracker/llms.txt LifetimeConfiguration defines tracking rules per class. Use initializers for standalone types, grouped types (sum of member maxCounts), or groups with an explicit override (groupMaxCount). ```swift import LifetimeTracker // 1. Standalone — no group class NetworkManager: LifetimeTrackable { class var lifetimeConfiguration: LifetimeConfiguration { return LifetimeConfiguration(maxCount: 1) // only 1 NetworkManager allowed } init() { trackLifetime() } } // 2. Grouped — group maxCount = sum of member maxCounts (3+3 = 6) class VideoDetailPage: UIViewController, LifetimeTrackable { class var lifetimeConfiguration: LifetimeConfiguration { return LifetimeConfiguration(maxCount: 3, groupName: "Detail Pages") } override init(nibName: String?, bundle: Bundle?) { super.init(nibName: nibName, bundle: bundle); trackLifetime() } required init?(coder: NSCoder) { super.init(coder: coder); trackLifetime() } } class ImageDetailPage: UIViewController, LifetimeTrackable { class var lifetimeConfiguration: LifetimeConfiguration { return LifetimeConfiguration(maxCount: 3, groupName: "Detail Pages") } override init(nibName: String?, bundle: Bundle?) { super.init(nibName: nibName, bundle: bundle); trackLifetime() } required init?(coder: NSCoder) { super.init(coder: coder); trackLifetime() } // Group warns when > 6 total Detail Pages are alive } // 3. Grouped with override — group max is 3, regardless of per-member limits class AudioDetailPage: UIViewController, LifetimeTrackable { class var lifetimeConfiguration: LifetimeConfiguration { return LifetimeConfiguration(maxCount: 3, groupName: "Detail Pages", groupMaxCount: 3) // Group warns when > 3 total Detail Pages alive, even though each member allows 3 } override init(nibName: String?, bundle: Bundle?) { super.init(nibName: nibName, bundle: bundle); trackLifetime() } required init?(coder: NSCoder) { super.init(coder: coder); trackLifetime() } } // Dynamic maxCount change — reflected immediately on next alloc/dealloc VideoDetailPage.lifetimeConfiguration.maxCount = 5 ``` -------------------------------- ### Check Swift Files for Lifetime Tracking Rules Source: https://github.com/krzysztofzablocki/lifetimetracker/blob/master/README.md This script iterates through modified and added Swift files, checking for compliance with lifetime tracking rules. It skips files with disabled rules and specific file types. It warns if `trackLifetime()` is missing in initializers for `LifetimeTrackable` types. ```ruby files_to_check = (git.modified_files + git.added_files).uniq (files_to_check - %w(Dangerfile)).each do |file| next unless File.file?(file) # Only check inside swift files next unless File.extname(file).include?(".swift") # Will be used to check if we're inside a comment block. is_comment_block = false # Collects all disabled rules for this file. disabled_rules = [] filelines = File.readlines(file) filelines.each_with_index do |line, index| if is_comment_block if line.include?("*/") is_comment_block = false end elsif line.include?("/*") is_comment_block = true elsif line.include?("danger:disable") rule_to_disable = line.split.last disabled_rules.push(rule_to_disable) else # Start our custom line checks # e.g. you could do something like check for methods that only call the super class' method #if line.include?("override") and line.include?("func") and filelines[index+1].include?("super") and filelines[index+2].include?("}") # warn("Override methods which only call super can be removed", file: file, line: index+3) end end end # Only continue checks for Lifetime Trackable types next unless (File.basename(file).include?("ViewModel") or File.basename(file).include?("ViewController") or File.basename(file).include?("View.swift")) and !File.basename(file).include?("Node") and !File.basename(file).include?("Tests") and !File.basename(file).include?("FlowCoordinator") if disabled_rules.include?("lifetime_tracking") == false if File.readlines(file).grep(/LifetimeTrackable/).any? fail("You forgot to call trackLifetime() from your initializers in " + File.basename(file, ".*") + " (lifetime_tracking)") unless File.readlines(file).grep(/trackLifetime()/).any? else warn("Please add support for LifetimeTrackable to " + File.basename(file, ".*") + " . (lifetime_tracking)") end markdown("- [ ] I've verified that showing and hiding " + File.basename(file, ".*") + " doesn't surface any [LifetimeTracker](https://github.com/krzysztofzablocki/LifetimeTracker) issues") end end ``` -------------------------------- ### Swift: Track Class Instance Lifetimes with LifetimeTrackable Source: https://context7.com/krzysztofzablocki/lifetimetracker/llms.txt Conform to LifetimeTrackable and call trackLifetime() in every init. The library automatically decrements the counter on deallocation. Warnings are fired if instance count exceeds maxCount. ```swift import LifetimeTracker // --- Swift --- class HomeViewController: UIViewController, LifetimeTrackable { // Exactly ONE HomeViewController should be alive at a time class var lifetimeConfiguration: LifetimeConfiguration { return LifetimeConfiguration(maxCount: 1, groupName: "ViewControllers") } override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) trackLifetime() // ← call in EVERY init } required init?(coder: NSCoder) { super.init(coder: coder) trackLifetime() } } class FeedViewModel: LifetimeTrackable { class var lifetimeConfiguration: LifetimeConfiguration { return LifetimeConfiguration(maxCount: 1, groupName: "ViewModels") } init() { trackLifetime() } } // Usage — the tracker warns when two HomeViewControllers are alive simultaneously let vc1 = HomeViewController() // count: 1/1 → OK let vc2 = HomeViewController() // count: 2/1 → ⚠️ LEAK reported ``` -------------------------------- ### Objective-C: Track Class Instance Lifetimes with LifetimeTrackable Source: https://context7.com/krzysztofzablocki/lifetimetracker/llms.txt Conform to LifetimeTrackable and call trackLifetime() in every init. The library automatically decrements the counter on deallocation. Warnings are fired if instance count exceeds maxCount. ```objc // --- Objective-C --- @import LifetimeTracker; @interface ProfileViewController () @end @implementation ProfileViewController + (LifetimeConfiguration *)lifetimeConfiguration { return [[LifetimeConfiguration alloc] initWithMaxCount:1 groupName:@"ViewControllers"]; } - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { [self trackLifetime]; // ← call in every init } return self; } @end ``` -------------------------------- ### Danger Integration for Automated PR Checks Source: https://context7.com/krzysztofzablocki/lifetimetracker/llms.txt This Dangerfile snippet warns when a modified ViewController/ViewModel/View file does not conform to `LifetimeTrackable`, and fails the build when a conforming type forgets to call `trackLifetime()`. It also adds a per-file manual verification checkbox to each PR. ```ruby # Dangerfile files_to_check = (git.modified_files + git.added_files).uniq (files_to_check - %w(Dangerfile)).each do |file| next unless File.file?(file) && File.extname(file) == ".swift" # Only check key actor types next unless File.basename(file).match?(/ViewModel|ViewController|View.swift/) next if File.basename(file).match?(/Node|Tests|FlowCoordinator/) disabled_rules = File.readlines(file).select { |l| l.include?("danger:disable") } .map(&:split).map(&:last) next if disabled_rules.include?("lifetime_tracking") if File.readlines(file).grep(/LifetimeTrackable/).any? fail("Forgot to call trackLifetime() in #{File.basename(file, '.*')}") \ unless File.readlines(file).grep(/trackLifetime()/).any? else warn("Please add LifetimeTrackable to #{File.basename(file, '.*')}") end markdown("- [ ] Verified that showing/hiding #{File.basename(file, '.*')} " \ "doesn't surface any [LifetimeTracker](https://github.com/krzysztofzablocki/LifetimeTracker) issues") end ``` -------------------------------- ### Track Lifetime of a Swift Class Source: https://github.com/krzysztofzablocki/lifetimetracker/blob/master/README.md Conform to `LifetimeTrackable` and call `trackLifetime()` in the init method of your Swift class to enable memory tracking. Configure `lifetimeConfiguration` to set limits and group names. ```swift class SectionFrontViewController: UIViewController, LifetimeTrackable { class var lifetimeConfiguration: LifetimeConfiguration { return LifetimeConfiguration(maxCount: 1, groupName: "VC") } override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) /// ... trackLifetime() } } ``` -------------------------------- ### Track Lifetime of an Objective-C Class Source: https://github.com/krzysztofzablocki/lifetimetracker/blob/master/README.md Implement `LifetimeTrackable` protocol and call `[self trackLifetime]` in the init method of your Objective-C class. Use `lifetimeConfiguration` to define tracking parameters like `maxCount` and `groupName`. ```objectivec @import LifetimeTracker; @interface SectionFrontViewController() @implementation SectionFrontViewController +(LifetimeConfiguration *)lifetimeConfiguration { return [[LifetimeConfiguration alloc] initWithMaxCount:1 groupName:@"VC"]; } - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { /// … [self trackLifetime]; } return self; } @end ``` -------------------------------- ### Inspect LifetimeTracker State Programmatically Source: https://context7.com/krzysztofzablocki/lifetimetracker/llms.txt The tracker exposes its full state through the `onUpdate` closure as `[String: LifetimeTracker.EntriesGroup]`. Each `EntriesGroup` holds a dictionary of `Entry` objects keyed by fully-qualified type name. Both expose a `lifetimeState` property (`.valid` / `.leaky`) and raw count/maxCount values. This API can be used to write UI integration tests that assert no leaks exist at the end of a test scenario. ```swift import LifetimeTracker import XCTest class MemoryLeakIntegrationTests: XCTestCase { func testNoLeaksAfterDismissingDetailScreen() { // Setup tracker with a custom closure that captures state var capturedGroups: [String: LifetimeTracker.EntriesGroup] = [: ] LifetimeTracker.setup { groups in capturedGroups = groups } // ... present and dismiss detail screen ... // Inspect groups programmatically for (groupName, group) in capturedGroups { XCTAssertEqual( group.lifetimeState, .valid, "Group '\(groupName)' has \(group.count) instances (max \(group.maxCount))" ) for (entryName, entry) in group.entries { XCTAssertLessThanOrEqual( entry.count, entry.maxCount, "\(entryName): \(entry.count) alive, max \(entry.maxCount). " + "Pointers: \(entry.pointers.joined(separator: ", "))" ) } } // The built-in accessibility identifier for UI test automation // XCUIApplication().staticTexts["LifetimeTracker.summaryLabel"].label == "No issues found" } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.