Help us understand the problem. What is going on with this article?

Swift未経験者が1日でアプリを作った話

こんにちは、前回投稿から相当時間が空いているのでたぶん初投稿です。

なんかアプリを作ることになってしまったんですが1日でできてしまったのでそのことを書いてみます。

~前日譚~

えらいひと「iPhoneのGPSの精度わかんないし調べようよ」
ぼく「アプリつくるんですか」
えらいひと「つくっちゃお、Mac借りてくるから」
~数日後~
社内ITのひと「Mac持ってきました」
ぼく「は~い」(マジで作るんかSwiftやったことないぞ)

構成図

swift01.png

端末からGPSの座標を取得してAzure上にデプロイしたAPIへPOSTする単純なアプリです。

いざ開発

といいつつも日ごろから触ってない環境で触ったこともない言語で一寸先は闇。困ったときはGoogle先生に頼ります。

Xcodeを入れる

Xcode入れるとiOSアプリ作れるんやね。入れたる。

プロジェクトを作る

スクリーンショット 2019-11-28 17.19.39.png

Create a new Xcode project っと。

スクリーンショット 2019-11-28 17.21.08.png

なにこれ…とりあえず機能多くないし Single View App でいいか

スクリーンショット 2019-11-28 17.23.24.png

アプリの情報適当に入れてええか。Next 押して保存場所選択するとええな。

詰む

User InterfaceSwift UI になっててGoogleに聞けども聞けども噛み合いません。
天の神に聞いたら
Storyboard 選べ」
とのこと。

なるほど、Storyboard で作るとGoogleで出てくる情報通りにいくんだなと。

頼るべきは神。

User Interface を Storyboard にして再度プロジェクト作成

ぼく「Main.storyboardがある!!!!!!!!!」

スクリーンショット 2019-11-28 17.30.47.png

Main.storyboard を選択するとデザイナーが出るのでUIのパーツを置いていきます。

スクリーンショット 2019-11-28 17.32.28.png

それっぽくなってきた。

コードを書く

天の声「Assistant Editorを開くとこのUIに紐づいたコードが表示されるらしい。」

なるほど。

~10分後~

いや。丸いアイコンのボタンないじゃん。

swift02.png

天の声「どうやらXcodeのバージョンが新しくなっていてUIが変わってるらしい。」

スクリーンショット 2019-11-28 17.40.53.png

あった。
スクリーンショット 2019-11-28 17.56.52.png

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に表示したい文言を追加っと。

スクリーンショット 2019-11-28 18.10.46.png

実機で見てみますか
image.png

:ok: :ok: :ok: :ok: :ok: :ok: :ok: :ok: :ok: :ok: :ok: :ok: :ok:

あとバックグラウンドでの位置情報更新を許可しないといけなかった。
プロジェクトのSigning & Capabilitiesから :heavy_check_mark: を入れましょう。

スクリーンショット 2019-11-28 18.17.58.png

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の中を見てみます。

swift03.png

値が入ってる~~~~~~~~~~~!!!!!!!!!!!!!!!!!!!!!!

というわけで1日(1営業日)でアプリ(と値を受け取るAPI)ができちゃいました。
おつかれさまでした。

おわり。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away