Sobes.tech
Middle

Prečo sa neodporúča zaťažovať hlavnú vlákno v iOS a aké sú spôsoby, ako tomu predísť?

sobes.tech AI

Odpoveď od AI

Hlavné vlákno je zodpovedné za aktualizáciu používateľského rozhrania a spracovanie udalostí UI. Akékoľvek dlhé operácie (sieťové požiadavky, ťažké výpočty, práca so súbormi) na hlavnom vlákne ho zablokujú, čo povedie k "zamrznutému" UI, nízkej odozve aplikácie a dokonca k jej zrúteniu (watchdog timeout).

Spôsoby, ako sa vyhnúť zaťaženiu hlavného vlákna:

  1. Grand Central Dispatch (GCD): Umožňuje vykonávať úlohy asynchrónne na pozadí pomocou frontov.

    • DispatchQueue.global(): Získanie globálnych pozadíových frontov s rôznou prioritou.
    • DispatchQueue.main: Hlavná fronta na aktualizáciu UI.
    • async { ... }: Asynchrónne vykonanie bloku kódu.
    // vykonanie náročnej úlohy na pozadí
    DispatchQueue.global(qos: .userInitiated).async {
        // náročné výpočty alebo sieťová požiadavka
    
        // aktualizácia UI na hlavnom vlákne
        DispatchQueue.main.async {
            // aktualizovať používateľské rozhranie
        }
    }
    
  2. Operation Queues (Operation & OperationQueue): Vyššia úroveň abstrakcie nad GCD frontami, podporujúca závislosti medzi operáciami, zrušenie a pozastavenie.

    • OperationQueue(): Vytvorenie fronty operácií.
    • Operation: Abstraktná trieda pre úlohy, ktoré možno pridať do fronty.
    • addOperation(_:): Pridanie operácie do fronty.
    let downloadOperation = BlockOperation {
        // stiahnutie dát
    }
    
    let parseOperation = BlockOperation {
        // rozbor dát
    }
    
    // závislosť: rozbor začína po stiahnutí
    parseOperation.addDependency(downloadOperation)
    
    let queue = OperationQueue()
    queue.addOperation(downloadOperation)
    queue.addOperation(parseOperation)
    
  3. Concurrency (async/await): Moderný prístup vo Swift pre asynchrónne programovanie.

    • async: Označuje funkciu ako asynchrónnu.
    • await: Čaká na dokončenie asynchrónnej operácie.
    • Task: Vytvorenie novej konkurenčnej úlohy.
    func fetchData() async throws -> Data {
        let url = URL(string: "https://example.com/data")!
        let (data, _) = try await URLSession.shared.data(from: url)
        return data
    }
    
    func updateUI() {
        Task {
            do {
                let data = try await fetchData()
                // spracovanie dát
                // aktualizácia UI na hlavnom vlákne automaticky
                // (ak je Task vytvorený v hlavnom Actor alebo DispatchQueue.main)
            } catch {
                // spracovanie chyby
            }
        }
    }
    
  4. Actors: Zabraňujú závodom dát pri prístupe z rôznych konkurenčných kontextov, zabezpečujúc exkluzívny prístup k svojmu stavu.

    actor DataStore {
        private var data: [String] = []
    
        func addData(_ item: String) {
            data.append(item)
        }
    
        func getData() -> [String] {
            return data
        }
    }
    
    let store = DataStore()
    
    Task {
        await store.addData("item1")
    }
    

Voľba medzi GCD, Operation Queues a Concurrency závisí od zložitosti úlohy, požadovanej úrovne kontroly a požiadaviek na štruktúru kódu. Concurrency je preferovaný prístup v moderných aplikáciách pre čitateľnosť a bezpečnosť.