回答編集履歴

2

追記

2019/05/27 02:17

投稿

takabosoft
takabosoft

スコア8356

test CHANGED
@@ -41,3 +41,87 @@
41
41
  print(countLines("あああ\nいいい\n")) // 3
42
42
 
43
43
  ```
44
+
45
+
46
+
47
+ -------------
48
+
49
+
50
+
51
+ ### 2019/05/27 追記
52
+
53
+
54
+
55
+ 自動改行も含むということで、UITextViewのクローンを生成し(フォントサイズなどを引き継げればなんでもいいです)、新しいテキストを流し込み、表示されている行数を調べるという手法で実装してみました。
56
+
57
+
58
+
59
+ ```swift
60
+
61
+ func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
62
+
63
+
64
+
65
+ let newText: String = (textView.text! as NSString).replacingCharacters(in: range, with: text)
66
+
67
+ return numberOfLines(orgTextView: textView, newText: newText) <= 3
68
+
69
+ }
70
+
71
+
72
+
73
+ private func numberOfLines(orgTextView: UITextView, newText: String) -> Int {
74
+
75
+
76
+
77
+ // UITextViewを複製します。iOS12では古いAPIを使っているというような警告がでます。
78
+
79
+ let cloneTextView = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: orgTextView)) as! UITextView
80
+
81
+
82
+
83
+ cloneTextView.text = newText + " "
84
+
85
+
86
+
87
+ let layoutManager = cloneTextView.layoutManager
88
+
89
+ let numberOfGlyphs = layoutManager.numberOfGlyphs
90
+
91
+ var numberOfLines = 0
92
+
93
+ var index = 0
94
+
95
+ var lineRange = NSRange()
96
+
97
+
98
+
99
+ while index < numberOfGlyphs {
100
+
101
+ layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
102
+
103
+ index = NSMaxRange(lineRange);
104
+
105
+ numberOfLines = numberOfLines + 1
106
+
107
+ }
108
+
109
+
110
+
111
+ return numberOfLines
112
+
113
+ }
114
+
115
+ ```
116
+
117
+
118
+
119
+ ろくに動作チェックはしていませんが、それとなく動いたところまでは確認しました。
120
+
121
+
122
+
123
+ 参考資料:
124
+
125
+ [Counting the number of lines in a UITextView, lines wrapped by frame size
126
+
127
+ ](https://stackoverflow.com/questions/5837348/counting-the-number-of-lines-in-a-uitextview-lines-wrapped-by-frame-size)

1

ちょっと修正

2019/05/27 02:17

投稿

takabosoft
takabosoft

スコア8356

test CHANGED
@@ -11,6 +11,8 @@
11
11
  ```swift
12
12
 
13
13
  func countLines(_ string: String) -> Int {
14
+
15
+ let string = string + " "
14
16
 
15
17
  var count = 0
16
18
 
@@ -30,10 +32,12 @@
30
32
 
31
33
  ```text
32
34
 
33
- print(countLines("")) // 0
35
+ print(countLines("")) // 1
34
36
 
35
37
  print(countLines("あああ")) // 1
36
38
 
37
39
  print(countLines("あああ\nいいい")) // 2
38
40
 
41
+ print(countLines("あああ\nいいい\n")) // 3
42
+
39
43
  ```