- iOS
- 2017-04-21 - 更新:2018-02-15
この記事は最終更新日から1年以上経過しています。
何やらタイトルが長くなってしまいましたが、複合的な内容なのでこうなりました。
今回やりたかったことはタイトルの通りですが、分解すると…
1)WEBからデータをダウンロード
2)バックグラウンドで処理を実行
3)JSONデータを解析
4)解析したデータをRealmに挿入
以上の4つです。
エラーが出なくなるまでかなり苦労したのですが、一番の原因は日本語の扱いに関する部分ですので、
日本語を含まないデータの解析だけならすんなり可能ではないかと思います。
1)WEBからデータをダウンロード
WEBからデータをダウンロードするにはURLSessionを使います。
ダウンロードするURLを指定
let url: String = "http://www.exam.jp/json.php"
セッションを作成します。
let session = URLSession(configuration: URLSessionConfiguration.default)
タスクを登録します。
let task = session.dataTask(with: URLRequest(url: Foundation.URL(string: url)!), completionHandler: { (data, response, error) in if let urlContent = data { // ここに処理を記述 } })
作成したタスクを実行します。
task.resume()
2)バックグラウンドで処理を実行
バックグラウンドで処理を実行するには、GCD(Grand Central Dispatch)を使用します。
DispatchQueue.global().async { // バックグラウンドスレッドでの処理を記述 }
asyncだと非同期処理、syncだと同期処理になります。
3)JSONデータを解析
取得したJSONデータをJSONSerializationクラスを使って解析します。
let jsonObj = try! JSONSerialization.jsonObject(with: urlContent, options: [])
JSONデータが配列の場合は以下のようになります。
let list = try! JSONSerialization.jsonObject(with: urlContent, options: []) as! NSArray
4)解析したデータをRealmに挿入
解析したJSONデータをRealmデータベースに挿入します。
ここで注意点ですが、JSONの構造とRealmモデルの構造が同じである必要があります。
まずはRealmモデルを定義します。
class realmModel: Object { dynamic var id = 0 dynamic var name = "" // プライマリキーの定義 override class func primaryKey() -> String? { return "id" } }
取得するJSONデータ
{ "id": 1, "name": "alpha" }
let realm = try! Realm() do { try realm.write { let jsonObj = try! JSONSerialization.jsonObject(with: urlContent, options: []) let myData = realmModel(value: jsonObj) } } catch { }
JSONデータが配列の場合
取得するJSONデータ
[{ "id": 1, "name": "alpha" },{ "id": 2, "name": "beta" }]
try realm.write { let list = try! JSONSerialization.jsonObject(with: urlContent, options: []) as! NSArray for item in list { let myData = realmModel(value: item) print(myData) //デバッグ用に出力 realm.add(myData, update: true) } }
まとめると以下のようになります。
let url: String = "http://www.exam.jp/json.php" let session = URLSession(configuration: URLSessionConfiguration.default) let task = session.dataTask(with: URLRequest(url: Foundation.URL(string: url)!), completionHandler: { (data, response, error) in if let urlContent = data { // バックグラウンドで処理を実行する。 DispatchQueue.global().async { let realm = try! Realm() do { try realm.write { let list = try! JSONSerialization.jsonObject(with: urlContent, options: []) as! NSArray for item in list { let myData = realmModel(value: item) print(myData) //デバッグ用に出力 realm.add(myData, update: true) } } } catch { } } } }) task.resume()
Xcode: 8.3.2
Swift: 3.1
OS: Sierra 10.12
3,649 views