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

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

新規登録して質問してみよう
ただいま回答率
85.48%
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

1回答

2220閲覧

UIBezierPathを使用した図形の描画について

wai21

総合スコア32

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/19 07:30

前提・実現したいこと

view 全体にグリッド線を描画したい。

UIView のサブクラス(下記ソースのCanvasView)で、そのビュー全体にグリッド線を描画するために、 UIViewdraw(_ rect: CGRect) をオーバーライドし、UIBezierPath を使用してグリッド線を描画しているのですが、ビューの大きさが大きくなると、グリッドが表示されません。
draw(_ rect: CGRect) は呼ばれているのですが、エラーも出力されておらず、原因がわかりません。
また、init(frame: CGRect)backgroundColor の設定も行なっていますが、こちらも反映されなくなります。

下記ソースではボタンでスクロールビューに載せるキャンバスを切り替えていますが、
小さいキャンバンスはグリッド線が描画されますが、
大きいキャンバスはグリッド線が描画されません。

原因および対策方法をご教授ください。

クラスの説明

ViewController :スクロールビュー上にキャンバスを表示する
CanvasView :グリッドを描画するUIView のサブクラス
Grid :グリッドを描画するために、グリッドの各マス目の四隅のポイントを保持する

グリッドの描画処理

CanvasView におけるグリッドの描画処理の順番です。

  1. init(frame: CGRect) を呼ぶ
  2. backgroundColor.yellow を設定する
  3. initGrid() にてビュー全体におさまるだけのGrid の配列を作成しgrids に設定する
  4. draw(_ rect: CGRect) にて、grids のすべての要素について、UIBezeriPathを使用して各ポイントを線でつなぎ、グリッド線とする

Swift

1class ViewController: UIViewController { 2 // キャンバス 3 var canvasView: CanvasView! 4 // キャンバスを載せるスクロールビュー 5 @IBOutlet weak var scrollView: UIScrollView! 6 7 // 小さいキャンバスを表示する 8 @IBAction func small(_ sender: UIButton) { 9 canvasView.removeFromSuperview() 10 11 canvasView = CanvasView(frame: scrollView.bounds) 12 13 scrollView.addSubview(canvasView) 14 scrollView.contentSize = canvasView.frame.size 15 scrollView.contentOffset = CGPoint(x: 0, y: 0) 16 } 17 // 大きいキャンバスを表示する 18 @IBAction func big(_ sender: UIButton) { 19 canvasView.removeFromSuperview() 20 21 canvasView = CanvasView(frame: CGRect(x: 0, y: 0, width: 6000, height: 4000)) 22 23 scrollView.addSubview(canvasView) 24 scrollView.contentSize = canvasView.frame.size 25 scrollView.contentOffset = CGPoint(x: 0, y: 0) 26 } 27 override func viewDidLoad() { 28 super.viewDidLoad() 29 30 } 31 override func didReceiveMemoryWarning() { 32 super.didReceiveMemoryWarning() 33 // Dispose of any resources that can be recreated. 34 } 35 override func viewDidLayoutSubviews() { 36 // 小さいキャンバスを表示する 37 canvasView = CanvasView(frame: scrollView.bounds) 38 scrollView.addSubview(canvasView) 39 scrollView.contentSize = canvasView.frame.size 40 } 41} 42 43// キャンバスのグリッドの一つ一つのマス目 44class Grid { 45 // 左上 46 var upperLeft: CGPoint! 47 // 右上 48 var upperRight: CGPoint { 49 return CGPoint(x: upperLeft.x + width, y: upperLeft.y) 50 } 51 // 左下 52 var lowerLeft: CGPoint { 53 return CGPoint(x: upperLeft.x, y: upperLeft.y + height) 54 } 55 // 右下 56 var lowerRight: CGPoint { 57 return CGPoint(x: upperLeft.x + width, y: upperLeft.y + height) 58 } 59 60 init(upperLeft: CGPoint) { 61 self.upperLeft = upperLeft 62 } 63 private let width: CGFloat = 30 64 private let height: CGFloat = 20 65} 66 67// キャンバス 68class CanvasView: UIView { 69 // グリッドの一つ一つのマス目を配列で保持する 70 var grids = Array<Grid>() 71 72 override init(frame: CGRect) { 73 super.init(frame: frame) 74 backgroundColor = .yellow 75 initGrid() 76 } 77 // 画面いっぱいのグリッドのマス目を作成する 78 func initGrid() { 79 var point = CGPoint(x: 20, y: 20) 80 while point.y < frame.height { 81 while point.x < frame.width { 82 grids.append(Grid(upperLeft: point)) 83 point.x = point.x + 30 84 } 85 point.x = 20 86 point.y = point.y + 20 87 } 88 } 89 // gridsの各要素について、グリッドを描画する 90 override func draw(_ rect: CGRect) { 91 let path = UIBezierPath(rect: bounds) 92 path.lineWidth = 0.5 93 UIColor.gray.set() 94 95 for grid in grids { 96 path.move(to: grid.upperLeft) 97 path.addLine(to: grid.upperRight) 98 path.addLine(to: grid.lowerRight) 99 path.addLine(to: grid.lowerLeft) 100 path.close() 101 } 102 path.stroke() 103 } 104 required init?(coder aDecoder: NSCoder) { 105 fatalError("init(coder:) has not been implemented") 106 } 107}

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

環境
Xcode Version 9.2 (9C40b)
Swift Version 4.0.3

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

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

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

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

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

guest

回答1

0

gridsは初期状態でのUIViewの大きさに合わせて作られていますので、UIViewの大きさが変わった時に作り直す必要がありますね

投稿2018/03/19 07:38

MasakiHori

総合スコア3384

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

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

wai21

2018/03/19 07:47 編集

小さいキャンバスと大きいキャンバスの入れ替えはViewController のsmall(_ sender: UIButton) と big(_ sender: UIButton) でそれぞれ行なっているのですが、CanvasView を新しく作り直しており、grids も作り直されていることを確認しました。 しかし、やはり大きいキャンバスのみグリッド線が描画されません。 UIBezierPath もしくはdraw(_ rect: CGRect) に何か制限があるのでしょうか。 描画範囲の大きさや処理時間等。。。
MasakiHori

2018/03/19 08:19

見落としてました。 そのほかの部分ですとUIBezierPathはrectを指定せずに単にUIBezierPath()とした方がよさそうです。 が、アフィン変換などが掛かってなければboundsとframeの大きさは同じなので関係はなさそうです。
wai21

2018/03/19 08:39

確かに、rectを指定してもしなくても同様の結果でした。 スクロールビューのインディケーターは表示されるので、指定のサイズのビューは作成されているようでした。 ご回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問