我正在制作一款拼字游戏,该游戏从Oxford Dictionary的API中获取单词。该应用程序提供了预期的单词,但其失败率高于我想要的水平。我的成功率约为25%至36%;大多数单词给出的结果都是nil,但这显然是我的错,而不是API的错。我想要更高的成功率,因为API不是免费的。还是这种命中率是主要API所特有的?
我知道我需要将其更改为Swift 4的JSON的Decodable ,但我还没有弄清楚那个问题。
您能在我的代码中找到导致完全简单的单词被跳过的任何内容,例如在任何词典中都存在的单音节单词吗?在代码的结尾,我在示例控制台日志中添加了成功和失败的单词。
func speakRandomWord() {
//Now that a valid random word is selected, this where I make my API call.
appId = "private"
appKey = "private"
language = "en"
word = randomWord //I get the random word from Lexicontext, Oxford API doesn't support random words yet. I filter out entriest that aren't one word.
regions = "gb"
word_id = word.lowercased()
url = URL(string:"https://odapi.oxforddictionaries.com:443/api/v1/entries/\(language)/\(word_id)/regions=\(regions)")!
var request = URLRequest(url: url)
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue(appId, forHTTPHeaderField: "app_id")
request.addValue(appKey, forHTTPHeaderField: "app_key")
let session = URLSession.shared
print ("URLSession began...")
dataAttempted += 1
_ = session.dataTask(with: request, completionHandler: { data, response, error in
if let httpResponse = response as? HTTPURLResponse {
print("statusCode: \(httpResponse.statusCode)")
if httpResponse.statusCode != 200 {
print ("URLSession failed, trying again...")
self.urlSessionFailed += 1
self.selectRandomWord()
self.speakRandomWord()
}
}
DispatchQueue.main.async { [unowned self] in
self.activitySpinner.stopAnimating()
self.activitySpinner.isHidden = true
self.theUserInput.becomeFirstResponder()
self.repeatButton.isEnabled = true
self.defineButton.isEnabled = true
}
if let response = response,
let data = data,
let jsonData = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:AnyObject]
{
if
let dictionary = jsonData as? [String: Any],
let results = dictionary["results"] as? [[String: Any]],
!results.isEmpty, case var result = results[0],
let lexicalEntries = result["lexicalEntries"] as? [[String: Any]],
!lexicalEntries.isEmpty, case var lexicalEntry = lexicalEntries[0],
let derivatives = lexicalEntry["derivatives"] as? [[String:Any]],
!derivatives.isEmpty, case var derivative = derivatives[0],
let pronunciations = lexicalEntry["pronunciations"] as? [[String: Any]],
!pronunciations.isEmpty, case var pronunciation = pronunciations[0],
let entries = lexicalEntry["entries"] as? [[String:Any]],
!entries.isEmpty, case var entry = entries[0],
let senses = entry["senses"] as? [[String:Any]],
!senses.isEmpty, case var sense = senses[0],
let examples = sense["examples"] as? [[String:Any]],
!examples.isEmpty, case var example = examples[0]
//Now I pick out details from the JSON like audio, sample sentence, etc.
{
if let theText = example.removeValue(forKey:"text") {
self.theText = String(describing:theText)
print ("The value is \(self.theText)")
}
if let meaning = sense.removeValue(forKey:"short_definitions") {
self.newMeaning = String(describing:meaning)
print ("The short meaning is \(self.meaning)")
}
if let origin = entry.removeValue(forKey:"etymologies") {
self.newEtymology = String(describing:origin)
self.decoded2 = String(self.newEtymology.characters.filter({!"U0123456789".contains(String($0))}))
// print ("The etymology is \(self.decoded2)")
}
if let audioPath = pronunciation.removeValue(forKey:"audioFile") {
print ("MP3 audio file for \(self.word) exists")
print (audioPath)
self.audioPaths.append(audioPath as! String)
self.dataIsValid += 1
self.successfulWords.append(self.word)
self.path = String(describing:audioPath)
self.repeatPath = self.path
print (self.path)
if let url = URL.init(string: self.path) {
self.player = AVPlayer.init(url: url)
self.player.play()
}
}
else {
print ("No audio data for \(self.word)!")
self.dataFailed += 1
self.audioFailed.append(self.word)
self.selectRandomWord()
}
}
else {
print ("\(self.randomWord) failed, reason unknown!")
self.dataFailed += 1
self.failedOtherReason.append(self.word)
self.selectRandomWord()
}
}
}).resume()
}
// Console results:
//URL Session failures: 5
//API attempts: 41.0
//API successes: 15.0
//API failures: 21.0
//Successful Oxford API hit percentage: 36.5853658536585
//These 15 words succeeded: ["denunciation", "strategic", "strategic", "detract", "opaline", "opaline", "jurist", "exit", "throaty", "mother", "mother", "regroup", "early", "managerial", "recalcitrant"]
//These 0 words had no audio: []
//These words 21 words failed for an unknown reason: ["overlook", "lignin", "mandate", "evident", "anagrammatize", "avoirdupois", "extraterrestrial", "opaline", "cauterization", "malted", "clear", "snuggle", "fresno", "jurist", "streamline", "nonconforming", "trochee", "adventitia", "rudiment", "sculpturesque", "bicycle"]
答案 0 :(得分:0)
没有足够的信息来调试此特定问题,但是您收到的JSON响应可能具有可选字段。对于某些响应,预期该字段为空。这部分代码,
if
let dictionary = jsonData as? [String: Any],
let results = dictionary["results"] as? [[String: Any]],
!results.isEmpty,
case var result = results[0],
let lexicalEntries = result["lexicalEntries"] as? [[String: Any]],
!lexicalEntries.isEmpty,
case var lexicalEntry = lexicalEntries[0],
let derivatives = lexicalEntry["derivatives"] as? [[String:Any]],
!derivatives.isEmpty,
case var derivative = derivatives[0],
let pronunciations = lexicalEntry["pronunciations"] as? [[String: Any]],
!pronunciations.isEmpty, case var pronunciation = pronunciations[0],
let entries = lexicalEntry["entries"] as? [[String:Any]],
!entries.isEmpty,
case var entry = entries[0],
let senses = entry["senses"] as? [[String:Any]],
!senses.isEmpty, case var sense = senses[0],
let examples = sense["examples"] as? [[String:Any]],
!examples.isEmpty,
case var example = examples[0]
//Now I pick out details from the JSON like audio, sample sentence, etc.
{
需要拆分以处理(和报告)缺少的字段。那是20个布尔测试,所有测试都必须在“好的”路径执行之前通过。 可能发生的情况是您的字典访问失败。例如,如果字典不包含“ lexicalEntries”,则它将采用失败路径,并且不会按预期返回空数组。 >
确认相同的单词每次都失败。查看实际的JSON以查找失败的单词,并确保报告了每个字段。
更新:
if let response = response,
let data = data,
let jsonData = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:AnyObject]
{
guard let dictionary = jsonData as? [String: Any] else {
print("Error: dictionary was not returned by endpoint")
return
}
guard let results = dictionary["results"] as? [[String: Any]] else {
print("Error: no results array returned by endpoint")
return
}
result = results.first
...