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 - რომ run loop-ი არ დასრულდეს დაუყოვნებლივ
        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).