值排序不正确

时间:2017-09-07 16:26:15

标签: ios swift

我列出了Textview中最常见的3个单词。然后我通过谷歌翻译翻译了这些单词以使用框架。我想这样做是为了显示我用不同的UILabel列出的这些单词的翻译。 但我有一个问题。当我在翻译功能中执行此操作时,翻译的单词排序不正确。

我该如何解决这个问题?

屏幕截图和代码如下所示。

enter image description here

class ViewController: UIViewController {
    @IBOutlet weak var txtMain: UITextView!
    var commonWordsArray = [String]()
    var yPoint = 250

    override func viewDidLoad() {
        super.viewDidLoad()

        findCommonWords()
        translate()
    }

    func findCommonWords() {
        let textViewText = txtMain.text

        //separate the text into words and get rid of the "" results
        let commonWords = textViewText?.lowercased().components(separatedBy: [" ","."]).filter({ !$0.isEmpty })

        //count the occurrence of each word
        let wordCounts = NSCountedSet(array: commonWords!)

        //sort the words by their counts in a descending order, then take the first three elements
        let sortedWords = wordCounts.allObjects.sorted(by: {wordCounts.count(for: $0) > wordCounts.count(for: $1) }) [0..<3]

        for word in sortedWords {
            print("\(word) \(wordCounts.count(for: word)) times")

            let myLabel = UILabel()
            myLabel.frame = CGRect(x: 0, y: 0, width: 120, height: 25)
            myLabel.center = CGPoint(x: 80, y: yPoint)
            myLabel.text = word as? String
            myLabel.textAlignment = .left
            self.view.addSubview(myLabel)

            yPoint += 30

            commonWordsArray.append(word as! String)
        }

        yPoint = 250

        print(commonWordsArray)
    }

    func translate() {
        let translator = ROGoogleTranslate()
        translator.apiKey = "YOURAPIKEY" // Add your API Key here

        var params = ROGoogleTranslateParams()
        params.source =  "tr"
        params.target =  "en"

        for i in commonWordsArray {
            params.text = i

            print(i)

            translator.translate(params: params) { (result) in
                DispatchQueue.main.async {
                    let myLabel = UILabel()
                    myLabel.frame = CGRect(x: 0, y: 0, width: 120, height: 25)
                    myLabel.center = CGPoint(x: 250, y: self.yPoint)
                    myLabel.text = result
                    myLabel.textAlignment = .left
                    self.view.addSubview(myLabel)
                    print(result)
                    self.yPoint += 30
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我相信这段代码是你麻烦的根源:

   for i in commonWordsArray {
        params.text = i

        print(i)

        // for each word you call translate asynchronously
        translator.translate(params: params) { (result) in
            // and here you add the word to the UI on the main thread
            // however, this callback does not have to be called in the same order in which you called translate, 
            // and thus you can end up with different orders

            // add this line to confirm my hypothesis (if it prints correct pairs of words, then I am right):
            print(">>>> \(i) is \(result)")
            DispatchQueue.main.async {

                let myLabel = UILabel()
                myLabel.frame = CGRect(x: 0, y: 0, width: 120, height: 25)
                myLabel.center = CGPoint(x: 250, y: self.yPoint)
                myLabel.text = result
                myLabel.textAlignment = .left
                self.view.addSubview(myLabel)
                print(result)
                self.yPoint += 30

            }
        }
    }

translate方法的回调以未定义的顺序调用 - 基于远程调用何时返回。在主线程上同步它不会对订单有所帮助,因为它已经是错误的顺序。

如果我是对的,你必须找到一种方法将这些对组合在一起。我会准备翻译标签以及原始单词的标签,并且只在翻译中填写他们的文本 - iresult在回调中正确配对,使用该事实(例如,您可以使用字典存储每个单词的翻译标签,然后在回调中检索它。

编辑:可能的解决方案

如何实现所需目标的众多方法之一(用以下内容替换for循环):

for i in commonWordsArray {
    params.text = i

    let myLabel = UILabel()
    myLabel.frame = CGRect(x: 0, y: 0, width: 120, height: 25)
    myLabel.center = CGPoint(x: 250, y: self.yPoint)
    myLabel.textAlignment = .left
    self.view.addSubview(myLabel)
    self.yPoint += 30

    translator.translate(params: params) { (result) in
        DispatchQueue.main.async {
            myLabel.text = result
        }
    }
}

在此代码中,您将以正确的顺序为每个i创建并添加标签(因为您在调用异步translate方法之前正在执行此操作。自从关闭后,您将传递给{{1调用捕获其作用域中的局部变量,在回调中translate变量将指向给定结果的正确标签,而不管回调执行的顺序如何。