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

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

ただいまの
回答率

90.48%

  • Swift

    7487questions

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

  • Xcode

    4218questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

  • iOS

    4092questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

  • TableView

    123questions

    TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。

UITableView 表示の仕組み

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 626

haruka-t

score 79

import UIKit

class ViewController: UIViewController, UITableViewDelegate/*UITabBarDelegate*/,UITableViewDataSource {

  @IBOutlet weak var mytableView: UITableView!

  var kei = [String]()




  override func viewDidLoad() {
    super.viewDidLoad()

    mytableView.delegate = self
    mytableView.dataSource = self

  }


  @IBAction func addbtr(_ sender: Any) {


   let alert = UIAlertController(title: "タイトル", message: "メッセージ", preferredStyle: .alert) 

      let okAction = UIAlertAction(title: "OK", style: .default, handler: {
         (action:UIAlertAction!) -> Void in

         if let textFields = alert.textFields {

            for textField in textFields {
               self.kei.append(textField.text!) 
               self.kei.append("cell 追加 ボタン")
            }
            self.mytableView.reloadData()

         }
      })
      alert.addAction(okAction)

      let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
      alert.addAction(cancelAction)

      alert.addTextField(configurationHandler: {(textField: UITextField!) -> Void in
         textField.placeholder = "テキスト"
      })


      alert.view.setNeedsLayout() 
      self.present(alert, animated: true, completion: nil)

   }

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return kei.count
  }


   func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {

      switch indexPath.row {

      case 1:
         return indexPath;


      default:
         return nil;
      }
   }

   func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
      if kei.count > (indexPath.row + 1) {
         return nil
      }
      return indexPath
   }

   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

      let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

      cell.textLabel?.text = kei[indexPath.row]
      cell.textLabel?.textColor = UIColor.red
      cell.backgroundColor = UIColor.black

      if kei.count > (indexPath.row + 1) {
         // セルの選択不可にする
         cell.selectionStyle = UITableViewCellSelectionStyle.none
         cell.textLabel?.textColor = UIColor.black
         cell.backgroundColor = UIColor.yellow
         } else {
         // セルの選択を許可
         cell.selectionStyle = UITableViewCellSelectionStyle.blue
         }

      return cell
   }

   func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) -> IndexPath? {


     if kei[indexPath.row] != "cell 追加 ボタン" {
         return [indexPath.row]
     }else /*if (self.kei.append("cell 追加 ボタン"))*/{

       let alert = UIAlertController(title: "タイトル", message: "メッセージ", preferredStyle: .alert)


    let okAction = UIAlertAction(title: "OK", style: .default, handler: {
      (action:UIAlertAction!) -> Void in


      if let textFields = alert.textFields {


        for textField in textFields {
          self.kei.insert(textField.text!, at:self.kei.count - 1)

        }
          self.mytableView.reloadData()

      }
    })
    alert.addAction(okAction)

    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    alert.addAction(cancelAction)

    alert.addTextField(configurationHandler: {(textField: UITextField!) -> Void in
      textField.placeholder = "テキスト"
    })


    alert.view.setNeedsLayout() 
    self.present(alert, animated: true, completion: nil)

      return indexPath
      }

  }

  func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
      self.kei.remove(at: indexPath.row)
      tableView.deleteRows(at: [indexPath], with: .fade)
   }
  }

   func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

      let delete = UITableViewRowAction(style: .normal, title: "削除") {ation, index in
         self.kei.remove(at: (indexPath.row))
         tableView.deleteRows(at: [indexPath], with: .fade)
   }
      delete.backgroundColor = .red

      let edit = UITableViewRowAction(style: .normal, title: "編集") { action, index in

         let alert = UIAlertController(title: "タイトル", message: "メッセージ", preferredStyle: .alert)

         let okAction = UIAlertAction(title: "OK", style: .default, handler: {
            (action:UIAlertAction!) -> Void in

            if let textFields = alert.textFields {

               for textField in textFields {
                  self.kei[indexPath.row] = textField.text!
                  //self.kei.append(textField.text!)
               }
               self.mytableView.reloadData()

            }
         })
         alert.addAction(okAction)

         let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
         alert.addAction(cancelAction)

         alert.addTextField(configurationHandler: {(textField: UITextField!) -> Void in
            textField.placeholder = "テキスト"
         })


         alert.view.setNeedsLayout() 

         self.present(alert, animated: true, completion: nil)
         print("edit")
      }
      edit.backgroundColor = .orange

      return [delete,edit]
      }


  func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {

   if kei.count > (indexPath.row + 1) {
      return true
   }else{
    return false
  }
   }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

}

やりたいこと
[+]ボタンを押した時にアラートテキストで題名を入力し[cell 追加ボタンと]と一緒に追加したい

