Sobes.tech
Junior

Ի՞նչ է փակումը։

sobes.tech AI

Պատասխան AI-ից

Swift- ում փակումը (closure) ինքնաբավ ֆունկցիոնալ բլոկ է ({}), որը կարող է փոխանցվել և օգտագործվել կոդում: Փակումները կարող են բռնել և պահել հղումներ ցանկացած հաստատունների և փոփոխականների դեպի կոնտեքստ, որտեղ դրանք սահմանված են:

Օգտագործման օրինակներ:

  • Ֆունկցիաների արգումենտներ (օրինակ, Completion Handlers)
  • Կոլեկցիաների անցնելու ժամանակ վարքագծի սահմանման համար (օրինակ, օգտագործելով map, filter, reduce, sorted մեթոդները)
  • Կոդի հետաձգված կատարման համար

Սինտաքսիս:

// Հիմնական սինտաքսիս
{ (պարամետրեր) -> վերադարձվողՏիպ in
    արտահայտություններ
}

// Փակման օրինակ, որը ընդունում է Int և վերադարձնում String
let integerToString: (Int) -> String = { (number: Int) -> String in
    return "Թիվը՝ \(number)"
}

Հատկանիշներ:

  • Ավտոմատ բռնում փոփոխականներ (capturing values)
  • Փակման սահմանման հնարավորությունը առանց բացահայտ տիպերի նշման (սինտաքսիկ շաքար)
  • Կրճատ անունների օգտագործում ($0, $1 և այլն)
  • Փակման սինտաքսիս (trailing closure syntax)

Փակման մեջ փոփոխականների բռնում:

Փակումը կարող է բռնել իր շրջապատից փոփոխականներ: Դրա նախնական ձևը՝ բռնումը կատարվում է հղումով: Եթե փակումը օգտագործվում է այն ժամանակ, երբ սկզբնական փոփոխականը դուրս է եկել տեսանելիության տարածքից, փակումը դեռ պահպանում է նրա հասանելիությունը:

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0 // Բացակետային կոնտեքստից փոփոխական
    let incrementer: () -> Int = { // Փակում
        runningTotal += amount // Բռնում է runningTotal և amount
        return runningTotal
    }
    return incrementer
}

let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen()) // Արտածում՝ 10
print(incrementByTen()) // Արտածում՝ 20

Բռնման ցանկեր (Capture Lists):

Օգտագործվում են հստակ նշելու, թե ինչպես պետք է բռնվեն փոփոխականները՝ արժեքով կամ հղումով, ինչպես նաև՝ ուժեղ հղումների ցիկլերը խուսափելու համար:

class MyClass {
    var value = 0

    lazy var myClosure: () -> Void = { [self, value] in // Բռնում self հղումով, value արժեքով
        print("self.value-ի արժեքը՝ \(self.value)")
        print("Բռնված արժեք՝ \(value)")
    }

    deinit {
        print("MyClass օբյեկտը ազատված է")
    }
}

Կարևոր է՝ ուժեղ հղումներից (strong reference cycles) խուսափելու համար օգտագործել [weak self] կամ [unowned self]:

class ViewController {
    var dataFetcher: DataFetcher?

    func fetchData() {
        dataFetcher?.fetch { [weak self] result in // թույլ հղում self-ին
            guard let self = self else { return } // ստուգում՝ արդյոք self-ը գոյություն ունի
            // արդյունքի մշակումը
        }
    }
}

class DataFetcher {
    var completionHandler: ((Result<String, Error>) -> Void)?

    func fetch(completion: @escaping (Result<String, Error>) -> Void) {
        self.completionHandler = completion
        // Ասինխրոն գործողություն...
    }
}