🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Swift

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

Q&A

1回答

1183閲覧

func addTargetの値を画面遷移する方法

xiu.a

総合スコア0

Swift

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

0グッド

0クリップ

投稿2020/12/26 09:12

前提・実現したいこと

私はUIButtonを使って、画像から位置と色を取得し、そして別のボタンを押すと自動に値を持って次の画面へ行くようにしたいと思っています。しかし値の受け渡しができない。
実際に位置はデバックエリアで表示できています。

swift12.2で
main.viewcontroller.swift
main.storyboard
next.viewcontroller.swift
next.storyboard
の四つで操作している。

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

位置と色の取得コード:
@objc public func xxx(_ sender: UIButton, event: UIEvent) {
let location : CGPoint = (event.touches(for: sender)?.first?.location(in: view))!
print(location)
let r2l = rgb_to_lab(red: r, green: g, blue: b)
print("lab色:", r2l as Any)
}

画面遷移のコード
@IBAction func Next(_ sender: UIButton) {
let storyboard: UIStoryboard = UIStoryboard(name: "Next", bundle: nil)
if let nt = storyboard.instantiateInitialViewController(), let nextNt = nt as? NextViewController {
nextNt.value = ?????
self.present(Nt, animated: true, completion: nil)
}
}
しかし,いくら試しても?????にr2lを入れることができません。
どうしたらいいでしょうか?

試したこと

二つのstoryboardに分けず、やっても移動できない。位置と色取得コードを@objc public func xxx(_ sender: UIButton, event: UIEvent) {}の外に出すと、どこを押したのかがわからなくなるから、ダメでした。
デバックエリアに表示できたのに、どうしてダメなのでしょう?どなたが位置と色の値が画面遷移できる方法を教えて下さい。おねがいします。

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

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

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

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

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

hoshi-takanori

2020/12/26 09:45

画面遷移についてはそれで行けそうな気がしますが、xxx で取得した位置と色をどうやって nextNt.value = ????? のところに受け渡すかの問題でしょうか? 質問文中のコードだと、location や r2l は xxx のローカル変数なので、xxx の外からはアクセスできないように見えますが…。
xiu.a

2020/12/26 10:00

画面遷移は直接nextNt.value = ”000”に書き込めば、できています。しかし、私はr2lの値を???に入れたいです。 ローカル変数だと、外からアクセスできないのですか?何をすれば、外に出すことができるでしょうか?教えていただきたいです。おねがいします。
hoshi-takanori

2020/12/26 10:06

xxx がいつどうやって呼ばれるかによりますが、r2l を xxx の戻り値にして画面遷移のコードから xxx を呼ぶか、r2l を main クラスのインスタンス変数にすることでしょうか。
xiu.a

2020/12/26 10:27

