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

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回答

571閲覧

【swift】円の中心座標をテキストフィールドに入力すると、その座標に円が再描画されるような挙動を実現したい。

naoharuiwai

総合スコア18

iOS

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

Swift

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

0グッド

0クリップ

投稿2018/09/15 19:48

前提・実現したいこと

Swift初心者です。勉強のために、二次元図形(円)を描画し、設置したtextfieldに中心座標を入力してreturnを押すと、その座標を中心として円が再描画されるという簡単なアプリを作っています。

アプリ起動時に円を描画することはできましたが、textfieldに座標を入力してもそれが反映されず、円がアプリ起動時に描画された座標のまま変化しません。
おそらく再描画する処理ができていないせいだと思いますが、どのタイミング・場所で再描画を行えば良いかが分かりません。
どなたか教えていただけるとありがたいです。

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

設定したtextfieldに新規座標を入力しても、それがviewに反映されない

該当のソースコード

lang

1//ViewController.swift 2 3import UIKit 4 5class ViewController: UIViewController, UITextFieldDelegate { 6 7 override func viewDidLoad() { 8 super.viewDidLoad() 9 // Do any additional setup after loading the view, typically from a nib. 10 11 // テキスト毎にタグを設定 12 xText.delegate = self 13 xText.tag = 1 14 yText.delegate = self 15 yText.tag = 2 16 self.view.backgroundColor = UIColor.gray // 全体背景をグレーに設定 17 } 18 19 @IBOutlet weak var xLabel: UILabel! 20 @IBOutlet weak var ylabel: UILabel! 21 @IBOutlet weak var xText: UITextField! 22 @IBOutlet weak var yText: UITextField! 23 24 25 func textFieldShouldReturn(_ textField: UITextField) -> Bool { 26 // キーボードを閉じる 27 textField.resignFirstResponder() 28 let nextView = TestDraw() // インスタンスを生成 29 // switch文により、xtextに入力した場合とytextに入力した場合を分ける 30 switch textField.tag { 31 case 1: 32 // xTextに入力した値をStringからCGFloatに変換 33 let xDouble: Double = atof(textField.text) 34 let x: CGFloat = CGFloat(xDouble) 35 // 入力された値をTestDraw.swift内に存在する座標変数へと格納 36 nextView.x = x 37 break 38 case 2: 39 // 同様のことをyTextについてもやる 40 let yDouble: Double = atof(textField.text) 41 let y:CGFloat = CGFloat(yDouble) 42 nextView.y = y 43 break 44 default: 45 print("エラー") 46 break 47 } 48 49 return true 50 } 51 52} 53

lang

1//TestDraw.swift 2 3import UIKit 4 5class TestDraw: UIView { 6 7 /* 8 // Only override draw() if you perform custom drawing. 9 // An empty implementation adversely affects performance during animation. 10 */ 11 // ViewControllerのxtextからの値を格納する変数 12 var x:CGFloat = 150 // 初期値 13 // 同じくyTextからの値を格納する変数 14 var y:CGFloat = 100 // 初期値 15 16 17 override func draw(_ rect: CGRect) { 18 // Drawing code 19 // 円の描画 20 let circle = UIBezierPath(arcCenter: CGPoint(x: x, y: y), radius: 80, startAngle: CGFloat(Double.pi*2.0*0.0/360.0), endAngle: CGFloat(Double.pi*2.0*360.0/360.0), clockwise: true) 21 let circleColor = UIColor.red 22 circleColor.setStroke() // 線の色を設定 23 circleColor.setFill() // 内側塗りつぶし色の設定 24 circle.fill() // 内側塗りつぶし 25 circle.lineWidth = 4 26 circle.stroke() 27 } 28 29 30} 31

試したこと

このプログラムでSimulatorを起動してみた画像が以下になります。

イメージ説明

円の中心座標XとYの初期値は、それぞれ150と100に設定していますので、異なる値を入力してみます。

イメージ説明

