Sobes.tech
Middle+

Kada treba koristiti run loop u razvoju iOS?

sobes.tech АИ

Одговор од АИ

Run loop treba koristiti kada je potrebno upravljati ponašanjem niti, omogućavajući joj da čeka na događaje i izvršava odgovarajući kod, umesto da se odmah završava nakon izvršenja zadatka. Ovo je ključno za:

  1. Glavni tok (Main Thread): Run loop glavnog toka obrađuje interakciju sa UIKit/AppKit, korisničke događaje (dodiri, klikovi), tajmere, mrežne događaje i pozive performSelector:withObject:afterDelay:. Bez njega, aplikacija neće moći da reaguje na korisničke radnje i da osvežava UI.

  2. Sekundarne niti: Kada pozadinska nit treba da izvršava asinhrone zadatke, sluša ulazne podatke (npr. sokete), obrađuje poruke iz drugih niti ili koristi tajmere. Tipični scenariji uključuju:

    • Rad sa soketima.
    • Izvršavanje ponovljenih zadataka putem tajmera.
    • Prijem i obrada poruka iz IPC (međuprocesne komunikacije).
    • Održavanje živosti niti za obradu budućih zahteva bez potrebe za stalnim kreiranjem i uništavanjem.

Primer korišćenja run loop-a u sekundarnoj niti može biti održavanje mrežne veze:

// Primer u Swift
class NetworkManager {
    private let networkThread = Thread {
        // Kod za inicijalizaciju mrežne sesije, soketa itd.

        // Dodavanje izvora događaja (npr. soketa ili porta) u run loop
        // CFRunLoopAddSource(CFRunLoopGetCurrent(), source, CFRunLoopMode.defaultMode)

        // Dodavanje tajmera, ako je potrebno
        // CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.defaultMode)

        // Pokretanje run loop-a. On će blokirati nit dok ne primi događaj.
        // .distantFuture - da run loop ne završi odmah
        RunLoop.current.run()

        // Kod za čišćenje nakon završetka run loop-a
        print("Network thread finishing")
    }

    func start() {
        // Korišćenje `start()` umesto `detachNewThreadSelector`
        // moderniji pristup
        networkThread.start()
    }

    // Metod za zaustavljanje run loop-a iz druge niti
    func stop() {
        // Signalizacija run loop-u da se završi
        // CFRunLoopStop(CFRunLoopGetCurrent()) // Ili dodavanje posebnog događaja za obradu
        // run loop obično završava kada nema izvora događaja ili po eksplicitnom pozivu
    }
}

Run loop nije potreban za niti koje izvršavaju jedan zadatak i zatim se završavaju (npr. jednokratne operacije u pozadinskoj niti putem DispatchQueue.global().async). U tim slučajevima dovoljno je koristiti Grand Central Dispatch (GCD).