こんにちは、前回投稿から相当時間が空いているのでたぶん初投稿です。
なんかアプリを作ることになってしまったんですが1日でできてしまったのでそのことを書いてみます。
~前日譚~
えらいひと「iPhoneのGPSの精度わかんないし調べようよ」
ぼく「アプリつくるんですか」
えらいひと「つくっちゃお、Mac借りてくるから」
~数日後~
社内ITのひと「Mac持ってきました」
ぼく「は~い」(マジで作るんかSwiftやったことないぞ)
構成図
端末からGPSの座標を取得してAzure上にデプロイしたAPIへPOSTする単純なアプリです。
いざ開発
といいつつも日ごろから触ってない環境で触ったこともない言語で一寸先は闇。困ったときはGoogle先生に頼ります。
Xcodeを入れる
Xcode入れるとiOSアプリ作れるんやね。入れたる。
プロジェクトを作る
Create a new Xcode project
っと。
なにこれ…とりあえず機能多くないし Single View App
でいいか
アプリの情報適当に入れてええか。Next
押して保存場所選択するとええな。
詰む
User Interface
が Swift UI
になっててGoogleに聞けども聞けども噛み合いません。
天の神に聞いたら
「Storyboard
選べ」
とのこと。
なるほど、Storyboard
で作るとGoogleで出てくる情報通りにいくんだなと。
頼るべきは神。
User Interface を Storyboard にして再度プロジェクト作成
ぼく「Main.storyboard
がある!!!!!!!!!」
Main.storyboard
を選択するとデザイナーが出るのでUIのパーツを置いていきます。
それっぽくなってきた。
コードを書く
天の声「Assistant Editor
を開くとこのUIに紐づいたコードが表示されるらしい。」
なるほど。
~10分後~
いや。丸いアイコンのボタンないじゃん。
天の声「どうやらXcodeのバージョンが新しくなっていてUIが変わってるらしい。」
viewDidLoad
が起動時に走る感じっぽい?
とりあえず書いていきます。
位置情報を扱うにはまずimportを追加する必要があるとな。
import CoreLocation
次に位置情報を司る CLLocationManager
を初期化する必要があると。
コンストラクタに書くのも長くなるしメソッド化します。
var locationManager : CLLocationManager!
func setupLocationManager() {
locationManager = CLLocationManager()
guard let locationManager = locationManager
else { return }
// アプリがバックグラウンドでも位置情報を取りたいのでAlwaysAuthorizationを要求
locationManager.requestAlwaysAuthorization()
// 端末で位置情報取得が許可されているか取得
let status = CLLocationManaager.authorizationStatus()
if status == .authorizedAlways {
locationManager.delegate = self
locationManager.distanceFilter = 2 // 位置情報を再取得する閾値(m)
locationManager.activityType = CLActivityType.automotiveNavigation // 車での移動を想定
locationManager.allowsBackgroundLocationUpdates = true // バックグラウンド取得の許可
}
}
こいつを起動時に呼び出してあげましょう
override func viewDidLoad() {
super.vierDidLoad()
setupLocationManager()
}
そして位置情報更新時に走る処理も作成
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.first
}
あとはInfo.plistに位置情報要求時の文言を追記。
Keyに NSLocationAlwaysUsageDescription
Valueに表示したい文言を追加っと。
あとバックグラウンドでの位置情報更新を許可しないといけなかった。
プロジェクトのSigning & Capabilities
から を入れましょう。
GPSは取れたからあとはAzureに投げるだけやな!
ということで投げる部分を書きます。
func sendGeoCoordinateToWebApi(_ geo: CLLocation) {
let url = "https://<Azure App Service名>.azurewebsites.net/api/GeoCoordinate"
let request = NSMutableURLRequest(url: URL(string: url)!)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
// jsonを作成
let params:[String:Any] = [
"Name": textOutlet.text as String?,
"Latitude": geo.coordinate.latitude,
"Longitude": geo.coordinate.longitude,
]
// POSTする
do {
request.httpBody = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
let task:URLSessionDataTask = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) -> Void in
let resultData = String(data: data!, encoding: .utf8)!
print(resultData)
})
task.resume()
} catch {
print("Error: \(error)")
return
}
}
jsonを作成の部分では以下のようなjsonを作っています。作ったAPIと形式を合わせてるだけなので適当です。
{
"Name": "ワイ",
"Latitude": 111,
"Longitude": 111,
}
textOutlet
はtextboxから値を引いてくるため設定したアウトレットです。
あとはこれを一情報更新時に発火するメソッドから呼び出すだけやな!
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.first
sendGeoCoordinateToWebApi(location)
}
完成!
早速AzureのSQL DBの中を見てみます。
値が入ってる~~~~~~~~~~~!!!!!!!!!!!!!!!!!!!!!!
というわけで1日(1営業日)でアプリ(と値を受け取るAPI)ができちゃいました。
おつかれさまでした。
おわり。