この状態でキーボードのreturnキーを押しても、変更が円に反映されませんでした。

ViewController.swiftを以下のようにし、returnキー押下時にTestDraw.swiftのxとyが正しく変化しているのか確認してみました。

lang

1//ViewController.swift 2 3import UIKit 4 5class ViewController: UIViewController, UITextFieldDelegate { 6 7 override func viewDidLoad() { 8 super.viewDidLoad() 9 // Do any additional setup after loading the view, typically from a nib. 10 11 // テキスト毎にタグを設定 12 xText.delegate = self 13 xText.tag = 1 14 yText.delegate = self 15 yText.tag = 2 16 self.view.backgroundColor = UIColor.gray // 全体背景をグレーに設定 17 } 18 19 @IBOutlet weak var xLabel: UILabel! 20 @IBOutlet weak var ylabel: UILabel! 21 @IBOutlet weak var xText: UITextField! 22 @IBOutlet weak var yText: UITextField! 23 24 25 func textFieldShouldReturn(_ textField: UITextField) -> Bool { 26 // キーボードを閉じる 27 textField.resignFirstResponder() 28 let nextView = TestDraw() // インスタンスを生成 29 // switch文により、xtextに入力した場合とytextに入力した場合を分ける 30 switch textField.tag { 31 case 1: 32 // xTextに入力した値をStringからCGFloatに変換 33 let xDouble: Double = atof(textField.text) 34 let x: CGFloat = CGFloat(xDouble) 35 // 入力された値をTestDraw.swift内に存在する座標変数へと格納 36 nextView.x = x 37 print("x = (nextView.x)") // 追加箇所 38 break 39 case 2: 40 // 同様のことをyTextについてもやる 41 let yDouble: Double = atof(textField.text) 42 let y:CGFloat = CGFloat(yDouble) 43 nextView.y = y 44 print("y = (nextView.y)") // 追加箇所 45 break 46 default: 47 print("エラー") 48 break 49 } 50 51 return true 52 } 53 54} 55

それぞれのtextfield内に、以下のように値を入力してみます。

イメージ説明

returnキーを押した後の出力は以下のようになりました。

x = 200.0
y = 150.0

これを見る限り、値はきちんと代入されているのだと思います、、。

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

Swift4.2
Xcode10

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

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

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

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

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

guest

回答1

0

ベストアンサー

まずTestDrawのインスタンスをtextFieldShouldReturnで毎回作成してるので、それはやめて、StoryboardにUIViewを配置、クラスをTestDrawにします。

また、x/yを設定した後 nextView.setNeedsDisplay() を呼んでください。
それで再描画されます。

投稿2018/09/16 02:52

編集2018/09/16 02:55
toki_td

総合スコア2850

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

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

naoharuiwai

2018/09/17 06:42

