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

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

ただいまの
回答率

89.52%

Swift Realtimedatabaseにユーザーを自動追加しその下に2つの項目を固定したい

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 176

globalplus

score 63

FirebaseのRealtimedatbaseにchildByAutoIDを使って新しくユーザーが自動追加できる様にし、
autoIDの下にuserLatitudeとuserLongitudeを固定して置き、そこに実際の緯度経度を保存したいです。
しかしRealtimedatabaseを見てみると保存されたデータが"Label"になってしまいます。
アドバイス頂きたいです。お願いします。

import UIKit
import Firebase
import MapKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    @IBOutlet weak var mapView: MKMapView!
    @IBOutlet weak var latitude: UILabel!
    @IBOutlet weak var longitude: UILabel!
    let locationManager = CLLocationManager()
    let user = Auth.auth().currentUser?.uid
    var ref: DatabaseReference!

    override func viewDidLoad() {
        super.viewDidLoad()
        ref = Database.database().reference()
        locationManager.delegate = self as!CLLocationManagerDelegate
        post()
    }
    //データ書き込み
    func post() {

        let post = ["userLatitude": latitude.text, "userLongitude": longitude.text]
        ref.child("users").childByAutoId().setValue(post)
    }
    //ロケーションマネージャー通知    
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        switch status {
        case .notDetermined:
            locationManager.requestWhenInUseAuthorization()
        case .authorizedWhenInUse:
            locationManager.startUpdatingLocation()
        default:
            break
        }
    }
   //座標を取得し、labelに表示←これは実装できてます。
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let coordinate = locations.last?.coordinate {
            // 現在地を拡大して表示する
            let span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
            let region = MKCoordinateRegion(center: coordinate, span: span)
            mapView.region = region
        }
        guard let newLocation = locations.last else {
                return
        }
        self.latitude.text = "".appendingFormat("%.4f", newLocation.coordinate.latitude)
        self.longitude.text = "".appendingFormat("%.4f", newLocation.coordinate.longitude)
        let location = locations.first
        let latitude = location?.coordinate.latitude
        let longitude = location?.coordinate.longitude

        print("latitude: \(latitude!)\nlongitude: \(longitude!)")
    }


}


実行結果
イメージ説明

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

func post() {


の次の行に

print("latitude:", latitude.text, "longitude:", longitude.text)


を入力し、送信する前の値を確認してみてはどうですか?
ちなみに、LabelのtextプロパティはString型になりますからね。
データベースの結果からすると、Labelと出力されるはず???

ちょっと考えたんですが、
気になるのはlocationManagerがきちんと動いているかですね、
座標はprintでコンソールに表示されるんですよね?
そしてから、postを押しましたか?

locationManagerで座標が取得される前の状態でPostを押したら、
おそらくstoryboardで設定されている文字(推測するに"Label"?)が送信されます。

なので、プログラムはきちんと書かれている通りに動いていると思います。
書き方に問題があるということになります。

通常なら、GPSの座標を保存する入れものを別に用意し、それでいろいろやります。
例えば、

import UIKit
import Firebase
import MapKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

    @IBOutlet weak var mapView: MKMapView!
    @IBOutlet weak var latitudeLabel: UILabel!  // なんであるかわかりやすいようにLabel付けました(Double型の数値でないことわかるように)
    @IBOutlet weak var longitudeLabel: UILabel!  // なんであるかわかりやすいようにLabel付けました
    var currentLatitude: Double? = nil  // この行追加、GPS取得前はnil(何もない)です
    var currentLongitude: Double? = nil // この行追加

// ~~間省略

    //データ書き込み
    func post() {
        // nilチェックし、gps取得前ならそもそも送信しない
        if let latitude = self.currentLatitude, let longitude = self.currentLongitude {
            // gps座標ありなので、送信(nilでない値=latitude, longitudeを使う)
            let postData = ["userLatitude": latitude, "userLongitude": longitude]
            ref.child("users").childByAutoId().setValue(postData)
        } else {
            // nilの状態(=まだ取得されてない)なので、アラートなどでもどうぞ
        }
    }

// ~~間省略

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // ここも変更しました。 nilをまだよく理解していないみたいですね。
        guard let newLocation = locations.last else {
                return
        }
        // 以降はnilを除外した、newLocationを用います。
        // 地図の表示変更
        let span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
        let region = MKCoordinateRegion(center: newLocation.coordinate, span: span)
        mapView.region = region
        // 変数にセット
        self.currentLatitude = newLocation.coordinate.latitude
        self.currentLongitude = newLocation.coordinate.longitude
        // UILabel更新, メンバ変数currentXXXを使うので、引数用いず。
        updateUILabeltext()
    }

    func updateUILabeltext() {
        // 自分もnil check忘れてました。
        if let latitude = self.currentLatitude, let longitude = self.currentLongitude {
            // double型からString型へ、桁数指定とともに
            self.latitudeLabel.text = String(format: "%.4f", self.latitude)
            self.longitudeLabel.text = String(format: "%.4f", self.currentLongitude)
        }
    }

こんなのでどうでしょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/11/24 01:47

    <+35.56357227,+140.36454139> +/- 65.00mと出力されました
    しっかり動いてる様です?
    ただref.child("users").childByAutoId().setValue(postData)
    の下に追加した
    print("保存後currentLatitude:", currentLatitude, "保存後currentLongitude:", currentLongitude)
    が出力されていません。

    キャンセル

  • 2019/11/24 01:57

    コードとして間違っているとは思えないんですが、、、
    変数に代入できない理由が全くわかりませんね。。。

    viewdidloadないで
    self.currentLatitude = 35.6585805
    self.currentLongitude = 139.7454329
    と設定してみてください。

    キャンセル

  • 2019/11/24 02:49

    出力されませんでした。。。
    何が原因なのでしょうか??

    キャンセル

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

  • ただいまの回答率 89.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる