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

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

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

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

Swift

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

Q&A

解決済

1回答

5540閲覧

swiftUIの異なるファイル間で変数を共有して動的に変更したい.

watsa

総合スコア4

iOS

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

Swift

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

0グッド

1クリップ

投稿2020/05/07 18:13

編集2020/05/07 18:31

前提・実現したいこと

swift初学者です.オブジェクト指向プログラミング自体もまだ理解し切れていません.
異なるswiftファイル間で変数を共有して動的に変更したく調べたのですが,自力で解決できませんでした.

実現したいことは+ボタンと-ボタンを配置して,+または-ボタンを押した時に画面上の数を増減させることです.
これ自体の実現は以下のコードでできています.

import SwiftUI class ShareNum: ObservableObject{ @Published var num: Int = 0 } struct ContentView: View { @ObservedObject var Num = ShareNum() var body: some View { VStack{ Text("(Num.num)") HStack{ Button(action: { self.Num.num += 1 }) { Image(systemName: "plus") .frame(width: 40, height: 40) .imageScale(.large) } .background(Color.blue) .foregroundColor(.black) Button(action: { self.Num.num -= 1 }) { Image(systemName: "minus") .frame(width: 40, height: 40) .imageScale(.large) } .background(Color.red) .foregroundColor(.black) } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }

しかしながら,ボタンをそれぞれ別のファイルで実装した時に変数が共有されず,デバッグで確認したところ画面上の数字は動かずに,それぞれ独立して変化していました.

異なるファイル間で変数を共有し動的に変更できる方法がありましたら,必要な知識を教えていただけたら幸いです.

作成したソースコード

ContentView

1#ContentView.swift 2 3import SwiftUI 4 5struct ContentView: View { 6 @ObservedObject var Num = ShareNum() 7 var body: some View { 8 VStack{ 9 Text("(Num.num)") 10 HStack{ 11 button1() 12 button2() 13 } 14 } 15 } 16} 17 18struct ContentView_Previews: PreviewProvider { 19 static var previews: some View { 20 ContentView() 21 } 22} 23

button1

1#button1.swift 2 3import SwiftUI 4 5struct button1: View { 6 @ObservedObject var Num = ShareNum() 7 var body: some View { 8 Button(action: { 9 self.Num.PlusButton() 10 }) { 11 Image(systemName: "plus") 12 .frame(width: 40, height: 40) 13 .imageScale(.large) 14 } 15 .background(Color.blue) 16 .foregroundColor(.black) 17 } 18} 19 20struct button1_Previews: PreviewProvider { 21 static var previews: some View { 22 button1(Num: ShareNum()) 23 } 24} 25

button2

1#button2.swift 2 3import SwiftUI 4 5struct button2: View { 6 @ObservedObject var Num = ShareNum() 7 var body: some View { 8 Button(action: { 9 self.Num.MinusButton() 10 }) { 11 Image(systemName: "minus") 12 .frame(width: 40, height: 40) 13 .imageScale(.large) 14 } 15 .background(Color.red) 16 .foregroundColor(.black) 17 } 18} 19 20struct button2_Previews: PreviewProvider { 21 static var previews: some View { 22 button2(Num: ShareNum()) 23 } 24}

Share

1class ShareNum: ObservableObject{ 2 @Published var num: Int = 3 3 func PlusButton(){ 4 self.num += 1 5 print(self.num) 6 } 7 func MinusButton(){ 8 self.num -= 1 9 print(self.num) 10 } 11}

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

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

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

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

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

guest

回答1

0

ベストアンサー

難しく考えてますかね。
親ビューを ContentView,子ビューをそれぞれのボタンのビューだと考えて
親ビューで @State をつけて Int 型の num を宣言して,
子ビューでは @Binding をつけて子ビューでの値の変更を親ビューに伝えれば良いです。
下記が例です。

import SwiftUI struct ContentView: View { @State private var num = 3 var body: some View { VStack{ Text("(num)") HStack{ // プラスボタンとマイナスボタン PlusButton(num: $num) // $num は Binding<Int> MinusButton(num: $num) // $num は Binding<Int> } } } } struct PlusButton: View { // 親ビュー(ContentView)に値を伝える @Binding var num: Int var body: some View { Button(action: { // num の値に変化があるので親ビューに通知される self.num += 1 }) { Image(systemName: "plus") .frame(width: 40, height: 40) .imageScale(.large) } .background(Color.blue) .foregroundColor(.black) } } struct MinusButton: View { // 親ビュー(ContentView)に値を伝える @Binding var num: Int var body: some View { Button(action: { // num の値に変化があるので親ビューに通知される self.num -= 1 }) { Image(systemName: "minus") .frame(width: 40, height: 40) .imageScale(.large) } .background(Color.red) .foregroundColor(.black) } }

値のバインドが分かりにくい場合は,
ボタンタップの処理をクロージャで返すことで親ビュー側で計算させることもできます。
どちらでも動作は同じなのでわかりやすい方で実装進めれば良いと思います!

import SwiftUI struct ContentView: View { @State private var num = 3 var body: some View { VStack{ Text("(num)") HStack{ PlusButton { self.num += 1 } MinusButton { self.num -= 1 } } } } } struct PlusButton: View { // プラスボタンが押された場合の処理のブロック var plusNum: () -> Void var body: some View { Button(action: { self.plusNum() }) { Image(systemName: "plus") .frame(width: 40, height: 40) .imageScale(.large) } .background(Color.blue) .foregroundColor(.black) } } struct MinusButton: View { // マイナスボタンが押された場合の処理のブロック var minusNum: () -> Void var body: some View { Button(action: { self.minusNum() }) { Image(systemName: "minus") .frame(width: 40, height: 40) .imageScale(.large) } .background(Color.red) .foregroundColor(.black) } }

投稿2020/05/07 18:49

TakuyaAso

総合スコア1361

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

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

watsa

2020/05/08 05:07 編集

bindingすることで解決することができました.ありがとうございます. 子viewのpreviewproviderの引数にbindingした変数を入れないとエラーが出てしまうのですが,何故なのでしょうか?previewproviderの役割について教えてほしいです.
TakuyaAso

2020/05/08 05:29

そのクラスのビューのプレビューできる感じです。 引数は @Binding var num: Int を宣言した際に初期化していないので 値入れてねって感じです。私は定数与える形で下記のように書いてます。 struct PlusButton_Previews: PreviewProvider { static var previews: some View { PlusButton(num: .constant(1)) } } プレビューする端末複数選べたり ビューのサイズ変えられたりするので 下記サイトなど参考にしてみてください。 https://qiita.com/michimae/items/87512856bf63ea0fbe65
watsa

2020/05/08 06:36

なるほど,そういう事だったんですね.わかりやすい説明ありがとうございます.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問