質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

2536閲覧

Swift3 httpメソッド・XMLパースでのデーター取得について

P-san

総合スコア21

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2017/04/19 02:17

###前提・実現したいこと
httpメソッドの仕組みについてまだよく解っていなく、データがうまく取得できません。

実現したいことは
loadXMLDataという関数を外部から呼び、その関数内でhttpメソッドのGETで取得したXMLデータをパースして
dataDictionaryという辞書型に格納して呼び出し元に返す。
という関数の作成です。

しかし、処理自体は動いているように見えるのですが、XMLのパースが終わる前に
returnされているようで、通信が成功してるのに値が[:]になってしまいます。

何が原因なのでしょうか。
よろしくお願いします。

###該当のソースコード

Swift

1 2// 呼び出し先 3 4import UIKit 5 6class GetData: NSObject , XMLParserDelegate { 7 8 // タグ 9 var tmpTag = "" 10 // 要素 11 var tmpElement = "" 12 // データを格納 13 var dataDictionary: [String:String] = [:] 14 15 16 /// XMLを解析する 17 /// 18 /// - Parameter urlText: URLを引数に指定 19 /// - Returns: サーバーからのデータ(サーバー通信が失敗した場合は[:]が返る。)を返す。 20 func loadXMLData(_ urlText: String) -> (dbData: [String:String]) { 21 22 // URLエラーチェック 23 guard let url = URL(string: urlText) else { 24 print("URLではありません") 25 return (dataDictionary) 26 } 27 28 var request = URLRequest(url: url) 29 request.httpMethod = "GET" 30 request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData 31 32 let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in 33 34 // check for http errors 35 if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { 36 print("statusCode should be 200, but is \(httpStatus.statusCode)") 37 print("response = \(response!)") 38 } 39 40 // check for fundamental networking error 41 if let _ = error { 42 print("error=\(error!)") 43 return 44 } 45 46 if let data = data { 47 48 // コンソールチェック 49 let responseString = String(data: data, encoding: .utf8) 50 print("サーバ結果" , "responseString = \(responseString!)") 51 52 // インターネット上のXMLを取得し、NSXML Parserに読み込む 53 let parser = XMLParser(data: data) 54 parser.delegate = self 55 parser.parse() 56 } 57 else { 58 print("data エラーです。") 59 return 60 } 61 } 62 task.resume() 63 64 return (dataDictionary) 65 } 66 67 68 // XML解析開始時に実行されるメソッド 69 func parserDidStartDocument(_ parser: XMLParser) { 70 71 // 初期化 =============================== 72 tmpTag = "" 73 tmpElement = "" 74 dataArray = [:] 75 // 初期化 =============================== 76 77 print("XML解析開始しました") 78 } 79 80 // 解析中に要素の開始タグがあった時に実行されるメソッド 81 func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { 82 print("開始タグ:" + elementName) 83 tmpTag = elementName 84 } 85 86 87 // 開始タグと終了タグでくくられたデータがあった時に実行されるメソッド 88 func parser(_ parser: XMLParser, foundCharacters string: String) { 89 print("要素:" + string) 90 tmpElement = string 91 } 92 93 94 // 解析中に要素の終了タグがあった時に実行されるメソッド 95 func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { 96 print("終了タグ:\(elementName)") 97 dataArray[tmpTag] = tmpElement 98 } 99 100 101 // XML解析終了時に実行されるメソッド 102 func parserDidEndDocument(_ parser: XMLParser) { 103 print("XML解析終了しました") 104 } 105 106 107 // 解析中にエラーが発生した時に実行されるメソッド 108 func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) { 109 print("エラー:" + parseError.localizedDescription) 110 } 111}

swift

1// 呼び出し元 2 3import UIKit 4 5class ViewController: UIViewController { 6 7let getData = GetData() 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 12 let result = getData.loadXMLData 13 print(result) // パースが終わる前に返ってきてる? 14 } 15}

###補足情報(言語/FW/ツール等のバージョンなど)
swift 3.1
xcode 8.2

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

[:]が返ってくるのは、非同期で動いているためです

swift

1print(result) // パースが終わる前に返ってきてる?

その通りです。非同期処理なのでパースが終わるのを待ちません。

その為解決策としては、

  1. 同期で動くものに変える
  2. delegate を viewController に向ける
  3. parserDidEndDocument() で viewController にパースしたDictionaryを渡す

3がおすすめです。

投稿2017/04/19 03:20

TakeoAsai

総合スコア880

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

P-san

2017/04/19 07:21

非同期処理というのを知りませんでした。勉強になります。 無事、うまくいきました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問