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

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

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

Swift Playgroundsは、初心者・子ども向けのSwift学習アプリ。iPad/Mac用があり、コーディングの知識は不要です。Swiftの言語そのものを選択肢からタップしてコード入力できる点が特徴。段階的に学習を積み上げる初心者にも優しい設計ながらも、正統派のSwiftが学べます。

Swift

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

Q&A

解決済

1回答

809閲覧

入力された任意の文字列をマップのdetailcalloutaccessoryview内に表示したい

Swift_Begginer

総合スコア4

Swift Playgrounds

Swift Playgroundsは、初心者・子ども向けのSwift学習アプリ。iPad/Mac用があり、コーディングの知識は不要です。Swiftの言語そのものを選択肢からタップしてコード入力できる点が特徴。段階的に学習を積み上げる初心者にも優しい設計ながらも、正統派のSwiftが学べます。

Swift

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

0グッド

0クリップ

投稿2022/05/06 07:40

SwiftUIのTextfieldやPickerに入力された任意の文字列や画像を、MapkitのUILabelに表示したいです。

文字列や画像の格納された変数を受渡するために@Stateや@Bindingなどを使って下記のコードのように実現しようとしたのですが、「Variable 〇〇 Used by function definition before being initialized」というエラーが出てしまい、意図した動作ができませんでした。
エラーの内容から初期化処理に関するエラーであると推測したのですが、具体的なエラーの内容の理解と、どのような書き方をすれば解決出来るか分からないので、ご教授いただきたいです。
よろしくお願いいたします。

swift