main.viewcontroller class ViewController: UIViewController { @IBOutlet weak var btn: UIButton! override func viewDidLoad() { super.viewDidLoad() btn.addTarget(self, action: #selector(xxx), for: .touchUpInside) view.addSubview(btn) } @objc public func xxx(_ sender: UIButton, event: UIEvent) { print("OK") let location : CGPoint = (event.touches(for: sender)?.first?.location(in: view))! print(location) 省略 let r2l = rgb_to_lab(red: r, green: g, blue: b) print("lab色:", r2l as Any) } @IBAction func Next(_ sender: UIButton) { // ここに画面遷移処理(NextViewControllerに遷移する処理)を記載 let storyboard: UIStoryboard = UIStoryboard(name: "Next", bundle: nil) if let vc = storyboard.instantiateInitialViewController(), let nextVc = vc as? NextViewController { // NextViewControllerのメンバ変数valueに文字列を代入 nextVc.value = ???? r2lを入れたい self.present(vc, animated: true, completion: nil) } } } という感じになっています。目的は???の中にr2lの値を入れる事です。手動に入れるのではなく、自動的に入って、画面遷移により次のページに移動する事です。 よろしくおねがいします
guest

回答1

0

たぶん、btn は main.storyboard で配置済みかつ押された時に Next を呼ぶように配線済みってことだと思いますが、その場合、ボタンを押すと Next と xxx の両方が呼ばれます。かつ、順番は Next が先で xxx が後になる気がします。つまり、NextViewController を開いた後で xxx が呼ばれて r2l の値が表示されてると思います。

main.storyboard と main.viewcontroller.swift の両方でボタンが押されたときの処理を設定する必要はないと思うので、Next から xxx を呼ぶことにすると次のようにすればいいのでは。
なお、r2l の型が不明なので xxx の戻り値の型は String にしてみましたが、実際の型を指定してください。
また、Next の引数を変更するので、main.storyboard のボタンを押したときの処理は配線し直す必要があります。

diff

1 class ViewController: UIViewController { 2 3 @IBOutlet weak var btn: UIButton! 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7- btn.addTarget(self, action: #selector(xxx), for: .touchUpInside) 8- view.addSubview(btn) 9 } 10 11- @objc public func xxx(_ sender: UIButton, event: UIEvent) { 12+ func xxx(_ sender: UIButton, event: UIEvent) -> String { 13 print("OK") 14 let location : CGPoint = (event.touches(for: sender)?.first?.location(in: view))! 15 print(location) 16 省略 17 let r2l = rgb_to_lab(red: r, green: g, blue: b) 18 print("lab色:", r2l as Any) 19+ return r2l 20 } 21 22- @IBAction func Next(_ sender: UIButton) { 23+ @IBAction func Next(_ sender: UIButton, event: UIEvent) { 24+ // まずxxxを呼び出し、結果をr2lに格納 25+ let r2l = xxx(sender, event: event) 26 // ここに画面遷移処理(NextViewControllerに遷移する処理)を記載 27 let storyboard: UIStoryboard = UIStoryboard(name: "Next", bundle: nil) 28 if let vc = storyboard.instantiateInitialViewController(), let nextVc = vc as? NextViewController { 29 // NextViewControllerのメンバ変数valueに文字列を代入 30- nextVc.value = ???? r2lを入れたい 31+ nextVc.value = r2l 32 self.present(vc, animated: true, completion: nil) 33 } 34 } 35 }

投稿2020/12/26 11:25

hoshi-takanori

総合スコア7899

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

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

xiu.a

2020/12/26 12:38

そうすることにより、 nextVc.value = r2l に Cannot assign value of type ‘(Double,Double,Double)’ to type ’String’ というエラーが発生する。r2lをバラバラにしましたが、あまり効果がありませんでした。 ちなみに、Next.viewcontrollerでは var value: String = "" となっています。
hoshi-takanori

2020/12/26 13:13

r2l の型が (Double, Double, Double) なら、NextViewController の value もそれに合わせるか、型変換が必要です。実際にどうやるかは、NextViewController で value の値をどう使いたいかによります。
xiu.a

2020/12/26 14:03

実際に言うと、[Double,Double,Double]の方が使いやすいです。 なので、 let r2l:(Double,Double,Double) = xxx(sender, event: event)に定義すると、main.viewのエラーが消えましたが、今度はnext.viewにてエラー発生。つまりnextVc.value = r2lではr2lは(Double,Double,Double)になっていて、nextVc.valueも(Double,Double,Double)になっているはず。ならば、next.viewに渡した値も(Double,Double,Double)になっているはずです。しかし //貰ったデータはここに入る var value: (Double,Double,Double) = “”①エラー文 override func viewDidLoad() { super.viewDidLoad() // 受け取った値をUILabelで表示  self.clab.text = self.value②エラー文 ①Cannot convert value of type ’String’ to specified type’(Double,Double,Double)’ ②Cannot assign value to type ‘(Double,Double,Double)’ to type ‘String’ ①のエラー文ではString型となっている。そして、その即下に‘(Double,Double,Double)に変換できないと言っています。 main->nextの型は両方共(Double,Double,Double)にしているのですが、なぜStringになるのでしょうか?
hoshi-takanori

2020/12/26 14:17

var value: (Double,Double,Double) = “” これは、value の型が (Double, Double, Double) なのに、文字列である “” で初期化しようとしているためにエラーになります。 var value: (Double, Double, Double) = (0, 0, 0) とかにすればいいはず。 self.clab.text = self.value (Double, Double, Double) の値を表示するには文字列に変換する必要があります。 self.clab.text = "(self.value)" とすればいいのでは。
xiu.a

2020/12/26 14:48

そうすることで、確かにエラーがなくなり、buildすることができましたが、 override func viewDidLoad() においてある、画像の読みよりができなくなり、位置と色が取れなくなりました。 override func viewDidLoad() { super.viewDidLoad() btn.addTarget(self, action: #selector(buttonDidTap), for: .touchUpInside) view.addSubview(btn) //sizeのバランスが崩れずに済む btn.imageView?.contentMode = .scaleAspectFit let picture = UIImage(named: "none") //ボタンの画像にする self.btn.setImage(picture, for: .normal) override func viewDidLoad() { super.viewDidLoad() let picture = UIImage(named: "none") //ボタンの画像にする self.btn.setImage(picture, for: .normal) } 一応画像は表示するようになりましたが、タッチしても、位置表示も色も出なくなりました???? すごいです、こうやって、初期化するのですね、勉強になりました。
xiu.a

2020/12/26 15:14 編集

全体的にこうなっています。 class ViewController: UIViewController { @IBOutlet weak var btn: UIButton! override func viewDidLoad() { super.viewDidLoad() let picture = UIImage(named: "none") //ボタンの画像にする self.btn.setImage(picture, for: .normal) } func xxx(_ sender: UIButton, event: UIEvent) -> (Double,Double,Double) { print("OK") let location : CGPoint = (event.touches(for: sender)?.first?.location(in: view))! print(location) //使う写真の指定 let picture = sender.imageView?.image! // 获取指定像素颜色 let rgbc = picture![Int(location.x), Int(location.y)]?.rgba print("rgb色:", rgbc as Any) let r: Double = Double((rgbc?.dr)!), g: Double = Double((rgbc?.dg)!), b: Double = Double((rgbc?.db)!); let r2l = rgb_to_lab(red: r, green: g, blue: b) print("lab色:", r2l as Any) return r2l } @IBAction func Next(_ sender: UIButton, event: UIEvent) { // まずxxxを呼び出し、結果をr2lに格納 let r2l = xxx(sender, event: event) // ここに画面遷移処理(NextViewControllerに遷移する処理)を記載 let storyboard: UIStoryboard = UIStoryboard(name: "Next", bundle: nil) if let vc = storyboard.instantiateInitialViewController(), let nextVc = vc as? NextViewController { // NextViewControllerのメンバ変数valueに文字列を代入 nextVc.value = r2l self.present(vc, animated: true, completion: nil) } } } override func viewDidLoad() で画像を入れたことにより、画像は表示されるようになりましたが、 btn.addTarget(self, action: #selector(buttonDidTap), for: .touchUpInside)消したことにより、位置と色が取得できないので、値が渡せるかどうかも確認できません。。。 せっかく助けていただいたのに、申しわけありません、もう少しおねがいします。
hoshi-takanori

2020/12/26 15:31

位置が取得できないとのことですが、location はどんな値が表示されますか? xxx では let location : CGPoint = (event.touches(for: sender)?.first?.location(in: view))! で location(in: view) としているので、たぶん画面全体における座標になってると思います。これを let location : CGPoint = (event.touches(for: sender)?.first?.location(in: sender))! と view から sender に変更すると押されたボタンの中での位置になるので、正しい位置が取れるのではないでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問