11. Memento va Iterator: Form Snapshots va OOM Crashesiz Stream
🏛️ iOS Design Patterns — Mukammal Enterprise & Architecture Qo‘llanma
11. Behavioral: Memento va Iterator Pattern
"Agar foydalanuvchi 20 ta maydondan iborat anketani to'ldirayotganda kutilmaganda ilovadan chiqib ketsa va qayta kirganda hamma narsa o'chib ketganini ko'rsa — u ilovani o'chirib tashlaydi. Memento inkapsulyatsiyani buzmasdan holatni 'suratga' oladi. Iterator esa millionlab yozuvlarni RAM ni portlatmasdan oqimda o'qish imkonini beradi."
1. Memento Pattern: Obyekt Holatini Saqlash va Tiklash
Memento (Yodgorlik / Snapshot) — bu obyektning ichki maxfiy ma'lumotlarini (Encapsulation) tashqi dunyoga oshkor qilmagan holda, uning o'sha lahzadagi holatini saqlab qolish va kerak bo'lganda o'tmishdagi shu holatga to'liq qaytarish imkonini beruvchi pattern.
sequenceDiagram
autonumber
participant Form as RegistrationForm (Originator)
participant Caretaker as DraftManager (Caretaker)
Note over Form: Foydalanuvchi ma'lumot kiritmoqda...
Form->>Form: makeSnapshot() -> FormMemento
Form->>Caretaker: save(memento) (Diskka yozildi)
Note over Form: 💥 Ilova yopildi yoki xotiradan o'chirildi!
Note over Form: Yangi seans boshlandi...
Caretaker->>Form: restore(memento)
Note over Form: Barcha maydonlar 100% tiklandi!
2. Real Swift 6 Kodi: Anketani Saqlovchi Memento
Swift'da Codable protokoli Memento patternini amalga oshirishning eng toza va zamonaviy usulidir:
import Foundation
// 1. Originator (Holati saqlanadigan asosiy obyekt)
public final class JobApplicationForm {
public var fullName: String = ""
public var expectedSalary: Int = 0
public var skills: [String] = []
public init() {}
// Memento (O'sha lahzadagi holat surati)
public struct Memento: Codable, Sendable {
fileprivate let name: String
fileprivate let salary: Int
fileprivate let skillsList: [String]
fileprivate let timestamp: Date
}
/// Hozirgi holatni suratga olish
public func createSnapshot() -> Memento {
return Memento(
name: fullName,
salary: expectedSalary,
skillsList: skills,
timestamp: Date()
)
}
/// Eski suratdan holatni qayta tiklash
public func restore(from memento: Memento) {
self.fullName = memento.name
self.expectedSalary = memento.salary
self.skills = memento.skillsList
print("✅ Forma tiklandi! (Saqlangan vaqti: \(memento.timestamp))")
}
}
// 2. Caretaker (Suratlarni diskda saqlovchi)
public final class DraftManager {
private let userDefaults = UserDefaults.standard
private let draftKey = "job_application_draft"
public func saveDraft(_ memento: JobApplicationForm.Memento) {
if let encoded = try? JSONEncoder().encode(memento) {
userDefaults.set(encoded, forKey: draftKey)
}
}
public func loadDraft() -> JobApplicationForm.Memento? {
guard let data = userDefaults.data(forKey: draftKey),
let memento = try? JSONDecoder().decode(JobApplicationForm.Memento.self, from: data) else {
return nil
}
return memento
}
}
3. Iterator Pattern: Millionlab Yozuvlarni RAM ni To'ldirmasdan O'qish
Iterator — bu to'plamning (Collection, List, Tree) ichki tuzilishini oshkor qilmasdan, uning elementlarini birma-bir ketma-ket aylanib chiqish (Traverse) imkonini beruvchi pattern.
flowchart LR
Source["Og'ir 500 MB CSV Fayl\n(1,000,000 ta qator)"] --> Iterator["LargeFileIterator\n(IteratorProtocol)"]
Iterator -->|"next() chaqirilganda"| RAM["Faqat 1 ta qator RAM'ga yuklanadi\n(Xotira sarfi: atigi 2 KB!)"]
RAM --> Worker["Qayta ishlovchi prosessor"]
style Source fill:#251014,stroke:#f87171,stroke-width:1px
style Iterator fill:#131720,stroke:#bef264,stroke-width:2px
style RAM fill:#0d1f14,stroke:#4ade80,stroke-width:1px
Swift'ning IteratorProtocol va Sequence:
Agar siz 1 millionta qatorni birdan lines = try String(contentsOf: file).components(separatedBy: "\n") qilib o'qisangiz — ilovangiz Jetsam Out-Of-Memory Crash bilan o'ladi! Iterator esa elementlarni faqat so'ralgandagina (Lazy Streaming) bittalab yuklaydi:
import Foundation
public struct InfiniteIDGenerator: Sequence, IteratorProtocol {
private var currentID: Int = 1
public mutating func next() -> Int? {
let id = currentID
currentID += 1
return id
}
}
// Ishlatilishi:
var generator = InfiniteIDGenerator()
print(generator.next()!) // 1
print(generator.next()!) // 2
print(generator.next()!) // 3
4. Interaktiv Savol-Javob (Self-Check Quiz)
<details> <summary><b>1-Savol: Memento va Command (Undo/Redo) o'rtasida qanday bog'liqlik bor?</b> (Yechimni ko'rish uchun bosing)</summary>
Tahlil va Yechim: Ular juda ko'p hollarda birga ishlatiladi! Command obyekti biror amalni bajarishdan oldin Originator'dan createSnapshot() orqali Memento olib, o'zining ichida saqlab qo'yadi. Agar foydalanuvchi "Undo" qilsa, Command o'sha saqlab qo'yilgan Mementoni Originator'ga qaytaradi (restore(memento)). </details>
<details> <summary><b>2-Savol: Swift'dagi 'for item in items' sikli qaysi pattern asosida ishlaydi?</b> (Yechimni ko'rish uchun bosing)</summary>
Tahlil va Yechim: Bu 100% Iterator Patternidir! Swift tili har qanday Sequence ni ko'rganda, orqa fonda uning makeIterator() metodini chaqiradi va while let item = iterator.next() siklini yurgizadi. </details>
5. Amaliy Topshiriq (Senior Challenge)
UserPreferencesOriginator sinfini quring:
- Unda
theme: String,fontSize: Double,notificationsEnabled: Boolmaydonlari bo'lsin. - Foydalanuvchi sozlamalarni o'zgartirganda "Oldingi holatga qaytish" (Revert) imkonini beruvchi Memento arxitekturasini yarating!