Sobes.tech
Middle

Kako sprečavate curenje memorije u vašim projektima?

sobes.tech АИ

Одговор од АИ

Koristim nekoliko pristupa:

  1. ARC (Automatic Reference Counting): To je glavni mehanizam za upravljanje memorijom u Swiftu i Objective-C. Automatski broji reference na objekte i oslobađa ih kada broj referenci padne na nulu.
  2. Izbegavanje ciklusa sa jakim referencama: Ovo je najčešći uzrok curenja memorije. Koristim weak ili unowned reference za prekidanje ciklusa. Najčešće se dešava pri radu sa delegatima i zatvaranjima.
  3. Alati za profilisanje: Redovno koristim alate iz Xcode, kao što su Instruments (Allocator, Leaks), za otkrivanje mesta curenja.
  4. Provera zatvaranja: Pažljivo proveravam zatvaranja, posebno pri hvatanju self, koristeći liste hvatanja [weak self] ili [unowned self].
  5. Odjavljivanje od obaveštenja: Odjavljujem se od NotificationCenter i posmatrača KVO pri uništenju objekata.
  6. Uklanjanje posmatrača i tajmera: Isključujem i nuliram invalidate tajmere i uklanjam posmatrače kada više nisu potrebni.
  7. Rad sa resursima: Ispravno upravljam resursima kao što su fajlovi, soketi i baze podataka, pravovremeno ih zatvarajući i oslobađajući.
  8. Recenzije koda: Redovno vršim revizije koda, uključujući s ciljem otkrivanja potencijalnih problema sa upravljanjem memorijom.

Primer korišćenja [weak self] u zatvaranju:

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

    func fetchData() {
        // Korišćenje weak self za sprečavanje jakog ciklusa
        DispatchQueue.global().async { [weak self] in
            // Simulacija dobijanja podataka
            sleep(1)

            DispatchQueue.main.async {
                // Provera na nil pre korišćenja self
                self?.completionHandler?()
            }
        }
    }
}

class ViewController {
    var fetcher: DataFetcher?

    func setupFetcher() {
        fetcher = DataFetcher()
        fetcher?.completionHandler = {
            // Ovde self sada može biti slab, ako fetcher i dalje postoji
            print("Data fetched in ViewController")
        }
    }

    deinit {
        print("ViewController deinitialized")
    }
}

Primer korišćenja weak za delegata:

protocol DataProcessorDelegate: AnyObject { // AnyObject obezbeđuje referentni tip i sprečava jake cikluse sa vrednosnim tipovima
    func processData(_ data: String)
}

class DataProcessor {
    weak var delegate: DataProcessorDelegate? // Korišćenje weak za delegata

    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")
    }
}