#AlamofireとKannaを使ってスクレイピングしてみました
gameのキャラクターの情報をサイトから取ってくるアプリを作ろうと思っています。
最初の画面(viewController)でURLを5個まで貼ってもらい、userDefaultsで保存して画面遷移しデータを取ってきてviewで表形式でそれぞれの値を比較しようと思いました。
ViewController
1 var urlArray:[String] = [] 2 @IBOutlet weak var textField1: UITextField! 3 @IBOutlet weak var textField2: UITextField! 4 @IBOutlet weak var textField3: UITextField! 5 @IBOutlet weak var textFiled4: UITextField! 6 @IBOutlet weak var textField5: UITextField! 7 8 9 10 @IBAction func buttonPushed(_ sender: UIButton) { 11 if self.textField1.text != ""{ 12 self.urlArray.append(self.textField1.text!) 13 } 14 if self.textField2.text != ""{ 15 self.urlArray.append(self.textField2.text!) 16 } 17 if self.textField3.text != ""{ 18 self.urlArray.append(self.textField3.text!) 19 } 20 if self.textFiled4.text != ""{ 21 self.urlArray.append(self.textFiled4.text!) 22 } 23 if self.textField5.text != ""{ 24 self.urlArray.append(self.textField5.text!) 25 } 26 let userDefaults = UserDefaults.standard 27 userDefaults.set(self.urlArray, forKey: "urlArray") 28 userDefaults.synchronize() 29 performSegue(withIdentifier: "goPlayers", sender: nil) 30 } 31 32 33} 34
PlayersViewController
1var players:[Player] = [] 2 3 override func viewDidLoad() { 4 super.viewDidLoad() 5 // Do any additional setup after loading the view. 6 7 let userDefaults = UserDefaults.standard 8 let urlArray:[String] = userDefaults.array(forKey: "urlArray") as! [String] 9 10 for i in 0..<urlArray.count{ 11 DispatchQueue.global().sync { 12 print(urlArray[i]) 13 self.scrapWebsite(urlArray[i]) 14 print("players.count3:(self.players.count)") 15 } 16 print("players.count1:(self.players.count)") 17 } 18 print(self.players.count) 19 //viewを追加する関数 20 self.SetView(players.count) 21 } 22 23/////////////////////////////////////////////////// 24 struct Player { 25 var playerName:String? 26 var MaxLevel:String? 27 var abilityList:[(name:String,score:String)] = [/*省略しますがタプル配列で26個分、予め項目名(name)と数値(score)を入れて置いてます*/] 28 } 29////////////////////////////////////////////////////// 30 31func scrapWebsite(_ url:String){ 32 //GETリクエスト 指定URLのコードを取得 33 Alamofire.request(url).responseString { response in 34 //Boolで確認 35 print("true or fauls:(response.result.isSuccess)") 36 37 if let html = response.result.value { 38 //plaers配列に追加 39 self.players.append(self.parseHTML(html: html)) 40 print("players.count2:(self.players.count)") 41 } 42 } 43 } 44 45 func parseHTML(html: String)-> (Player){ 46 //戻り値を宣言 47 var returnPlayer = Player() 48 49 if let doc = try? HTML(html: html, encoding: .utf8) { 50 //タイトルをプリント 51 print("doc.titile:(doc.title!)") 52 53 for link in doc.xpath("/html/body/div[2]/div[4]/script[1]/text()"){ 54 //省略しますがreturnPlayerに値を入れる処理をします 55 } 56 } 57 print("returnPlayer:(returnPlayer)") 58 return returnPlayer 59 } 60
##躓いているところはAlamofireとKannaとは全く関係ないところです
ViewControllerでtextField1のみにURLを入れれ実行します。
するとscrapWeb()でplayers配列にperseHTML()の戻り値(returnPlayer)を追加しているのにprint("players.count2:(self.players.count)")ではplayers.countが1となりますが、print("players.count1:(self.players.count)"),print("players.count3:(self.players.count)")では0となってしまします。
###クロージャの処理はその関数の処理が終わってから始まるのか?
PlayersViewController
1 for i in 0..<urlArray.count{ 2 DispatchQueue.global().sync { 3 print(urlArray[i]) //(1) 4 self.scrapWebsite(urlArray[i]) //(2) 5 print("players.count3:(self.players.count)" //(3) 6 } 7 print("players.count1:(self.players.count)" //(4) 8 }
これだとglobal()が並列処理でsyncが同期処理なので、処理が開始される順番は(1)→(2)→(3)→(4)となり、並列処理なので(1),(2),(3)の終了の順番はまちまちで、(1),(2),(3)の終了後に(4)が開始され終了されるのではないでしょうか?
"start"/"end"ログを見ると、おそらくクロージャの処理はscrapWebsite関数の処理が終了した後に実行されていると思うのですがそういう考えでいいのでしょうか?
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/19 09:02
2020/02/19 23:30 編集
2020/02/21 14:43