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

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

新規登録して質問してみよう
ただいま回答率
85.50%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

2回答

4945閲覧

ARkitとCoreLocationを用いて特定の位置に特定のオブジェクトが出現するアプリケーション

curh

総合スコア11

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/03/25 12:52

編集2018/03/26 07:57

Swift初心者です.

前提・実現したいこと

・使用言語,開発環境
swift Xcode9.2

・作りたいアプリケーション
ARkitとCoreLocationを用いて,特定の位置(locationData?.coordinate.latitude>=35.689634)に特定のオブジェクト(sphere3Node)を表示するiOSアプリケーションを作りたいです.
()内はソースコード内での特定のオブジェクト名,特定の位置です.テストのため適当な位置とオブジェクトです.

・実現したいこと
特定の位置に特定のオブジェクトを表示させたい.
CoreLocationを用いていますが,他に方法がありましたら是非教えていただきたいです.
現段階で自分で実装できるかもしれないと思った方法が「CoreLocationを用いて緯度経度を取得し,その範囲内においてオブジェクトを表示する」のみだったため,今回それに沿った質問をさせていただきました.
緯度経度を表示するだけのアプリケーションでしたら作れたのですが,ARと位置情報を融合させたいと思い作成している最中です.

CoreLocationで取得した緯度経度の情報をviewDidLoad内で使用したい
その時の値の渡し方を知りたい

位置情報はユーザーの移動ごとに取得したいです.

発生している問題・エラーメッセージ

if locationData?.coordinate.latitude >= 35.689634 { scene.rootNode.addChildNode(sphere3Node) }

のところで,Swift Compiler Error, Use of unresolved identifier 'locationData'と出ます.
locationData?.coordinate.latitudeの部分はもともとidoという変数にしていたのですが,エラーが出たため,locationData?.coordinate.latitudeに変えて見たのですが,それでもエラーが出ます.

ソースコードは以下のようになります.