困っていること
前まではボタンからでもアラートテキストで入力した内容がcellに追加できたのですが色々コードを書き足している内に出来なくなりました。
それと[cell 追加ボタン]がどういう仕組みでtableViewに表示されているのかが分からないのでボタンの中に[cell 追加ボタン]の処理の書き方が分からなく困っています。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ykws

    2017/09/29 07:35

    質問のタイトルは「UITableView の表示する仕組みについて」の方が適切な気がしました。

    キャンセル

回答 2

checkベストアンサー

+1

それと[cell 追加ボタン]がどういう仕組みでtableViewに表示されているのかが分からないので+ボタンの中に[cell 追加ボタン]の処理の書き方が分からなく困っています。

UITableView の表示は func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell の部分で制御しています。
これは UITableView を表示するときに indexPath セルの位置を受け取り、そこに表示する UITableViewCell セルの内容を返し、それが画面上に反映される仕組みになっています。

この中で下記のように、配列 kei の値をセルの位置に合わせて表示しているのが読み取れると思います。

cell.textLabel?.text = kei[indexPath.row]

自分がやったこととしては宣言文をvar kei = [String]()にするとcell上の"cell 追加 ボタン"をを消すことが出来ます。

なので、 @blakekei さんの試した方法で配列 kei の値を変更すれば UITableView の表示にも反映される理屈になります。

追加していく順番を3,2,1ではなく1,2,3のようにしたいのですがその場合どうしたらいいのでしょうか?
appendにすると1,2,3にはなるのですがそうすると[cell 追加 ボタン]の下に追加されてしまいます。

これを踏まえて、表示順は配列のデータ順なので、配列の末尾の前にデータを追加していけば期待するデータ順となり、表示順もそのようになります。

self.kei.insert(textField.text!, at:self.kei.count - 1)

意味合いの異なるセルはセクションを分けるのも方法の一つだと思います。
そうすると可変の配列と固定の配列を別で管理することになるので、 append が有効になります。

参考: UITableView Section の設定

続いて、セルのタップ制御を現状は下記のように最後のセルしか反応しないように書いていますので、

kei.count > (indexPath.row + 1)

「cell 追加 ボタン」全てに反応させるには、例えば、以下のような条件に変更すれば反応します。

kei[indexPath.row] != "cell 追加 ボタン"

