Sobes.tech
Middle

Jak předcházíte únikům paměti ve svých projektech?

sobes.tech AI

Odpověď od AI

Používám několik přístupů:

  1. ARC (Automatic Reference Counting): Je to hlavní mechanismus správy paměti ve Swiftu a Objective-C. Automaticky počítá odkazy na objekty a uvolňuje je, když počet odkazů klesne na nulu.
  2. Vyhýbání se cyklům silných odkazů: Nejčastější příčina úniků paměti. Používám weak nebo unowned odkazy k přerušení cyklů. Nejčastěji se to vyskytuje při práci s delegáty a uzávěry.
  3. Nástroje profilování: Pravidelně používám nástroje z Xcode, jako jsou Instruments (Allocator, Leaks), k odhalení míst úniků.
  4. Kontrola uzávěrů: Pečlivě kontroluji uzávěry, zejména při zachycení self, pomocí seznamů zachycení [weak self] nebo [unowned self].
  5. Odhlášení z oznámení: Odhlášení z NotificationCenter a observerů KVO při zničení objektů.
  6. Odstranění observerů a časovačů: Odpojuji a nulují invalidate časovače a odstraňuji observerů, když již nejsou potřeba.
  7. Práce s prostředky: Správně spravuji prostředky, jako jsou soubory, sokety a databáze, včas je zavírám a uvolňuji.
  8. Recenze kódu: Pravidelně provádím revize kódu, včetně s cílem odhalit potenciální problémy s řízením paměti.

Příklad použití [weak self] v uzávěru:

class DataFetcher {
    var completionHandler: (() -> Void)?

    func fetchData() {
        // Použití weak self k prevenci silného cyklu
        DispatchQueue.global().async { [weak self] in
            // Simulace získání dat
            sleep(1)

            DispatchQueue.main.async {
                // Kontrola na nil před použitím self
                self?.completionHandler?()
            }
        }
    }
}

class ViewController {
    var fetcher: DataFetcher?

    func setupFetcher() {
        fetcher = DataFetcher()
        fetcher?.completionHandler = {
            // Zde může být self slabé, pokud fetcher stále existuje
            print("Data fetched in ViewController")
        }
    }

    deinit {
        print("ViewController deinitialized")
    }
}

Příklad použití weak pro delegáta:

protocol DataProcessorDelegate: AnyObject { // AnyObject zajišťuje odkazový typ a zabraňuje silným cyklům s hodnotovými typy
    func processData(_ data: String)
}

class DataProcessor {
    weak var delegate: DataProcessorDelegate? // Použití weak pro delegáta

    func process(_ data: String) {
        delegate?.processData(data)
    }
}

class AnotherViewController: DataProcessorDelegate {
    let processor = DataProcessor()

    init() {
        processor.delegate = self
    }

    func processData(_ data: String) {
        print("Processing data: \(data)")
    }

    deinit {
        print("AnotherViewController deinitialized")
    }
}