Ինչպես սինխրոնիզացնել տվյալները միջեւ հոսքերի (կոնտեքստի) iOS-ում?
sobes.tech AI
Պատասխան AI-ից
Կանխարգելման համար կարող եք օգտագործել հետևյալ մեխանիզմները:
-
NSLock: Պրիմիտիվ բլոկավորող մյուտեքս:
let lock = NSLock() func doSomething() { lock.lock() // Կրիտիկական հատվածի կոդ lock.unlock() } -
NSRecursiveLock: Թույլ է տալիս մի թելին բազմիցս գրավել բլոկավորումը առանց deadlock-ի:
let recursiveLock = NSRecursiveLock() func recursiveFunction(level: Int) { recursiveLock.lock() if level < 3 { recursiveFunction(level: level + 1) } recursiveLock.unlock() } -
NSCondition: Թույլ է տալիս թելերին սպասել որոշակի պայման, նախքան շարունակել կատարելագործումը:
let condition = NSCondition() var dataAvailable = false func producer() { condition.lock() // Տվյալների արտադրություն dataAvailable = true condition.signal() // Սիգնալ տալ սպասող թելերին condition.unlock() } func consumer() { condition.lock() while !dataAvailable { condition.wait() // Սպասել, մինչև պայմանը կատարվի } // Տվյալների մշակումը dataAvailable = false condition.unlock() } -
NSConditionLock: Մյուտեքս, որը կարող է լինել միայն որոշակի պայման-արժեքի կատարման դեպքում:
let conditionLock = NSConditionLock(condition: 0) let DATA_READY = 1 func producer() { conditionLock.lock(when: 0) // Զավթել, երբ պայմանը 0 է // Տվյալների արտադրություն conditionLock.unlock(withCondition: DATA_READY) // Զավթել և սահմանել պայմանը DATA_READY } func consumer() { conditionLock.lock(when: DATA_READY) // Զավթել, երբ պայմանը DATA_READY է // Տվյալների մշակումը conditionLock.unlock(withCondition: 0) // Զավթել և սահմանել պայմանը 0 } -
Dispatch Queues (GCD): Օգտագործել հերթական dispatch-երը ընդհանուր ռեսուրսներին մուտք գործելու համար:
let serialQueue = DispatchQueue(label: "com.yourapp.serialQueue") var sharedResource = 0 func updateResource() { serialQueue.async { // Մուտք դեպի sharedResource միայն այս հերթում sharedResource += 1 } } -
NSOperationQueue: Կառավարել կախվածությունները և առաջնահերթությունները:
let operationQueue = OperationQueue() var sharedOperationResource = 0 let operation1 = BlockOperation { // Մուտք դեպի sharedOperationResource sharedOperationResource += 1 } operationQueue.addOperation(operation1) -
Actors (Swift 5.5+): Կենտրոնանում են վիճակի մեկուսացման վրա, կանխելով միաժամանակյա մուտքը տարբեր կոնտեքստներից:
actor Counter { private var count = 0 func increment() { count += 1 } func getCount() -> Int { return count } } let counter = Counter() Task { await counter.increment() let currentCount = await counter.getCount() print(currentCount) } -
Core Data Contexts: Տվյալների կոնտեքստների սինխրոնիզացման համար կարելի է օգտագործել հիերարխիկ կոնտեքստներ (հայր-պատուէր) կամ mergeChanges(fromContextDidSaveNotification:):
// Հրամար հիերարխիա (հայր - ֆոնային, զավակ - UI) let privateMoc = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) privateMoc.persistentStoreCoordinator = persistentStoreCoordinator let mainMoc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) mainMoc.parent = privateMoc // mergeChanges օրինակ NotificationCenter.default.addObserver(self, selector: #selector(contextDidSave(_:)), name: .NSManagedObjectContextDidSave, object: nil) @objc func contextDidSave(_ notification: Notification) { guard let savingContext = notification.object as? NSManagedObjectContext else { return } if savingContext != mainMoc { // Եթե պահպանումը տեղի է ունեցել ոչ հիմնական կոնտեքստում mainMoc.perform { mainMoc.mergeChanges(fromContextDidSave: notification) } } } -
Ատոմարային օպերացիաներ: Օգտագործել ատոմարային պրիմիտիվներ (օրինակ,
os/lock.h-ից) պարզ գործողությունների համար:
Ընտրությունը կախված է խնդրի բարդությունից, տվյալների տիպից և պահանջվող կատարողականությունից: Actors և GCD-ը ժամանակակից և նախընտրելի մոտեցումներ են։