Category: iOS

Swift4:UITextView制御(再修正)

placeholderの制御に関して、解決方法がわかりました。

解決方法

  1.  Z.yUserNote.endEditing(true)を付加
    ①このアプリの場合、表の行がクリックされたとき、UITextViewに対して.endEditing(true)を実行します。
    ②textViewDidBeginEditingやtextViewDidEndEditiongでフラグを立て、これを監視する必要はありません。.endEditing(true)を実行すると、UITextViewからキャレットが移動されます。
  2. 設定された値の変更(save)
    当該イベントが終了したときではなく、ほかのイベントがキックされたとき、実施しています(従来通り)。これは、textViewDidEndEditiongで実施しても、結局、ほかのイベントがはじまったときに監視しなければならないからです。
  3. キーボードを閉じる処理
    iPadでは問題がないのですが、iPhone SEだと入力対象エリアがキーボードで隠れてしまい、確認ができないからです。
    ①クリックされた直後にUITextFieldキーボードを閉じる。
    ②textViewDidEndEditingでUITextViewキーボードを閉じる。

@IBAction func ExecIBAGo2Click(){                        //<*Process when a row in UITableView is kicked*>
   self.ExecClickedRow(self.Z.qRow, pCount:0)            // 🔵🔵Click Process🔵🔵
}//🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳🐳
func ExecClickedRow(_ pRow:Int, pCount:Int) {//<*pCount>=0: Click Process pCount<0: Update process after a row removal*>
   Z.ySearchbar.resignFirstResponder()                    //Close a keyboard for UITextField(Search).
   if pRow < 0 || pRow >= Z.rcArray.count || Z.rcArray.count <= 0 {//Available?
       Z.qRow          = -999                           //Out of the Array.
       return                                           //♻️return♻️ Go back.
   } else { }                                           //
   if pCount >= 0 {                                     //1st click or 2nd click and later?
       ExecSetValues2Array(Z.qRow//Save the previous values in tow UITextField and one UITextView.
   } else { }                                           //
   Z.yUserNote.endEditing(true)                         //End editing UITextView.
   Z.qRow              = pRow                           //Set the target row.
   Z.maybeLastRow      = pRow                           //Set the target row just in case.
   ExecSetDateTitleMemo(Z.qRow)                         //Draw Date & Time 📅Group 📚Title.
   Z.sortURL           = Z.rcArray[Z.qRow][Z.fURL] as! String//Set the current URL in case of clicking the screen shot.
   Z.yTableView.selectRow(at: IndexPath(row: Z.qRow, section: 0), animated: true, scrollPosition: .top)//Select the row.
   Z.yTableView.reloadData()                           //🍋🍋reloadData🍋🍋    }//====================================================//
func ExecSetDateTitleMemo(_ pRow:Int) {                //<*Set values to UITextView*>
   Z.yUserNote.text    = “”                            //
   if pRow < 0 || pRow >= Z.rcArray.count { return }   //♻️return♻️ The previous row is out of the array
   else { }                                            //
   Z.yGroup.text       = (Z.rcArray[pRow][Z.fGroup] as! String)//Set Group value.
   Z.yTitle.text       = (Z.rcArray[pRow][Z.fTitle] as! String)//Set Title value.
   let wImage:UIImage  = Com.CallResizeCapturedImage((Z.rcArray[pRow][Z.fScreen] as! UIImage), pImageView:Z.yScreen)//Set Screenshot.
   Z.yScreen.image     = wImage                        //
   let wCheck:NSMutableAttributedString?   = (Z.rcArray[pRow][Z.fNote] as? NSMutableAttributedString) //Check UserNote.
   if wCheck == nil || (wCheck?.string.count)! <= 0  { //Set the placeholder if the caret is out of the UITextView & no data.
       if wkEdited == “” { Z.yUserNote.attributedText = wkPlaceholder }//
       else              {  }                              //
   } else { Z.yUserNote.attributedText = Z.rcArray[pRow][Z.fNote] as! NSMutableAttributedString }//Set UserNote.
}//========================================================//
func textViewDidBeginEditing(_ textView: UITextView) {     //<*Watch the UITextView(Note Area)*>
   if Z.yUserNote.text == wkPlaceholder.string {           //Placeholder string?
      Z.yUserNote.text            = “”                     //No data.
      Z.yUserNote.textColor       = UIColor.black</b>      //Black. (Placeholder: Gray)
   } else {  }                                             //
}//========================================================//
func textViewDidEndEditing(_ textView: UITextView) {       //<*Watch the carsor (caret)*>
  Z.yUserNote.resignFirstResponder()                      //Close keyboard for UITextView(UserNote).
}//========================================================//

Screenshot 2018-06-12 07.34.11

 

Swift4:UITextViewの制御(修正版)

UITextViewをハンドリングする方法についての忘備録です。

要点は次の2点です。

placeholderのハンドリングと変更内容のsaveタイミング

  1. キャレットをUITextViewの外側に出さないとplaceholderの設定が自動的に行われません。外に出さないと、設定したplaceholderが文字列と認識される問題が発生します。解決方法のひとつとして、たとえばUITextFieldに文字列を置き、selectAllで選択すれば、この問題を解消できます。これには、副作用があり、selectAllのあとにキャレットを最初の文字列の前に持っていっても、pasteのポップアップが表示されてしまう問題が起きます。
  2. ない知恵を出し切っていろいろ考えたのですが、結局、次のようにしました。①UITextViewにキャレットがある間はplaceholderを表示しない仕様とする。
    ②キャレットをユーザーがUITextViewの外側に移動した場合、直前のUITextViewの変更内容をsaveし、次からplaceholderが表示される仕様とする。
    ③表のクリックやボタンのクリックなどのアクティビティが起きた場合、直前のUITextViewの変更内容をsaveする。

上記paste popup画面については、pasteできる状態にあるから表示されると推測しています。よって、copy and pasteの機能追加をしてこのpasteを取り消せばいいのではないか、と考えています。以前、macOSでは、copy and pasteを実装したことがあります。その経験からするとそんなにむずかしい話ではありません。少し余裕ができたら検討したいと思います。

 

@IBAction func ExecIBAGo2Click(){//<*Process when a row in UITableView is kicked*>
        self.ExecClickedRow(self.Z.qRow, pCount:0)                 // 🔵🔵Click Process🔵🔵
   }//=============================================================//
    func ExecClickedRow(_ pRow:Int, pCount:Int) {                  //<*pCount>=0: Click Process pCount<0: Update process after a row removal*>
        if pRow < 0 || pRow >= Z.rcArray.count || Z.rcArray.count <= 0 {//Available?
            Z.qRow          = -999                                  //Out of the Array.
            return                                                  //♻️return♻️ Go back.
        } else { }                                                  //
        if pCount >= 0 {                                            //1st click or 2nd click and later?
            ExecSetValues2Array(Z.qRow)                             //Save the previous values in tow UITextField and one UITextView.
        } else { }                                                  //
        Z.qRow              = pRow                                  //Set the target row.
        Z.maybeLastRow      = pRow                                  //Set the target row just in case.
        ExecSetDateTitleMemo(Z.qRow)                                //Draw ⏰Date & Time 📅Group 📚Title.
        Z.sortURL           = Z.rcArray[Z.qRow][Z.fURL] as! String  //Set the current URL in case of clicking the screen shot.
        Z.yTableView.selectRow(at: IndexPath(row: Z.qRow, section: 0), animated: true, scrollPosition: .top)//Select the current row.
       Z.yTableView.reloadData()                                    //🍋🍋reloadData🍋🍋
    }//=============================================================//
    func ExecSetDateTitleMemo(_ pRow:Int) {                         //<*Set values to UITextView*>
        Z.yUserNote.text    = “”                                    //
        if pRow < 0 || pRow >= Z.rcArray.count { return }           //♻️return♻️ The previous row is out of the array.
        else { }                                                    //
        Z.yGroup.text       = (Z.rcArray[pRow][Z.fGroup] as! String)//Set Group value.
        Z.yTitle.text       = (Z.rcArray[pRow][Z.fTitle] as! String)//Set Title value.
        let wImage:UIImage  = Com.CallResizeCapturedImage((Z.rcArray[pRow][Z.fScreen] as! UIImage), pImageView: Z.yScreen)//Set Screenshot.
        Z.yScreen.image     = wImage                                //
        let wCheck:NSMutableAttributedString?   = (Z.rcArray[pRow][Z.fNote] as? NSMutableAttributedString) //Check UserNote.
        if wCheck == nil || (wCheck?.string.count)! <= 0  {         //Set the placeholder if the caret is out of the UITextView and no data.
            if wkEdited == “” { Z.yUserNote.attributedText = wkPlaceholder }//
            else              {  }                                  //
        } else { Z.yUserNote.attributedText = Z.rcArray[pRow][Z.fNote] as! NSMutableAttributedString }//Set UserNote.
    }//=============================================================//
    func textViewDidBeginEditing(_ textView: UITextView) {          //<*Watch the UITextView(Note Area)*>
        if Z.yUserNote.text == wkPlaceholder.string {               //Placeholder string?
            Z.yUserNote.text            = “”                        //No data.
            Z.yUserNote.textColor       = UIColor.black             //Black. (Placeholder: Gray)
            wkEdited                    = “🍎”                      //🍎Begin Editing with no data.
        } else {                                                    //
            wkEdited                    = “🍎”                      //🍎Begin Editing with data.
        }                                                           //
    }//=============================================================//
    func textViewDidEndEditing(_ textView: UITextView) {            //<*Watch the carsor (caret)*>
        if Z.yUserNote.text.count <= 0 || Z.yUserNote.text == wkPlaceholder.string {//No data or placeholder?
            wkEdited                    = “”                        //Clear the Edit sign.
        }else if wkEdited == “🍎” {                                 //Going on editing the UITextView?
            wkEdited                    = “⛔️”                      //⛔️End.
        } else { }                                                  //
    }//=============================================================//

Screenshot 2018-06-10 13.32.22

Swift4:viewを中心に置く

iPhoneとiPadの機種毎のサイズに適合するようにviewを中心に置く方法をあれこれ考えました。

最初、すべてのオブジェクトを配列に定義し、x / yで動かしてみたのですが、よくよく考えたらUIViewで定義しておけば、個々のオブジェクトを動かす必要がありません。

しかし、iPadの場合、画面サイズが大きいのでローテーションに対応すべきで、そうなるとLandscapeだけに対応すればいいという安直回答は不適です。そう思いながら実装してみると、ローテーションするたびにシフト幅が加算されてしまうバグが出てしまい、結局、オブジェクトの全体サイズを知る必要がありました。

ない知恵を絞った結果、見えないUIButtonを下側に設置し、これから計算すれば面倒な計算をしなくていいとわかりました。

Screenshot 2018-06-03 10.35.01

Screenshot 2018-06-03 10.51.27

Screenshot 2018-06-03 11.03.05

Swift:modal delegate vs. storyboard ID

iOSの画面遷移の仕方がよくわかっていないという根本的な問題は一旦横に置いて、結局、storyboard IDで遷移した方が簡単です。

それに、独立性が高いので、書き方・考え方だけでなく、呼び出しも簡単です。結局、全部、storyboard IDで遷移する方法に書き換えました。もうひとついい点は、entry pointを設定しなくても遷移できるので、UIを一箇所にまとめて管理できます。

Screenshot 2018-05-30 21.27.23

Swift4:UITextView文字列へのリンク設定

UITextViewの文字列にリンク(URL)を設定する方法は、基本的には、色付の機能と同じ手順になります。

注意点は次の通りでした。

  • UITextViewの選択された文字列を覚えておく。
  • リンクを入力してもらう。
  • 選択された文字列にリンクを設定し、色付を行う。
    • ここでは、NSMutableAttributedStringでハンドリングする必要があり、UITextView⇆UILabel間で変換しないと、うまくいきません。
    • また、リンクを取得したあと、どこでその処理をキックするかにより色の制御ができません。

Screenshot 2018-05-29 07.10.38

Swift4:UIImageのリサイズ

リサイズするとボケる、あるいはリサイズの仕方はどうすればいいの?

スクリーンショットを撮ってリサイズする機能を実装してはじめて成程と納得しました。ボケることについては、画像が粗くなる(画像が劣化する)!?で言及されています。

実際のリサイズのコードについては、【Swift4】UIImageで画像のサイズ変更、指定した倍率で拡大/縮小に書いてある通りです。そのままで動きます。

注意:拡大・縮小比率を求めるとき、結果から-0.002すれば、該当図形枠からはみださずに収まりました。高さからマイナスして計算したのですが、それではうまく行きませんでした。参考まで。

Screenshot 2018-05-29 01.18.53