ただ、 UI 的に不自然な気はします。
セルの追加は画面右上の「+」ボタンだけで十分では?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/29 08:26

    そのようなやり方があったんですね!
    私場合、昨日ダメごとでこのようにコードを書いたら1,2,3,4と表示させることが出来ました。
    self.kei.insert(textField.text!, at: indexPath.row)
    でも@ykwsさんのコードの方がコードとして正しそうなのでself.kei.insert(textField.text!, at:self.kei.count - 1)を使いたいと思います。
    それとなんですが、今の時点だと一番下の[cell 追加 ボタン]でしかcellを追加できないのですが、どうすれば他の[cell 追加 ボタン]でもcellを追加できるのでしょうか?
    私なりに考えられることしてはfunc didSelectRowAtIndexPathのif 文のelseの部分に self.kei.append("cell 追加 ボタン")を関連させることが出来れば全ての[cell 追加 ボタン]にcell追加する機能を付けれると思うのですがどのように関連させればいいか分からないのでもし宜しければ教えて頂けないでしょうか?

    キャンセル

  • 2017/09/29 09:57

    回答に追記しました。
    基本的にはその考え方であっています。ただ現状はセルの活性状態を制御しているので、その部分の条件を変えるのが妥当だと思いました。

    キャンセル

  • 2017/09/29 12:54

    typo があったので回答編集しました。
    当然、追記してもらったように配列外アクセスになりますね。

    キャンセル

  • 2017/09/29 12:55

    さそっく試して見たのですがビルドと+ボタンで追加するまでは大丈夫だったのですが[cell 追加 ボタン]で追加しようとすると画像のようなエラーが出てきたのですが他にも何か書き直さないといけなかったのでしょうか?

    キャンセル

  • 2017/09/29 13:09

    kei[indexPath.row] != "cell 追加 ボタン"
    上記のようにするとエラーは取れましたがやはり黄色の部分の[cell 追加 ボタン]は反応しませんでした。
    確かにcellを追加するだけなら[+]だけで十分だと思うのですが私としてはブロックごとに小分けにして、そのブロックで何か追加し忘れてもそのブロックにボタンがあるとあとでそのブロックにまたcellを追加できるのでその方が使い勝手がいいのかなと思いこのようにしたいと思いました。

    キャンセル

  • 2017/09/29 13:23

    willSelectRowAt と didSelectRowAtIndexPath の両方の条件を変更しても反応しないですか?

    キャンセル

  • 2017/09/29 13:46

    fun didSelectRowAtIndexPathしかやっていませんでした。なのでwillSelectRowAtにもそのようにして見たところ無事にやりたいことが出来ました。
    それと全く別な事なんですが@ykwsさんはswiftをどのように勉強しているのでしょか?毎回毎回、ものすごく分かりやすく、私の質問に対して全部回答してくださるのでもし宜しければ何を参考に勉強しているのか教えていただけると嬉しいです。一応私としては本気ではじめるiphoneアプリ開発などの本を3冊ほど購入し、勉強しているのですがこのような私の質問に対しては本には全然書いてなかったのでお聞きしたく質問しました。

    キャンセル

  • 2017/09/30 02:03

    Swift に関しては「Swift実践入門」で理解を深めました。ただ、この辺りの基本的な考え方は iOS の初期からそれほど変わってはいないと思うので、それまでの iPhone / iOS / Objective-C の経験が糧になっているなと感じています。改めて本棚を見返し、書籍をまとめてみました。参考までに。
    http://ykawashi7.hatenablog.com/entry/2017/09/30/015609

    キャンセル

  • 2017/10/01 11:59

    昨日早速教えて頂いた[Swift実践入門]の本を購入しました。hatenaブログで紹介していた他の書籍も購入したかったのですがまだ学生なのでとりあえず[Swift実践入門]を理解してからまた購入しようと思います。
    それとなんですがもし宜しければtableViewのチェックマークについて質問しましたので教えて頂けないでしょうか?qiita等で調べチェックマークはつけることは出来たのですが消すことが出来なく困っています。
    お忙しと思いますがもし宜しくお願い致します。
    https://teratail.com/questions/94578

    キャンセル

  • 2017/10/02 09:04

    let cell = tableView.cellForRow(at: indexPath)

    if cell!.accessoryType == .checkmark{
    cell!.accessoryType = .none
    }else{
    cell!.accessoryType = .checkmark
    }

    func didSelectRowAtIndexPathで上記のようなコードを追加したところ[cell 追加 ボタン]にチェックマークをつけたり、消したりは出来るようになったのですが[cell 追加 ボタン]と[+]ボタンで最初に追加したcell以外だけにチェックマークをつけたい場合どのようなif文を書けばいいのでしょうか?
    条件が二つなのでどうif文を書けばいいか分からなく困っています。

    キャンセル

  • 2017/10/02 11:17

    教えてもらった質問の方に回答しました。

    キャンセル

  • 2017/10/19 16:15

    先日の質問で教えて頂いた構造体を自分なりに使ってみたのですがコードのエラーはないのですがチェックマークがやっぱりcellを追加するとずれてしまうのでもし宜しければもう少し詳しく教えて頂けないでしょうか?
    一応cellのチェックマークずれについて新しく質問を立てました。
    https://teratail.com/questions/96997

    キャンセル

  • 2017/10/19 22:21

    @fuzzball さんの回答がすでに付いていて正しいと思いますので、補足のコメントをしました。

    キャンセル

  • 2017/10/22 13:27

    すいません、再度お聞きしたいことがあるのですがtableViewのスワイプ処理なんですが一般的右から左にスワイプする処理は出来るのですが左から右にスワイプする方法が分からなくて困っています。一応私なりにappleのドキュメントを参考にしleadingSwipeActionsConfigurationForRowAtを使って書いてみたのですがこれってios11じゃないとエラーが出るのでしょうか?
    もし宜しければ教えて頂けないでしょうか?
    一応スワイプに関する処理について質問を立てました。
    https://teratail.com/questions/97229

    キャンセル

  • 2017/10/23 09:31

    教えてもらった質問の方に回答しました。

    キャンセル

+1

今日自分も同じことで困っていました。でも解決できたので自分なりのやり方でアドバイスするので参考にして見てください。自分がやったこととしては宣言文をvar kei = [String]()にするとcell上の"cell 追加 ボタン"をを消すことが出来ます。その次にalerttextの中の
self.kei.insert(textField.text!, at:0)の部分をもう一行追加し、self.kei.insert("cell 追加ボタン 追加", at: 1)にするとおそらくやりたいことが出来ると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/28 10:53

    教えて頂いた通りにやったら出来ました。それとなんですがcell追加時に[apple 製品について 題名]と[cell 追加 ボタン]の間にcellを追加させたくself.kei.insert("cell 追加ボタン 追加", at: 1)にしたら間に追加することは出来たのですが追加していく順番を3,2,1ではなく1,2,3のようにしたいのですがその場合どうしたらいいのでしょうか?appendにすると1,2,3にはなるのですがそうすると[cell 追加 ボタン]の下に追加されてしまいます。

    キャンセル

  • 2017/09/28 11:28

    すいません。私自身もまだswiftについて勉強している途中なのでそこまではわかりません。しかし、私もそれについて気になるので@haruka-tさんに何度か回答をしている@ykwsさん にお聞きして見てはどうでしょうか?

    キャンセル

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

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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

  • Swift

    7487questions

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

  • Xcode

    4218questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

  • iOS

    4092questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

  • TableView

    123questions

    TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。