Sobes.tech
Middle

Ako predchádzate únikom pamäte vo vašich projektoch?

sobes.tech AI

Odpoveď od AI

Používam niekoľko prístupov:

  1. ARC (Automatic Reference Counting): Je to hlavný mechanizmus správy pamäte v Swift a Objective-C. Automaticky počíta odkazy na objekty a uvoľňuje ich, keď počet odkazov klesne na nulu.
  2. Vyhýbanie sa cyklom silných odkazov: Najčastejšia príčina únikov pamäte. Používam weak alebo unowned odkazy na prerušenie cyklov. Najčastejšie sa to vyskytuje pri práci s delegátmi a uzávermi.
  3. Nástroje profilovania: Pravidelne používam nástroje z Xcode, ako sú Instruments (Allocator, Leaks), na odhalenie miest únikov.
  4. Kontrola uzávierok: Pozorne kontrolujem uzávierky, najmä pri zachytení self, pomocou zoznamov zachytenia [weak self] alebo [unowned self].
  5. Odhlásenie z oznámení: Odhlasujem sa od NotificationCenter a observerov KVO pri zničení objektov.
  6. Odstránenie observerov a časovačov: Odpojujem a nulujem invalidate časovače a odstraňujem observerov, keď už nie sú potrebné.
  7. Práca s prostriedkami: Správne spravujem prostriedky ako sú súbory, sokety a databázy, včas ich zatváram a uvoľňujem.
  8. Recenzie kódu: Pravidelne vykonávam revízie kódu, vrátane s cieľom odhaliť potenciálne problémy s riadením pamäti.

Príklad použitia [weak self] v uzávierke:

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

    func fetchData() {
        // Použitie weak self na prevenciu silného cyklu
        DispatchQueue.global().async { [weak self] in
            // Simulácia získania dát
            sleep(1)

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

class ViewController {
    var fetcher: DataFetcher?

    func setupFetcher() {
        fetcher = DataFetcher()
        fetcher?.completionHandler = {
            // Tu self teraz môže byť slabé, ak fetcher stále existuje
            print("Data fetched in ViewController")
        }
    }

    deinit {
        print("ViewController deinitialized")
    }
}

Príklad použitia weak pre delegáta:

protocol DataProcessorDelegate: AnyObject { // AnyObject zabezpečuje odkazový typ a zabraňuje silným cyklom s hodnotovými typmi
    func processData(_ data: String)
}

class DataProcessor {
    weak var delegate: DataProcessorDelegate? // Použitie weak pre 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")
    }
}