Reputation: 566
View Freezes while data is fetched and displayed. In my understanding fetchBoard()
and initUserInfo()
do not execute in parallel. (As view only loads when fetchBoard()
loads the boards)
I'm concerned if the use of DispatchQueue.main.async
multiple times is freezing the view. Also, How do I make it work smoothly.
class MultipleCardsController2vs2: BaseController, UICollectionViewDataSource , UICollectionViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let repo = GameRepository()
repo.CreateGame(gameID : self.jsonGame.Id , completion: { (jsonGame, err) -> Void in
if(err == ErrorCode.NoError){
DispatchQueue.main.async{
self.jsonGame = jsonGame
}
}
})
//These are the two functions I want these 2 to work in parallel
self.fetchBoard() //Function 1
self.initUserInfo() //Function 2
collectionView.delegate = self
collectionView.dataSource = self
} // .viewDidLoad
func fetchBoard(){
let repo = GameRepository()
self.sortedBoardArr.reserveCapacity(self.BoardArr.count)
let serialQueue = DispatchQueue(label: "serialQueue")
let group = DispatchGroup()
for board in self.jsonGame.boards{
group.enter()
serialQueue.async {
repo.GetBoardInfo(gameID: self.jsonGame.Id, boardID: board , completion : {(response , errorCode ) -> Void in
if errorCode == ErrorCode.NoError{
self.BoardArr.append(response)
group.leave()
}
})
DispatchQueue.main.async{
//Main async - 1
group.wait()
self.sortArr()
self.collectionView.reloadData()
}
}
}
}
func sortArr(){
if self.jsonGame.boards.count == self.BoardArr.count{
for board in self.jsonGame.boards{
for boardarr in self.BoardArr{
if boardarr.id == board{
self.sortedBoardArr.append(boardarr)
}
}
}
}
}
fileprivate func initUserInfo()
{
DispatchQueue.main.async{
//Main async - 2
self.name1.text = self.CurrentUser.UserName
self.imgPlayie1.image = UserManager.GetAvatar(user: self.CurrentUser)
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.jsonGame.boards.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Round2Cell", for: indexPath) as! Round1vs1cell
cell.background.backgroundColor = UIColor(white: 1, alpha: 0.0)
cell = self.populateGameCell(game_res, cell , indexPath)
return cell
}
fileprivate func populateGameCell(_ game_res: Game_Res, _ cell: Round1vs1cell , _ indexPath : IndexPath ) -> Round1vs1cell
{
DispatchQueue.main.async {
//Main async - 3
cell.background.backgroundColor = UIColor(white: 1, alpha: 0.0)
cell.word_1.text = game_res.words[0].word
cell.color_1.image = UIImage(named: "")
cell.life_1.image = UIImage(named: "")
cell.name.text = ""
cell.op_name.text = game_res.master[index].username
cell.timeout_left.image = UIImage(named: "Hourglass.png")
cell.round.text = "Round: \(indexPath.row + 1)"
}
return cell
}
}
Looking for the smooth working and not freezing the view. I'm noob at working with Dispatch. Any help is welcome. Thanks in advance.
Upvotes: 3
Views: 1999
Reputation: 19602
Use notify()
instead of wait()
to not block the main thread.
Playground example:
import PlaygroundSupport
func longRunningTask(completion: () -> Void) {
sleep(1)
completion()
}
func foo(){
let queue = DispatchQueue(label: "myQueue")
let group = DispatchGroup()
let array = [1, 2, 3]
for i in array {
print(i)
group.enter()
queue.async {
longRunningTask {
print("done \(i)")
group.leave()
}
}
}
group.notify(queue: DispatchQueue.main) {
print("done!")
}
}
foo()
PlaygroundPage.current.needsIndefiniteExecution = true
Prints:
1
2
3
done 1
done 2
done 3
done!
Additional Info why you are causing a deadlock can be found in this answer.
Upvotes: 3