user1619290
user1619290

Reputation: 31

How to run for loop in background thread swift

i am using for loop to iterate photos and adding it to core data but it blocks UI thread while in process I am using

self.fetchResult = PHAsset.fetchAssets(with: .image, options: allPhotosOptions)

DispatchQueue.main.async { }

for i in 0 ..< self.fetchResult.count {
    GenericCoreData.saveEntity("Details")
}

Upvotes: 1

Views: 5817

Answers (2)

Lance Samaria
Lance Samaria

Reputation: 19592

I had the same question. In my situation the loop was locking the main thread. It wasn't a simple count from 1 -10, on every iteration two other internal functions were running so the UI was blocked. I needed to run it in the background and then when it finished update the UI on the main thread.

I used a background task from this answer and added a loop to it

1- Create an extension on DispatchQueue and add this static method to it

extension DispatchQueue {

    static func myBackground(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) {
        DispatchQueue.global(qos: .background).async {
            background?()
            if let completion = completion {
                DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: {
                    completion()
                })
            }
        }
    }
}

2- Call the above method and add your loop inside the first part:

DispatchQueue.myBackground(background: {

    // do something in background like run a loop in the background

    for num in 1..<10 {

        // run function 1
        // run function 2 after function 1 is finished
    }

}, completion:{

    // when background job finished, do something in main thread

})

Another method you can also use is a DispatchGroup

let dispatchGroup = DispatchGroup()

for num in 1..<10 {

    // ** call this to enter the group **
    dispatchGroup.enter()

    // run function 1
    // run function 2 after function 1 is finished and call **dispatchGroup.leave()** to exit the group when function 2 is finished
    // make sure to call **dispatchGroup.leave()** or this will never end
}

dispatchGroup.notify(queue: .global(qos: .background)) {

    DispatchQueue.main.async { [weak self] in

        // when background job finished, do something in main thread
    }
}

Upvotes: 1

Salman Ghumsani
Salman Ghumsani

Reputation: 3657

You can use DispatchQueue like this.

DispatchQueue.global(qos: .background).async {
    for i in 0 ..< self.fetchResult.count {
       GenericCoreData.saveEntity("Details")
    }
}

This will help you more.

Upvotes: 3

Related Questions