Sobes.tech
Middle+

Millal kasutada run loopi iOS arenduses?

sobes.tech AI

Vastus AI-lt

Run loop tuleks kasutada, kui on vaja hallata niidi käitumist, võimaldades tal oodata sündmusi ja täita vastavat koodi, selle asemel et see kohe lõpetaks oma ülesande täitmise järel. See on kriitiline:

  1. Peamine niit (Main Thread): Run loop peamise niidi töödleb suhtlust UIKit/AppKit-iga, kasutaja sündmusi (puudutused, klõpsud), taimerid, võrgusündmused ja performSelector:withObject:afterDelay:-i väljakutseid. Ilma selleta ei saa rakendus reageerida kasutaja tegevustele ega uuendada kasutajaliidest.

  2. Teisese niidid: Kui taustaniit peab täitma asünkroonseid ülesandeid, kuulama sisendandmeid (näiteks sokette), töötlema sõnumeid teistest niitidest või kasutama taimerid. Tüüpilised stsenaariumid hõlmavad:

    • Soketitega töötamine.
    • Korduvate ülesannete täitmine taimeri abil.
    • Sõnumite vastuvõtt ja töötlemine IPC-st.
    • Niidi elususe säilitamine tulevaste päringute jaoks ilma selle pideva loomise ja hävitamiseta.

Näide run loopi kasutamisest teises niidis võib olla võrguside säilitamine:

// Näide Swiftis
class NetworkManager {
    private let networkThread = Thread {
        // Kood võrguseansi, sokettide jms initsialiseerimiseks

        // Allika lisamine (näiteks sokett või port) run loopi
        // CFRunLoopAddSource(CFRunLoopGetCurrent(), source, CFRunLoopMode.defaultMode)

        // Taimeri lisamine, kui vaja
        // CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.defaultMode)

        // Run loopi käivitamine. See blokeerib niidi, kuni saab sündmuse.
        // .distantFuture – et run loop ei lõpetaks kohe
        RunLoop.current.run()

        // Puhastuskood pärast run loopi lõpetamist
        print("Network thread finishing")
    }

    func start() {
        // Kasutada `start()` asemel `detachNewThreadSelector`
        // kaasaegsem lähenemine
        networkThread.start()
    }

    func stop() {
        // Signaal run loopile, et see peaks lõpetama
        // CFRunLoopStop(CFRunLoopGetCurrent()) // või lisada eriline sündmus
        // run loop lõpeb tavaliselt, kui tal pole sündmuse allikaid või kui seda otseselt kutsutakse
    }
}

Run loop ei ole vajalik nende niitide jaoks, mis täidavad ühe ülesande ja seejärel lõpetavad (näiteks ühekordsed toimingud taustaniidis DispatchQueue.global().async kaudu). Sellistel juhtudel piisab Grand Central Dispatchi (GCD) kasutamisest.