英単語を推測するゲームを作っています。
viewDidLoad
でまずvocab.txt
を読み込み、newRound()
で単語をテスト、その後missedVocab.txt
に保存するようにしたいのですが、newRound()
が実行される前にmissedVocab.txt
へ保存するコードが実行されてしまっています。
newRound()
が完全に終わってからテキストファイルへ保存するようにしたいのですがどのように実装すれば良いでしょうか?
swift
1override func viewDidLoad() { 2 super.viewDidLoad() 3 // --- テキストファイルの取得 --- 4 if let filePath = Bundle.main.path(forResource: "vocab", ofType: "txt"), 5 let str = try? String(contentsOfFile: filePath, encoding: String.Encoding.utf8) { 6 7 var vocabArr = str.components(separatedBy: "\n") 8 9 for i in 0..<vocabArr.count { 10 let j = Int(arc4random_uniform(UInt32(vocabArr.count))) 11 if i != j { 12 vocabArr.swapAt(i,j) 13 } 14 } 15 16 for vocab in vocabArr { 17 var appendObj = vocab.components(separatedBy: "#") 18 appendObj[0] = appendObj[0].trimmingCharacters(in: .whitespaces) 19 if appendObj != [""] { 20 vocabList.append(appendObj) 21 } 22 } 23 24 // 新しいゲームを開始 25 // 問題を間違える度にmissedVocabs[]にstringを保存 26 newRound() 27 28 29 // missedVocabsに保存されたstringをファイルに保存 30 if let dir = FileManager.default.urls( for: .documentDirectory, in: .userDomainMask ).first { 31 32 let filePath = dir.appendingPathComponent( "missedVocab.txt" ) 33 print("abh") 34 print(filePath) 35 36 do { 37 print("filepath : (filePath)") 38 print("missedVocabs : (missedVocabs)") 39 for missedVocab in missedVocabs { 40 try missedVocab.write(to: filePath, atomically: true, encoding: .utf8) 41 } 42 } catch { } 43 } 44 } 45}
for-in文でmissedVocab上書きしてませんか?
このままだと上書きされてしまうのでそれも要修正です。今問題視してるのが、newRound()の中で単語を間違える度に間違えた単語をprintしているのですが、それよりnewRound()の後に書かれてるprint("missedVocabs : \(missedVocabs)")が実行されることでして、確実にnewRound()が終わったあとにdo{} catch{} のコードを実行するにはどうすればよいでしょうか?
戻り値じゃだめかな? DispatchQueueか、クロージャか。
「newRound()が実行される前にmissedVocab.txtへ保存するコードが実行されてしまっています」というのはありえません。newRound()から戻ってこない限り、その下にある保存処理は実行されません。また、ViewControllerのライフサイクルを理解できていないようなので、その辺りから調べることをおすすめします。
newRound()内の保存部分が非同期なのでは?