質問: fullText[startIndex..
回答: ### 前書き これは絵文字のことを**考慮していない**アプローチです。絵文字を考慮したものは回答の最下部に書いてみました。 ### 実装の流れ 今回実装したい機能の流れとしては 1. テキストがない場合抜ける 2. カーソルの位置が一番右にある場合抜ける 3. ターゲットとする文字の左側のインデックスおよび右側のインデックスの取得を行う。 4. 文字列の頭からターゲットの左側までの文字列およびターゲットの右側から文字列の最後尾の二つを取得する 5. 4で取得した文字列の結合 となります。 やることは前回した回答と同じような流れではあるのですが2の場合の抜け方とtargetOfLeftIndexおよびtargetOfRightIndexの取得方法が若干異なります。 ### 型の違い 前回の質問の段階でもっと丁寧にしておけばと思っていたのですが今回その機会がやってきたので少し説明をしておきます。今回出てくる定数のうちstartIndex, endIndex, targetOfLefindex, targetOfRightIndexはString.indexという少々特殊な型です。が一方でoffsetは基本的なIntになります。後述してあるfullText.countも同様にIntです。型が違うのでそのままたし算、ひき算は出来ません。 ### インデックスについて インデックスの認識というのは慣れるまで分かりにくいので図を用意してみました。 !explanation この図では文字「お」をターゲットとして定めた場合の各定数、プロパティの名称等をふんわりと図にしたものです(汚いのはご容赦ください)。この時のカーソルの位置は「お」の**左側**にあります。また左右混乱しやすいのでゆっくり確認してください。 offsetに関してですが、 カーソルが「あ」の**左側**にある場合 ``` offset == 0 ``` になります。 またカーソルが「く」の**左側**にある場合 ``` offset == 7 ``` となります。 カーソルが「こ」の**右側**にある場合は ``` offset == fullText.count ``` です。 ### コーディングの前準備 前回した回答との違いは実のところ2と3だけになります。 前回の質問では2の部分は「カーソルの位置が一番左にある場合抜ける」でした。 そしてカーソルの位置が一番左の時を表すコードは ``` offset == 0 ``` でした。では「カーソルが一番右にある場合」を表すコードはどうなるでしょうか。使えそうなのはすでに入力されている文字列の量です。 今度考える点は3です。これはつまりtargetOfLeftIndexとtargetOfRightIndexの関係性を考えることになります。これら二つはstartIndexを起点とするとtargetOfLeftIndexはstartIndexからoffset分移動したところにあると言えます。ではtargetOfRightIndexはというとstartIndexからoffset分移動したところにあるtargetOfLeftIndexの一つ隣になります。 以上を考えた上でコーディングを行なっていきます。 ### サンプルコード ``` //(1) guard let fullText = textView.text else { return } //(2) let count = fullText.count let offset = textView.selectedRange.location if offset >= count { return } //(3) let startIndex = fullText.startIndex let endIndex = fullText.endIndex let targetOfLeftIndex = fullText.index(startIndex, offsetBy: offset) let targetOfRightIndex = fullText.index(startIndex, offsetBy: offset + 1) //targetOfLeftIndexの一つ隣 //(4) let leftText = fullText[startIndex..= count { return } //(2) //文字列の最初のインデックス情報 let startIndex = fullText.utf16.startIndex //カーソルのインデックス情報 let cursorIndex = fullText.utf16.index(startIndex, offsetBy: offset) //文字列の最初からカーソルまでの文字列 let leftText = fullText[startIndex..