Sobes.tech
Middle+

Երբ պետք է օգտագործել run loop-ը iOS-ի զարգացման ժամանակ?

sobes.tech AI

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

Run loop պետք է օգտագործել, երբ անհրաժեշտ է կառավարել հոսքի վարքագիծը, թույլ տալով նրան սպասել իրադարձությունների և կատարել համապատասխան կոդը, փոխարենը այն անմիջապես չավարտվել հետո իր գործը կատարելուց։ Սա կարևոր է՝

  1. Հիմնական հոսք (Main Thread): Run loop-ը հիմնական հոսքի մշակում է UIKit/AppKit-ի հետ փոխազդեցությունը, օգտագործողի իրադարձությունները (կծկումներ, սեղմումներ), ժամացույցները, ցանցային իրադարձությունները և performSelector:withObject:afterDelay: կանչերը։ Բան չունենալու դեպքում, հավելվածը չի կարող արձագանքել օգտագործողի գործողություններին և թարմացնել UI-ն։

  2. Երկրորդական հոսքեր: Երբ ֆոնային հոսքը պետք է իրականացնել ասինխրոն գործառույթներ, լսել մուտքային տվյալներ (օրինակ, սոկետներ), մշակել հաղորդագրություններ այլ հոսքերից կամ օգտագործել ժամացույցներ։ Տիպիկ սցենարները ներառում են՝

    • Սոկետների հետ աշխատել։
    • Կրկնվող գործառույթներ իրականացնել ժամացույցով։
    • Ստանալ և մշակել հաղորդագրություններ IPC-ից։
    • Հետաձգել հոսքի կյանքը՝ բարդ պահանջների համար, առանց մշտական ստեղծման և ոչնչացման։

Օրինակ՝ օգտագործելով run loop երկրորդական հոսքում՝ կարող է լինել ցանցային կապի պահպանումը՝

// Swift-ում օրինակ
class NetworkManager {
    private let networkThread = Thread {
        // Կոդ՝ ցանցային սեսիայի, սոկետների և այլն։

        // Ավելացնել իրադարձության աղբյուր (օրինակ, սոկետ կամ պորտ) run loop-ին
        // CFRunLoopAddSource(CFRunLoopGetCurrent(), source, CFRunLoopMode.defaultMode)

        // Ավելացնել ժամացույց, եթե անհրաժեշտ է
        // CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.defaultMode)

        // Սկսել run loop-ը։ Այն կլրացնի հոսքը, մինչև ստանա իրադարձություն։
        // .distantFuture - որպեսզի չավարտվի անմիջապես
        RunLoop.current.run()

        // Մաքրման կոդ՝ run loop-ի ավարտից հետո
        print("Network thread finishing")
    }

    func start() {
        // Օգտագործել `start()` փոխարեն `detachNewThreadSelector`
        // ավելի արդիական մոտեցում
        networkThread.start()
    }

    func stop() {
        // Սիգնալիզացնել run loop-ին, որ պետք է ավարտվի
        // CFRunLoopStop(CFRunLoopGetCurrent()) // կամ ավելացնել հատուկ իրադարձություն
        // run loop-ը սովորաբար ավարտվում է, երբ չունի իրադարձության աղբյուրներ կամ հստակ կանչով
    }
}

Run loop չի անհրաժեշտ այն հոսքերի համար, որոնք կատարում են մեկ գործառույթ և հետո ավարտվում (օրինակ, միանվագ գործողություններ ֆոնային հոսքում՝ DispatchQueue.global().async միջոցով): Այդ դեպքերում բավական է օգտագործել Grand Central Dispatch (GCD):