Dispatchqueue and SVProgressHUD in swift

1.3k Views Asked by At

I have been designing an app that analyzes lines of text, and I want to use SVProgressHUD to show progress of it.

This is my code:

let total = text.count
for line in text{
    count = count + 1
    DispatchQueue.global(pos: .background).async{
        //Analyzing line
        DispatchQueue.main.async{
            SVProgressHUD.showProgress(count/total)
        }
    }
}

The analyzing works, and the HUD shows properly, when the count reaches total, the process gets stuck, and SVProgressHUD stops at max status, and the program stops. What is the issue with the program?

Am I using Dispatchqueue wrong? Do I have to call something other to free the background process or something?

I have tried exchanging //Analyzing line and SVProgressHUD.show..., but it still doesn't work. I initially used SVProgress within the loop without the dispatchqueue, but then the progress hud moves only after the analyzation(full loop) has been completed, which is a problem.

Any help would be appreciated.

Thank you.

2

There are 2 best solutions below

0
On BEST ANSWER

Try using this code. It does not use loop but implements recursive calls to a function for processing your string data.

func processLines() {
    SVProgressHUD.showProgress(0)

    // sample data
    var text = Array("abcdefghijklmnop")
    var lines : [Line] = []
    let count : [Int] = Array(0..<text.count)
    count.forEach({ pos in lines.append(Line(char: text[pos])) })
    var currentIndex : Int = 0

    func processLine(at index: Int) {

        DispatchQueue.global(qos: .background).async{
            //Analyzing line
            let line = lines[index]
            print("Processing Line CHAR: \(line.char)")

            DispatchQueue.main.async{
                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                    guard currentIndex < lines.count-1 else {
                        SVProgressHUD.showProgress(1)
                        return
                    }
                    currentIndex += 1
                    startLineProces(at: currentIndex)
                }
            }
        }

    }

    func startLineProces(at index: Int) {
        processLine(at: index)
        SVProgressHUD.showProgress(Float(index) / Float(lines.count))
    }


    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        startLineProces(at: currentIndex)
    }
}

struct Line {
   var char: Character
   init(char: Character) {
     self.char = char
   }
}
4
On

Use the below string extension to analyse your string. It has a completion block which will return progress as well as status of completion.

extension String {
func analyseString(completion: @escaping (Bool, Float) -> ()) {
    let totalCountOfString = self.count
    for (index, _) in self.enumerated() {
        if index == totalCountOfString - 1 {
            completion(true, Float(index)/Float(totalCountOfString))
        } else {
            completion(false, Float(index)/Float(totalCountOfString))
        }
    }
  }
}

You can call the above method to show your progress as below (maybe on a button click). self.yourString is your input string that you need to analyse.

@IBAction func clicked(_ sender: UIButton) {
    DispatchQueue.main.async {
        self.yourString.analyseString { (isCompleted, progress) in
            if isCompleted {
                SVProgressHUD.dismiss()
                print("Ending")
            } else {
                SVProgressHUD.showProgress(progress, status: "Analysing (\(progress)%)")
            }
        }
    }
}