1import SwiftUI 2import MapKit 3 4struct MapView: UIViewRepresentable { 5 6 func makeUIView(context: Context) -> MKMapView { 7 let map = MKMapView() 8 map.delegate = context.coordinator 9 map.addGestureRecognizer(context.coordinator.myLongPress) 10 return map 11 } 12 func makeCoordinator() -> Coordinator { 13 Coordinator(self) 14 } 15 func updateUIView(_ mapView: MKMapView, context: Context) { 16 let latitude = 43.31513, longitude = 143.08874 17 let coordinate = CLLocationCoordinate2DMake(latitude, longitude) 18 // 縮尺を設定 19 let span = MKCoordinateSpan(latitudeDelta: 5, longitudeDelta: 5) 20 // マップの中心を設定 21 let region = MKCoordinateRegion(center: coordinate, span: span) 22 mapView.setRegion(region, animated: true) 23 } 24 25 26 class Coordinator: NSObject, MKMapViewDelegate { 27 var parent: MapView 28 let myLongPress: UILongPressGestureRecognizer = UILongPressGestureRecognizer() 29 30 init(_ parent: MapView) { 31 self.parent = parent 32 super.init() 33 self.myLongPress.addTarget(self, action: #selector(recognizeLongPress)) 34 } 35 36 @objc func recognizeLongPress(sender: UILongPressGestureRecognizer) { 37 if sender.state == .ended { 38 if let mapView = sender.view as? MKMapView { 39 // タップした位置を取得 40 let point = sender.location(in: mapView) 41 // mapView上での位置に変換 42 let coordinate = mapView.convert(point, toCoordinateFrom: mapView) 43 print(coordinate.latitude) 44 print(coordinate.longitude) 45 print("-") 46 // アノテーション作成 47 let annotation = MKPointAnnotation() 48 annotation.coordinate = coordinate 49 //annotation.title = "taitooooru" 50 mapView.addAnnotation(annotation) 51 } 52 } 53 } 54 55 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { 56 57 @Binding var num:Int 58 @Binding var titlename:String 59 @Binding var image: UIImage? 60 //@State var num:Int = 1 61 //@State var titlename:String = "ssss" 62 63 64 let identifier = "annotation" 65 if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) { 66 annotationView.annotation = annotation 67 return annotationView 68 } else { 69 let annotationView = MKAnnotationView( 70 annotation: annotation, 71 reuseIdentifier: identifier 72 ) 73 74 //ピンのスタイルを変更 75 if num == 1{ 76 annotationView.image = UIImage(named: "pre") 77 }else if num == 2{ 78 annotationView.image = UIImage(named: "Eat") 79 } 80 81 //stackViewの設定 82 let stackView = UIStackView() 83 stackView.axis = NSLayoutConstraint.Axis.vertical 84 stackView.alignment = UIStackView.Alignment.leading 85 86 //ラベルの作成 87 let title = UILabel() 88 title.text = "\(titlename)" 89 title.font = UIFont.boldSystemFont(ofSize: 20) 90 title.isUserInteractionEnabled = true 91 stackView.addArrangedSubview(title) 92 93 //景色の画像の作成 94 let imageView = UIImageView(image: UIImage(named: "Try")) 95 imageView.frame = CGRect(x: 0, y: 0, width: 50, height: 50) 96 imageView.contentMode = .scaleAspectFit 97 stackView.addArrangedSubview(imageView) 98 99 annotationView.canShowCallout = true 100 annotationView.detailCalloutAccessoryView = stackView 101 annotationView.isUserInteractionEnabled = true 102 return annotationView 103 } 104 } 105 } 106}

swift

1import SwiftUI 2 3struct uiview: View { 4 @State var titlename:String = "" 5 @State var honbun:String = "" 6 @State private var image: UIImage? 7 @State var input:Bool = false 8 @State var num:Int = 1 9 10 var body: some View { 11 ZStack{ 12 MapView() 13 VStack{ 14 Button(action: { 15 //ボタンを押した時の処理を記載 16 input = true 17 }) { 18 Text("ピン設定のためのボタン") 19 .foregroundColor(.black) 20 } 21 } 22 .sheet(isPresented: $input) { 23 inputView(titlename: self.$titlename, honbun: self.$honbun, image: self.$image, num: $num) 24 } 25 } 26 } 27}

swift

1import SwiftUI 2 3struct inputView: View { 4 @Binding var titlename:String 5 @Binding var honbun:String 6 @Binding var image: UIImage? 7 @Binding var num:Int 8 @State var showingImagePicker:Bool = false 9 10 @Environment(\.presentationMode) var presentationMode 11 private func didTapDismissButton() { 12 presentationMode.wrappedValue.dismiss() 13 } 14 15 var body: some View { 16 ZStack{ 17 NavigationView { 18 VStack { 19 Form { 20 TextField("ピンの名前", text: $titlename) 21 Picker(selection: $num, label: Text("選択")) { 22 Text("みかん").tag(1) 23 Text("ぶどう").tag(2) 24 } 25 .frame(width: 400) 26 27 Button(action: { 28 showingImagePicker = true 29 }) { 30 Text("フォトライブラリから選択") 31 if let uiImage = image { 32 Image(uiImage: uiImage) 33 .resizable() 34 .scaledToFit() 35 .frame(width: 200, height: 200) 36 } else { 37 Image("noimage") 38 .resizable() 39 .scaledToFit() 40 .frame(width: 200, height: 200) 41 } 42 } 43 44 Button(action: { 45 //確定ボタンを押した時の処理を記載 46 didTapDismissButton() 47 }) { 48 Text("確定") 49 } 50 } 51 .navigationBarTitle("ピン情報入力画面") 52 } 53 } 54 .sheet(isPresented: $showingImagePicker) { 55 ImagePicker(sourceType: .photoLibrary, selectedImage: $image) 56 } 57 } 58 } 59}

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

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

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

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

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

guest

回答1

0

ベストアンサー

https://developer.apple.com/documentation/swiftui/binding

@Bindingのリファレンスを見ますと、@Binding(@State)はView構造体の中に定義するのが一般的なのかなと思います。

CoordinatorはView構造体を継承したものではありません。
この中に@Bindingを定義するような形を見たことがありません。
(私が経験不足なだけかもしれません。。)

MapViewの中に@Bindingを定義して、
mapView(_:viewFor:)メソッドの中ではparent.numなどの形で参照する形にしてみたらどうでしょうか。

@Bindingなどについて、面倒かもしれませんが、公式のチュートリアルの内容を一から実施してみて理解しておくと良いかもしれません。
https://developer.apple.com/tutorials/swiftui/creating-and-combining-views

追記です

コメントありがとうございます。

MapViewクラスだけ修正イメージを貼り付けてみます。
(動かしていないので雰囲気だけ見てください。。)
(// *****の付近が主な修正です。)

swift

1struct MapView: UIViewRepresentable { 2 3 // ***** @Binding 4 @Binding var num:Int 5 @Binding var titlename:String 6 @Binding var image: UIImage? 7 8 func makeUIView(context: Context) -> MKMapView { 9 let map = MKMapView() 10 map.delegate = context.coordinator 11 map.addGestureRecognizer(context.coordinator.myLongPress) 12 return map 13 } 14 func makeCoordinator() -> Coordinator { 15 Coordinator(self) 16 } 17 func updateUIView(_ mapView: MKMapView, context: Context) { 18 let latitude = 43.31513, longitude = 143.08874 19 let coordinate = CLLocationCoordinate2DMake(latitude, longitude) 20 // 縮尺を設定 21 let span = MKCoordinateSpan(latitudeDelta: 5, longitudeDelta: 5) 22 // マップの中心を設定 23 let region = MKCoordinateRegion(center: coordinate, span: span) 24 mapView.setRegion(region, animated: true) 25 } 26 27 28 class Coordinator: NSObject, MKMapViewDelegate { 29 30 var parent: MapView 31 let myLongPress: UILongPressGestureRecognizer = UILongPressGestureRecognizer() 32 33 init(_ parent: MapView) { 34 self.parent = parent 35 super.init() 36 self.myLongPress.addTarget(self, action: #selector(recognizeLongPress)) 37 } 38 39 @objc func recognizeLongPress(sender: UILongPressGestureRecognizer) { 40 if sender.state == .ended { 41 if let mapView = sender.view as? MKMapView { 42 // タップした位置を取得 43 let point = sender.location(in: mapView) 44 // mapView上での位置に変換 45 let coordinate = mapView.convert(point, toCoordinateFrom: mapView) 46 print(coordinate.latitude) 47 print(coordinate.longitude) 48 print("-") 49 // アノテーション作成 50 let annotation = MKPointAnnotation() 51 annotation.coordinate = coordinate 52 //annotation.title = "taitooooru" 53 mapView.addAnnotation(annotation) 54 } 55 } 56 } 57 58 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { 59 60 //@State var num:Int = 1 61 //@State var titlename:String = "ssss" 62 63 64 let identifier = "annotation" 65 if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) { 66 annotationView.annotation = annotation 67 return annotationView 68 } else { 69 let annotationView = MKAnnotationView( 70 annotation: annotation, 71 reuseIdentifier: identifier 72 ) 73 74 // ***** MapViewクラスの@Bindingのプロパティを参照します 75 //ピンのスタイルを変更 76 if parent.num == 1{ 77 annotationView.image = UIImage(named: "pre") 78 }else if parent.num == 2{ 79 annotationView.image = UIImage(named: "Eat") 80 } 81 82 //stackViewの設定 83 let stackView = UIStackView() 84 stackView.axis = NSLayoutConstraint.Axis.vertical 85 stackView.alignment = UIStackView.Alignment.leading 86 87 //ラベルの作成 88 let title = UILabel() 89 title.text = "\(parent.titlename)" 90 title.font = UIFont.boldSystemFont(ofSize: 20) 91 title.isUserInteractionEnabled = true 92 stackView.addArrangedSubview(title) 93 94 //景色の画像の作成 95 let imageView = UIImageView(image: UIImage(named: "Try")) 96 imageView.frame = CGRect(x: 0, y: 0, width: 50, height: 50) 97 imageView.contentMode = .scaleAspectFit 98 stackView.addArrangedSubview(imageView) 99 100 annotationView.canShowCallout = true 101 annotationView.detailCalloutAccessoryView = stackView 102 annotationView.isUserInteractionEnabled = true 103 return annotationView 104 } 105 } 106 } 107}

投稿2022/05/06 09:11

編集2022/05/09 23:36
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Swift_Begginer

2022/05/09 14:53

コメントありがとうございます。 お返事遅くなり申し訳ありません。 @Bindingについて、公式のチュートリアルにて内容を見直しました。 おっしゃられた通り、@Binding(@State)はView構造体の中に定義するのが一般的であるのだと理解できました。 また、mapView(_:viewFor:)メソッド内で参照する必要性は理解できるのですが、参照の方法が分からないため、 具体的な書き方も教えて頂けないでしょうか? お手数をおかけしますが、よろしくお願いいたします。
Swift_Begginer

2022/05/11 10:23

ありがとうございます。 無事に値を参照することができ、 意図した挙動をすることができました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問