import SceneKit import ARKit import CoreLocation import UIKit class ViewController: UIViewController, ARSCNViewDelegate, CLLocationManagerDelegate{ var locationManager = CLLocationManager() //ロケーションマネージャを作る @IBOutlet weak var idoLabel: UILabel! @IBOutlet weak var keidoLabel: UILabel! @IBOutlet weak var hyoukouLabel: UILabel! @IBOutlet weak var hanteiLabel: UILabel! @IBOutlet var sceneView: ARSCNView! func setupLocationService(){ locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.distanceFilter = 1 } func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { switch status{ case .authorizedAlways, .authorizedWhenInUse : //ロケーションの更新を開始 locationManager.startUpdatingLocation() case .notDetermined: //ロケーションの更新を停止する locationManager.stopUpdatingLocation() //disabledLocationLabel() default: //ロケーションの更新を停止する locationManager.stopUpdatingLocation() //disabledLocationLabel() } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){ let locationData = locations.last //緯度 if var ido = locationData?.coordinate.latitude{ ido = round(ido*1000000)/1000000 } //経度 if var keido = locationData?.coordinate.longitude{ keido = round(keido*1000000)/1000000 } //標高 if var hyoukou = locationData?.altitude{ hyoukou = round(hyoukou*100)/100 } } override func viewDidLoad() { super.viewDidLoad() //緯度経度設定 super.viewDidLoad() //disabledLocationLabel() locationManager.requestWhenInUseAuthorization() locationManager.delegate = self setupLocationService() self.sceneView = ARSCNView(frame: self.view.frame) self.view.addSubview(self.sceneView) // Set the view's delegate sceneView.delegate = self // Show statistics such as fps and timing information sceneView.showsStatistics = true // Create a new scene let scene = SCNScene() // box blue //Color Setting , random let random: CGFloat = CGFloat(arc4random() % 10) let r: CGFloat = CGFloat(arc4random_uniform(255)+1) / 255.0 let g: CGFloat = CGFloat(arc4random_uniform(255)+1) / 255.0 let b: CGFloat = CGFloat(arc4random_uniform(255)+1) / 255.0 //let color: UIColor = UIColor(red: r, green: g, blue: b, alpha: 1.0) let box = SCNBox(width: 0.2, height: 0.2, length: 0.2, chamferRadius: 0) //形,大きさ let material = SCNMaterial() material.diffuse.contents = UIColor(red:r, green:g, blue:b, alpha: 1) let node = SCNNode() node.geometry = box material.name = "Color" node.geometry?.materials = [material] node.position = SCNVector3(random, 0.2, -1) // sphere green let sphere = SCNSphere(radius: 0.2) //形,大きさ let sphereMaterial = SCNMaterial() // sphereMaterial.diffuse.contents = UIColor.green sphereMaterial.diffuse.contents = UIImage(named: "earthmap.jpeg") //色ではなく画像指定する let sphereNode = SCNNode() sphereNode.geometry = sphere sphereNode.geometry?.materials = [sphereMaterial] sphereNode.position = SCNVector3(0.4, 0.1, -1) // 表示位置 // sphere2 red let sphere2 = SCNSphere(radius: 0.1) //形,大きさ let sphere2Material = SCNMaterial() sphere2Material.diffuse.contents = UIColor.red let sphere2Node = SCNNode() sphere2Node.geometry = sphere2 sphere2Node.geometry?.materials = [sphere2Material] sphere2Node.position = SCNVector3(0.4, 0.1, -3) //ifでboxを表示できるかテスト let sphere3 = SCNSphere(radius: 0.1) //形,大きさ let sphere3Material = SCNMaterial() sphere3Material.diffuse.contents = UIColor.blue let sphere3Node = SCNNode() sphere3Node.geometry = sphere3 sphere3Node.geometry?.materials = [sphere3Material] sphere3Node.position = SCNVector3(0.5, 0.2, 0) scene.rootNode.addChildNode(node) scene.rootNode.addChildNode(sphereNode) scene.rootNode.addChildNode(sphere2Node) if locationData?.coordinate.latitude >= 35.689634 { scene.rootNode.addChildNode(sphere3Node) } //gesture 検知 let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped)) //タップされたら呼ばれる関数tapped self.sceneView.addGestureRecognizer(tapRecognizer) // Set the scene to the view sceneView.scene = scene } //objective-C func tapped @objc func tapped(recognizer: UIGestureRecognizer) { let sceneView = recognizer.view as! SCNView //as!型変換,タップされたオブジェクトのシーンを取得 let touchLocation = recognizer.location(in: sceneView) //タッチされた座標を返す let hitResults = sceneView.hitTest(touchLocation, options: [:]) //hitTestメソッドを利用, if !hitResults.isEmpty { //もしタッチしたデータがあれば(先頭の!はnotの意味) let node = hitResults[0].node //ノードに,先頭のノードの値を取り出す let material = node.geometry?.material(named: "Color") //Colorは対応する上で設定済み material?.diffuse.contents = UIImage(named: "earthmap.jpeg") //material?でアンラップ,color chnage, change graphic } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // Create a session configuration let configuration = ARWorldTrackingConfiguration() // Run the view's session sceneView.session.run(configuration) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // Pause the view's session sceneView.session.pause() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Release any cached data, images, etc that aren't in use. } // MARK: - ARSCNViewDelegate /* // Override to create and configure nodes for anchors added to the view's session. func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? { let node = SCNNode() return node } */ func session(_ session: ARSession, didFailWithError error: Error) { // Present an error message to the user } func sessionWasInterrupted(_ session: ARSession) { // Inform the user that the session has been interrupted, for example, by presenting an overlay } func sessionInterruptionEnded(_ session: ARSession) { // Reset tracking and/or remove existing anchors if consistent tracking is required } }

試したこと

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status:CLAuthorizationStatus) {

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){

の位置を変えたりしましたが,エラーメッセージは変わりませんでした.

(2)

locationData?.coordinate.latitude>=35.689634

の部分は当初変数idoを使っていたのですが,
Use of unresolved identifier 'ido'
というエラーが出ました.

補足情報(FW/ツールのバージョンなど)

・Xcodeのバージョンは9.2です.
・位置情報自体は取得できていると思います
(アプリを実行した際,位置情報取得確認の画面が出たため)

よろしくお願いいたします.
初心者のため至らないところもありますがよろしくおねがいいたします.

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2018/03/26 07:47

viewDidLoad()は、ViewControllerの表示開始時に一度しか呼ばれませんが、位置情報の確認(latitude >= 35.689634 )はそのタイミングだけで大丈夫なのでしょうか?
curh

2018/03/26 07:51

いえ,位置情報の確認は移動ごとに行いたいです.ただ,Swiftを勉強し始めたばかりなのでそこまで考えておりませんでした….理想としては,ポケモンGOのように移動した先にオブジェクトが出現させる,というものを考えております.
guest

回答2

0

「位置情報の確認は移動ごとに行いたい」のであれば、位置情報のチェックはlocationManager(_:didUpdateLocations:)で行って下さい。

今悩んでいる問題も、それで解決できます。

投稿2018/03/26 08:01

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

curh

2018/03/26 08:24

fuxxball様 回答ありがとうございます. func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){ の部分を func locationManager(_ manager: CLLocationManager, didUpdateLocations: [CLLocation]){ に書き換えたら良いのでしょうか? また,別の方がviewDidLoadから変数locationDataは参照できないとおっしゃっていたのですが,その問題も解決するのでしょうか? よろしくおねがいいたします.
guest

0

ベストアンサー

変数locationDataはdidUpdateLocationsの中のローカル変数なので、viewDidLoadからは参照できないです。

例えば

import SceneKit import ARKit import CoreLocation import UIKit class ViewController: UIViewController, ARSCNViewDelegate, CLLocationManagerDelegate{ var locationManager = CLLocationManager() var locationData:CLLocation? = nil // ここに宣言を追加 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){ // ここで値を代入する locationData = locations.last ... } override func viewDidLoad() { super.viewDidLoad() .... if let locationData = locationData, locationData.coordinate.latitude >= 35.689634 { scene.rootNode.addChildNode(sphere3Node) } } }

などクラス変数として使ってみてはいかがでしょうか?

投稿2018/03/25 21:49

編集2018/03/26 08:22
newmt

総合スコア1277

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

curh

2018/03/26 06:48

newmt様,回答ありがとうございます.変数locationDataはviewDidLoadから参照できないのですね. 宣言を追加するところまでは理解できたのですが, locationData = locations.last をクラス変数として使う,というところがわかりません….自分なりにlocationData = locations.lastの部分をコードに加えて見たのですが,エラー内容は変わらずです. よければもう少し詳しく教えていただけないでしょうか. よろしくおねがいいたします.
curh

2018/03/26 06:55

追記 override func viewDidLoad() { super.viewDidLoad() の下部に let locationData = locations.last と書いたのですが, use of unresoloved identifer 'locations'と出ました. 書き加える場所が間違っているのでしょうか?
newmt

2018/03/26 07:07

locationsはdidUpdateLocationsの引数ですので、viewDidLoadからは参照できません。回答を編集してみたですが、こちらでいかがでしょうか?
curh

2018/03/26 07:27

回答の編集ありがとうございます. 質問のソースコードにあるように, func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){ let locationData = locations.last という風にすでにコードを書いてありますので, var locationData:CLLocation? // ここに宣言を追加 を追加するのみ,ということでしょうか? 上記のように書いてみたのですが,エラー内容は変わりませんでした. let locationData = locations.lastではなく locationData = locations.lastのみにしてもエラー内容は変わりませんでした. それともそもそも if locationData?.coordinate.latitude >= 35.689634 { scene.rootNode.addChildNode(sphere3Node) } または if ido >= 35.689634 { scene.rootNode.addChildNode(sphere3Node) } の書き方が違うのでしょうか? ここでUse of unresolved identifier 'locationData'またはUse of unresolved identifier 'ido'と出ます. viewDidLoadからlocationsが参照できないとのことで,idoという変数で置いてみたのですが,変わらずです. お手数おかけします.よろしくお願いいたします.
newmt

2018/03/26 08:27 編集

すいません。一部修正しました。こちらでエラーは解消されるはずですが、fuzzball様のおっしゃる通り都度位置を確認したいのでしたら、viewDidLoadではなくlocationManager(_:didUpdateLocations:)で行なってください。詳しい処理はわかりませんが、位置をチェックして図形を追加している処理をlocationManager(_:didUpdateLocations:)で行う必要があると思います。
curh

2018/03/26 08:28

修正,また詳しいご説明ありがとうございます.無事エラー解消できました. とても勉強になりました.ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問