回答ありがとうございます。 おっしゃる通り、x/yを設定したのちにnextView.setNeedsDisplay()を呼びましたが、再描画されませんでした。 呼ぶ場所が間違っているのでしょうか、、。 func textFieldShouldReturn(_ textField: UITextField) -> Bool { // キーボードを閉じる textField.resignFirstResponder() // switch文により、xtextに入力した場合とytextに入力した場合を分ける switch textField.tag { case 1: // xTextに入力した値をStringからCGFloatに変換 let xDouble: Double = atof(textField.text) let x: CGFloat = CGFloat(xDouble) // 入力された値をTestDraw.swift内に存在する座標変数へと格納 nextView.x = x nextView.setNeedsDisplay() break case 2: // 同様のことをyTextについてもやる let yDouble: Double = atof(textField.text) let y:CGFloat = CGFloat(yDouble) nextView.y = y nextView.setNeedsDisplay() break default: print("エラー") break } return true }
toki_td

2018/09/17 07:23

別段変でもないですが、、、drawでログ仕込んでみたらどうですか?ちゃんと呼ばれます?
naoharuiwai

2018/09/17 08:56

draw内にログを仕込んでみましたが、returnキーを押した段階では呼ばれていませんでした。
toki_td

2018/09/17 11:20

それはおかしいですね、setNeedsDisplayを読んだら再描画されるのでdraw(rect:)が呼ばれるはずですが。 一度ソースまとめてアップしてもらったほうがわかりやすいです。
naoharuiwai

2018/09/17 12:12 編集

分かりました。 こちらに質問時のようにソースコード全体を貼るので良いでしょうか? それとも、Xcodeのプロジェクト自体のリンクを貼ったほうが分かりやすいでしょうか?
toki_td

2018/09/17 13:26

質問時のように張ってもらえたらいいですよ。TestDrawは変更なしですか? それだったらViewControllerだけでもいいです。
naoharuiwai

2018/09/17 14:27 編集

TestDrawはログを追加したのみですが、一応どちらも貼っておきます。 よろしくお願いします。 ``` //ViewController.swift import UIKit class ViewController: UIViewController, UITextFieldDelegate { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. // テキスト毎にタグを設定 xText.delegate = self xText.tag = 1 yText.delegate = self yText.tag = 2 self.view.backgroundColor = UIColor.gray // 全体背景をグレーに設定 } @IBOutlet weak var xLabel: UILabel! @IBOutlet weak var yLabel: UILabel! @IBOutlet weak var xText: UITextField! @IBOutlet weak var yText: UITextField! let nextView = TestDraw() func textFieldShouldReturn(_ textField: UITextField) -> Bool { // キーボードを閉じる textField.resignFirstResponder() // switch文により、xtextに入力した場合とytextに入力した場合を分ける switch textField.tag { case 1: // xTextに入力した値をStringからCGFloatに変換 let xDouble: Double = atof(textField.text) let x: CGFloat = CGFloat(xDouble) // 入力された値をTestDraw.swift内に存在する座標変数へと格納 nextView.x = x nextView.setNeedsDisplay() break case 2: // 同様のことをyTextについてもやる let yDouble: Double = atof(textField.text) let y:CGFloat = CGFloat(yDouble) nextView.y = y nextView.setNeedsDisplay() break default: print("エラー") break } return true } } ``` ``` //TestDraw.swift import UIKit class TestDraw: UIView { /* // Only override draw() if you perform custom drawing. // An empty implementation adversely affects performance during animation. */ // ViewControllerのXtextからの値を格納する変数 var x:CGFloat = 150 // 初期値 // 同じくyTextからの値を格納する変数 var y:CGFloat = 100 // 初期値 override func draw(_ rect: CGRect) { // Drawing code // 円の描画 let circle = UIBezierPath(arcCenter: CGPoint(x: x, y: y), radius: 80, startAngle: CGFloat(Double.pi*2.0*0.0/360.0), endAngle: CGFloat(Double.pi*2.0*360.0/360.0), clockwise: true) let circleColor = UIColor.red circleColor.setStroke() // 線の色を設定 circleColor.setFill() // 内側塗りつぶし色の設定 circle.fill() // 内側塗りつぶし circle.lineWidth = 4 circle.stroke() print(x) // ログ print(y) } } ``` コメントではMarkdown記法は適用されないんですね、、。
toki_td

2018/09/17 16:29

これってそもそも円表示されてませんよね?nextView はインスタンスを作成しただけでビューに追加してませんし。 ↓を行いましたか? > StoryboardにUIViewを配置、クラスをTestDrawにします。 で、ラベルとかと同様にReference Outletを結び付けてやれば @IBOutlet weak var nextView: TestDraw! ソースにと追加されるはずです。
toki_td

2018/09/17 16:31

ViewはStoryboardで作成するか、自分でインスタンスを追加した後、親に対してaddSubViewを行いレイアウトしないと表示されません。
naoharuiwai

2018/09/17 17:09

すみません、どうやらUIViewとVIewController.swiftとの結び付けができていなかったようです。 @IBOutlet weak var nextView: TestDraw! をコード内に書き、simulatorを起動すると上手くいきました。 回答して下さり、ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問