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

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

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

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

Q&A

解決済

UItextViewで指定行数以降の入力を不可にしたい

ttah
ttah

総合スコア35

Swift

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

1回答

0グッド

1クリップ

605閲覧

投稿2019/05/21 08:47

実現したいこと

UItextViewで3行までしか入力を出来ないない様にしたいです

今考えている実現方法は

func textViewDidChange(_ textView: UITextView){ 現在の行数の取得する if 現在の行数>3 { キーボードの入力を不可にする  } }

と考え
現在の行数の取得方法
キーボードの入力を不可にする方法
を調べましたがわかりませんでした

質問

上記の方法が正しければ実現するコードはどの様になるでしょうか?
また上記の方法で実現出来なければどのようなコードで実現できるでしょうか?

余談かもしれませんが試した事として

message.textContainer.maximumNumberOfLines = 3 message.textContainer.lineBreakMode = .byTruncatingTail

は、表示は3行になりましたが表示されていないだけで実際には文字は入力された状態になっていて自分が実現したいところはではいけませんでした

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

fuzzball

2019/05/21 09:02

行数は物理行ですか?論理行ですか?
ttah

2019/05/21 10:24

閲覧ありがとうございます 画面に表示されている見た目そのままの行数です。 (今自分が調べた範囲ではこれを物理行と言っているサイトと逆もあったのでどっちか答えられず↑の表現になりましたすいません) 方針ありがとうございます。リンクと他サイトで調べましたがまだ正解のコードがまだ解からない状態です、よろしくお願いします
fuzzball

2019/05/22 00:28

https://teratail.com/questions/73665 今回の場合は「文脈2」になるので物理行ですね。 やることは二つです。 (a) 制限に引っかかったら入力出来なくする (b) 「三行を超える」の判定をする (a)は上記のデリゲートメソッドを使用します。 (b)は面倒くさそう?(文字数制限ならよく見かけますが)
ttah

2019/05/22 09:31

やる事は理解しました 入力出来なくする方法は textField.resignFirstResponder() でも良いですが 閉じずにキーを押しても反応しなくなる方法があればそちらを利用したいと考えています 文字数制限は私もよく見かけたのですが行数の制限の情報はあまり見かけられず公式を理解できないレベルの自分はつまずてしまいました。 (b)の参考コードを書いて頂くことはかなりご負担をおかけしてしまうレベルでしたでしょか?

回答1

0

ベストアンサー

(b)の参考コードを書いて頂くことはかなりご負担をおかけしてしまうレベルでしたでしょか?

代打ですがどうぞ。
*丸投げはよくありませんので、まずはご自分で調べたり試したりしてみましょう。

swift

1func countLines(_ string: String) -> Int { 2 let string = string + " " 3 var count = 0 4 string.enumerateLines { _, _ in 5 count += 1 6 } 7 return count 8}

text

1 print(countLines("")) // 1 2 print(countLines("あああ")) // 1 3 print(countLines("あああ\nいいい")) // 2 4 print(countLines("あああ\nいいい\n")) // 3

2019/05/27 追記

自動改行も含むということで、UITextViewのクローンを生成し(フォントサイズなどを引き継げればなんでもいいです)、新しいテキストを流し込み、表示されている行数を調べるという手法で実装してみました。

swift

1 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { 2 3 let newText: String = (textView.text! as NSString).replacingCharacters(in: range, with: text) 4 return numberOfLines(orgTextView: textView, newText: newText) <= 3 5 } 6 7 private func numberOfLines(orgTextView: UITextView, newText: String) -> Int { 8 9 // UITextViewを複製します。iOS12では古いAPIを使っているというような警告がでます。 10 let cloneTextView = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: orgTextView)) as! UITextView 11 12 cloneTextView.text = newText + " " 13 14 let layoutManager = cloneTextView.layoutManager 15 let numberOfGlyphs = layoutManager.numberOfGlyphs 16 var numberOfLines = 0 17 var index = 0 18 var lineRange = NSRange() 19 20 while index < numberOfGlyphs { 21 layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange) 22 index = NSMaxRange(lineRange); 23 numberOfLines = numberOfLines + 1 24 } 25 26 return numberOfLines 27 }

ろくに動作チェックはしていませんが、それとなく動いたところまでは確認しました。

参考資料:
Counting the number of lines in a UITextView, lines wrapped by frame size

投稿2019/05/24 08:07

編集2019/05/27 02:17
takabosoft

総合スコア8337

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

fuzzball

2019/05/24 08:10

改行による行数ではないのです‥。
takabosoft

2019/05/24 08:11

ああ、自動改行も含むのですね。了解です。
takabosoft

2019/05/24 08:59

また来週時間があれば調べますが、 例えば裏にダミーのUITextViewを仕込んでおいて、文字列を流し込み、期待する行数より多かったらtextView(_:shouldChangeTextIn:replacementText:)でfalseを返せばいけそうかなという予感はしました。
ttah

2019/05/26 02:57

takabosoft様回答有難うございます 自動改行も含む事を明示しておらず説明不足でした。 (処理方法が違うとは思いませんで考慮不足でした) 回答から func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool{ func countLines(_ string: String) -> Int { let string = string + " " var count = 0 string.enumerateLines { _, _ in count += 1 } return count } if countLines(textView.text) > 3{ textView.resignFirstResponder() } を試みたところ 4行目に差し掛かると無事入力不可になりました しかしその後文字を削除して3行にしようとしてもdeleteも受け付けなくなりましたので、この解決方法と自動改行への対応をダミーUITextViewの使用を含め試みています(がまだ解決出来ていません)
ttah

2019/05/27 10:08

有難うございます。 問題なく完璧に動作しました。 コードの理解はまだほとんど出来ていませんのでこれから理解に努めます。 お手数おかけしましたが、諦めかけていたので非常に助かりました。

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Swift

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