我列出了Textview中最常见的3个单词。然后我通过谷歌翻译翻译了这些单词以使用框架。我想这样做是为了显示我用不同的UILabel列出的这些单词的翻译。 但我有一个问题。当我在翻译功能中执行此操作时,翻译的单词排序不正确。
我该如何解决这个问题?
屏幕截图和代码如下所示。
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
}
}
}
}
}
答案 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
方法的回调以未定义的顺序调用 - 基于远程调用何时返回。在主线程上同步它不会对订单有所帮助,因为它已经是错误的顺序。
如果我是对的,你必须找到一种方法将这些对组合在一起。我会准备翻译标签以及原始单词的标签,并且只在翻译中填写他们的文本 - i
和result
在回调中正确配对,使用该事实(例如,您可以使用字典存储每个单词的翻译标签,然后在回调中检索它。
编辑:可能的解决方案
如何实现所需目标的众多方法之一(用以下内容替换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
变量将指向给定结果的正确标签,而不管回调执行的顺序如何。