栃木県宇都宮市の赤ちゃんの駅と幼稚園一覧を地図表示するアプリを作ってみる。
2016/05/25
まだ子供が生後半年くらいだった頃、街を歩いてるとおむつ替えスペースが見つからなくて詰む、ということがあって、以来、デパートとかそういう施設がなさそうなところを歩くのは危険という認識だったのだけど、そういうことが現在位置からわかるようなアプリがあれば便利そうなので作ろうかなと思った。
そのためには、県とか市区町村がオープンデータでそう言った情報を公開してくれていたらいいのだけど、まあそういうの出してない自治体の方が多いんだろうなと思って試しに栃木県宇都宮市というところのホームページを検索していたら、子育て関係情報という、様々な育児情報をcsvファイルで公開しているページが見つかって、これは半端ないなと思った。
というわけで、この中で一番役に立ちそうな「赤ちゃんの駅登録施設一覧」というファイル、加えて「幼稚園一覧」についても地図に載せるようなアプリを作ってみました。
〔赤ちゃんの駅登録施設一覧〕,宇都宮市,クリエイティブ・コモンズ・ ライセンス表示 2.1(http://creativecommons.org/licenses/by/2.1/jp/)、
〔幼稚園一覧〕,宇都宮市,クリエイティブ・コモンズ・ ライセンス表示 2.1(http://creativecommons.org/licenses/by/2.1/jp/)
アプリを立ち上げると、まず赤いピンで「幼稚園一覧」から読み出した赤いピンが表示されます。
ピンをクリックすると、名称,住所,電話番号,公立/私立,保育時間が表示されます。
なお、画面をタップすると、緑色のピンで赤ちゃんの駅なるもののピンが表示されます。
ピンクリックで施設名,サービス内容,利用可能時間・休館日,所在地,連絡先が出ます。
特に、これでオムツ替え用スペースの有無がチェックできるから便利です。
弓道場もオムツ替えスペースあるんだなあ。
宇都宮が誇るFKD(福田屋百貨店)ももちろんの事
で、どうして上記のように画面タッチで次のピンが表示されるようにしたか。
本当は最初からピンを差したかったんですけど、赤いピンと緑のピンを同時に表示する方法がわからなかったのですよねえ。。
ピンはデフォルトで赤なのですが、緑のピンを刺すには、デリゲートメソッドのfunc mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?で、色を設定してやらなければならない。
ただ、これをやると、すべてのピンの色がそれ一色になってしまう。
なので、まずデリゲートメソッドを行う前にピンを挿しておいて、次のファイルの分は、タッチイベントをきっかけにピン表示およびデリゲートメソッドを開始するようにしたわけです。
あと、下のコードみればわかりますが、幼稚園ファイルと赤ちゃんの駅ファイル、それぞれ、HP上のcsvファイルから内容をコピペして「kinderGarden.txt」、「babyStation.txt」というファイルに格納してから、それを読みだしてます。
ちょっとアホくさくて、本当はそのままcsvファイルのurlにNSURLSessionとかNSURLConnectionでアクセスすればいいのですが、
ちゃんとデータは取れてるものの、なぜかそれをNSJSONSerializationとかでパースしようとしたりエンコードしようとしたりしてもうまくいかない、というかnilになるので、どうしたものかと。。。。
とりあえずいずれはurlでアクセスしてそのままやりたいけど、現状このような対処法です。
以下、コード。
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
let mapView: MKMapView = MKMapView()
var babyStationFlg: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
mapView.frame = CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height)
self.view.addSubview(mapView)
let centerCoordinate : CLLocationCoordinate2D = CLLocationCoordinate2DMake(36.558852,139.898126)//宇都宮駅
let span = MKCoordinateSpanMake(0.1, 0.1)
//中心位置、表示領域
let centerPosition = MKCoordinateRegionMake(centerCoordinate, span)
mapView.setRegion(centerPosition,animated:true)
getKinderGardenData()//幼稚園ファイル読み込み
}
//タッチされた時
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
if babyStationFlg == 0 {
mapView.delegate = self//自身をデリゲートとして設定
getBabyStationData()
babyStationFlg++
}
}
//赤ちゃん駅読み込み
func getBabyStationData() {
let filePath = NSBundle.mainBundle().pathForResource("babyStation",ofType:"txt")
do {
let data = try NSString(contentsOfFile: filePath!, encoding: NSUTF8StringEncoding) as String
data.enumerateLines{
line, stop in
let all = line//1行ごとに分割
let split = all.componentsSeparatedByString(",")//カンマ区切りに分割
print(split[0]) // 施設名
print(split[1]) // サービス内容
print(split[2]) // 利用可能時間・休館日
print(split[3]) // 所在地
print(split[4]) // 連絡先
print(split[5]) // GEOM
if split[5] != "GEOM" {//最初の行は緯度経度が数値じゃなくてGEOMだから排除
let GEOM = split[5].componentsSeparatedByString(":")//経度緯度を分割
print(GEOM[0])//経度
print(GEOM[1])//緯度
//緯度経度から地図上の座標を取得
let location = CLLocationCoordinate2DMake(CLLocationDegrees(GEOM[1])!,CLLocationDegrees(GEOM[0])!)
//CLLocationCoordinate2Dに変換
let mapPoint:CLLocationCoordinate2D = location
//ピン生成
let annotation = MKPointAnnotation()
//ピンの場所
annotation.coordinate = mapPoint
//ピンのタイトル
annotation.title = "\(split[0])"
//ピンのサブタイトル
annotation.subtitle = "\(split[1]),\(split[2]),\(split[3]),\(split[4])"
//ピンを地図上に追加
self.mapView.addAnnotation(annotation)
}
}
} catch {
print("エラー")
}
}
//デリゲートメソッド
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
//pinView?.animatesDrop = true
}
else {
pinView?.annotation = annotation
}
pinView?.pinTintColor = UIColor.greenColor()//緑色のピン
pinView?.canShowCallout = true//吹き出し表示
return pinView
}
//幼稚園ファイル読み込み
func getKinderGardenData() {
let filePath = NSBundle.mainBundle().pathForResource("kinderGarden",ofType:"txt")
do {
let data = try NSString(contentsOfFile: filePath!, encoding: NSUTF8StringEncoding) as String
data.enumerateLines{
line, stop in
let all = line//1行ごとに分割
let split = all.componentsSeparatedByString(",")//カンマ区切りに分割
print(split[0]) // 名称
print(split[1]) // 住所
print(split[2]) // 電話番号
print(split[3]) // 公立/私立
print(split[4]) // 保育時間
print(split[5]) // GEOM
if split[5] != "GEOM" {//最初の行は緯度経度が数値じゃなくてGEOMだから排除
let GEOM = split[5].componentsSeparatedByString(":")//経度緯度を分割
print(GEOM[0])//経度
print(GEOM[1])//緯度
//緯度経度から地図上の座標を取得
let location = CLLocationCoordinate2DMake(CLLocationDegrees(GEOM[1])!,CLLocationDegrees(GEOM[0])!)
//CLLocationCoordinate2Dに変換
let mapPoint:CLLocationCoordinate2D = location
//ピン生成
let annotation = MKPointAnnotation()
//ピンの場所
annotation.coordinate = mapPoint
//ピンのタイトル
annotation.title = "\(split[0])"
//ピンのサブタイトル
annotation.subtitle = "\(split[1]),\(split[2]),\(split[3]),\(split[4])"
//ピンを地図上に追加
self.mapView.addAnnotation(annotation)
}
}
} catch {
print("エラー")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
