Sobes.tech
Middle

Pastāstiet mums par atmiņas pārvaldību iOS.

sobes.tech AI

Atbilde no AI

iOS izmanto automātisku atmiņas pārvaldību, izmantojot ARC (Automatic Reference Counting). ARC automātiski atbrīvo objektus, kad tiem vairs nav atsauces:

Galvenās koncepcijas:

  • Stipra atsauce: Palielina atsauces skaitītāju uz objektu. Objekts netiks atbrīvots, kamēr ir stipras atsauces.
  • Vāja atsauce: Nepalielina atsauces skaitītāju. Izmanto, lai novērstu stipro atsauču ciklus. Atsauce uz objektu, kas var tikt atbrīvots. Ja objekts tiek atbrīvots, vāja atsauce kļūst par nil.
  • Nepārtraukta atsauce: Līdzīga vājai, bet neparādās nil objekta atbrīvošanas brīdī. Izmanto, ja objekts vienmēr ir pieejams vai tam ir ilgāks dzīves cikls. Nepārtraukta atsauce neparādās nil atbrīvojot objektu. Mēģinot piekļūt atbrīvotam objektam caur nepārtrauktu atsauci, rodas izņēmums.

Stipro atsauču cikli (Retain Cycles): rodas, kad divi vai vairāki objekti ir stipri saistīti viens ar otru, neļaujot tiem tikt atbrīvotiem. To risina ar vājām vai nepārtrauktām atsaucēm.

Piemērs:

class Person {
    let name: String
    var apartment: Apartment?

    init(name: String) {
        self.name = name
        print("\(name) sāk darboties")
    }

    deinit {
        print("\(name) beidz darboties")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // Vāja atsauce, lai novērstu ciklu

    init(unit: String) {
        self.unit = unit
        print("Apartments \(unit) sāk darboties")
    }

    deinit {
        print("Apartments \(unit) beidz darboties")
    }
}

var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john // Šeit rodas cikls

john = nil
unit4A = nil
// Deinitializācijas metodes netiek izsauktas cikla dēļ

Risinājums ar weak:

class Person {
    let name: String
    var apartment: Apartment?

    init(name: String) {
        self.name = name
        print("\(name) sāk darboties")
    }

    deinit {
        print("\(name) beidz darboties")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // Vāja atsauce, lai novērstu ciklu

    init(unit: String) {
        self.unit = unit
        print("Apartments \(unit) sāk darboties")
    }

    deinit {
        print("Apartments \(unit) beidz darboties")
    }
}

var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil
unit4A = nil
// Abi objekti tiek pareizi atbrīvoti

Nepārtraukta vs Vāja:

  • Izmanto weak, ja atsauce var kļūt par nil (objekts var tikt atbrīvots pirmais)
  • Izmanto unowned, ja atsauce vienmēr būs ar vērtību (objekts, uz kuru atsaucas, ir ar tādu pašu vai ilgāku dzīves ciklu)

Aizvērumi (Closures) un cikli:

Aizvērumi var iekļaut objektu atsauces, radot stiprus ciklus. To risina ar capture list.

Piemērs:

class HTMLElement {
    let name: String
    let text: String?

    lazy var asHTML: () -> String = {
        [weak self] in // Ņemot `self` vājo atsauci
        guard let self = self else {
            return ""
        }
        var html = "<\(self.name)"
        if let text = self.text {
            html += ">\(text)</\(self.name)>"
        } else {
            html += " />"
        }
        return html
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

    deinit {
        print("\(name) beidz darboties")
    }
}

var paragraph: HTMLElement? = HTMLElement(name: "p", text: "sveiki, pasaule")
print(paragraph!.asHTML())

paragraph = nil
// Objekts ir atbrīvots

Atmiņas problēmu labošana:

  • Memory Graph Debugger: Xcode ļauj vizualizēt objektu saites un identificēt ciklus
  • Instruments (Allocations, Leaks): Uzrauga atmiņas sadali un atbrīvošanu, meklē zaudējumus.