34365


cellのaccessoryで付けることができるDetail（iの丸マーク）を押すと、画面遷移できる仕組みにしたいのですが、どのように関連付けをしたり、コードを書けばいいのかわかりません。

[![画像の説明をここに入力](https://i.stack.imgur.com/s20dh.png)](https://i.stack.imgur.com/s20dh.png)

[![画像の説明をここに入力](https://i.stack.imgur.com/8lksi.png)](https://i.stack.imgur.com/8lksi.png)

関連付けはしてみたものの、マークを押しても全く動きません。

* * *

↓変更後

[code]

    import UIKit
    
    class ViewController: UIViewController, UITableViewDataSource, TestDelegate {
    
    @IBOutlet weak var testTableView: UITableView!
    
    
    //表示データ
    var dataList = ["","","","","","","",""]
    
    //データを返すメソッド（スクロールなどでページを更新する必要が出るたびに呼び出される）
    func tableView(_ tableView:UITableView, cellForRowAt indexPath:IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for:indexPath) as UITableViewCell
        cell.textLabel?.text = dataList[indexPath.row]
    
        return cell
    }
    
    //データの個数を返すメソッド
    func tableView(_ tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
        return dataList.count
    }
    
    
    //削除ボタン
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
        dataList.remove(at: indexPath.row)
        testTableView.deleteRows(at: [indexPath], with: .fade)
        }
    }
    
    
    func TableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = "No. \(indexPath.row)"
        // 偶数行にDetailボタンを表示する。
        if indexPath.row & 0x01 == 1 {
            cell.accessoryType = .detailButton
        }
    
        return cell
    }
    
    // UITableViewDelegate
    // アクセサリボタンをタップしたら……
    func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
        // セグエGoNextを実行する。
        performSegue(withIdentifier: "GoNext", sender: nil)
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    
       //自作セルをテーブルビューに登録する。
        let testXib = UINib(nibName:"TestTableViewCell", bundle:nil)
        testTableView.register(testXib, forCellReuseIdentifier:"TestCell")
    }
    
    //デリゲートメソッド
    func textFieldDidEndEditing(cell: TestTableViewCell, value:String) {
        //変更されたセルのインデックスを取得する。
        let index = testTableView.indexPathForRow(at: cell.convert(cell.bounds.origin, to:testTableView))
    
        //データを変更する。
        dataList[index!.row] = value
        print(dataList)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
    }
    
[/code]

@nagonsoftware さんの教えていただいた通りにやったつもりなのですが、iの丸を押しても画面遷移できません。  
上に載せたコードは、ViewControllerのものです。  
TableViewのCellはTextFieldをタップするだけで簡単に入力できる仕組みにしています。  
この仕組みのコードを書いているから、画面遷移できないのかなと思い、色々コードを書く順番を並び替えたりしたのですが、ダメでした。。  
何が原因で画面遷移ができないのか、さっぱりわかっていません。


CC BY-SA 3.0
2017-04-28T17:31:22.230
34362
2017-04-30T03:49:12.113
2017-04-29T15:23:21.423
22835
22835
question
swift uitableview
cellのaccessoryで付けることができるDetailを押して、画面遷移したい


Storyboard上でセグエを正しく設定できていれば、コードは書かなくても普通に遷移できるようになります。セグエの設定手順を見直して、正しく設定し直すか、それでダメであればTable
Viewの方が正しくPrototype Cellを表示できていない可能性があります。

  1. まずは普通にアクセサリーを設定したPrototype Cellから遷移先にcontrol-ドラッグします。

[![control-
ドラッグ](https://i.stack.imgur.com/kFjri.png)](https://i.stack.imgur.com/kFjri.png)

  2. ドラッグを終了した時に表示されるポップアップメニューの中でAccessory Actionの中から好きな遷移スタイルを選びます。

[![Accessory
Action](https://i.stack.imgur.com/KMMWx.jpg)](https://i.stack.imgur.com/KMMWx.jpg)

Xcode8.3.2でビルドして、Detailのⓘから遷移先に指定したViewControllerに確実に遷移できるのは確認しました。実際には遷移先になんらかの情報を渡す必要があるでしょうから、その分のコードは追加する必要があるでしょうが、それはなくても「全く動きません」と言うことはないはずです。

上記の手順に従ってやり直してもダメなら、そもそもTable View側で正しくPrototype
Cellを表示していない可能性がありますので、その辺の情報を詳しく提示していただかないとなんとも言えません。コメントを付けるかご質問を編集して情報を追記してください。

* * *

なお、右のView Controllerから左のTable Viewを含むView
Controllerに向けたセグエが存在するようですが、これだと「元の画面に戻る」のではなく、「新しい画面を別に作って新しい画面の方に遷移する」と言う動作になります。それは意図した動作ではないが直し方がわからないと言ったことがあれば、別質問としてご投稿ください。


CC BY-SA 3.0
2017-04-28T20:22:07.280
34364
2017-04-28T20:22:07.280
13972
34362
answer


**`UIStoryboardSegue`による画面遷移を、Storyboardの編集でなく、プログラムで実行するには、どうすればいいか？**  
質問者さんが求めているものは、上の質問に帰結することに、まず気づくことが大事です。  
セグエのみならず、Storyboard上の編集は、すべてプログラムコードで記述できる。それが基本です。[UIStoryboard](https://developer.apple.com/reference/uikit/uistoryboard)、[UIStoryboardSegue](https://developer.apple.com/reference/uikit/uistoryboardsegue)、[UIViewController](https://developer.apple.com/reference/uikit/uiviewcontroller)これら3つのリファレンスを読めば、どういうプロパティ、メソッドを使えば、セグエを編集できるかを学習できます。  
`UITableViewDelegate`のメソッド`tableView(_:accessoryButtonTappedForRowWith:)`を使うと、セルのアクセサリをタップした時の処理を記述できます。ここに、セグエを実行して、画面遷移するコードを記述すると、DetailButtonをタップして、画面遷移することができます。

* * *

Storyboard上で、セグエをオブジェクト間に結ぶとき、ボタンとViewController、テーブルセルとViewControllerの間に結ぶことが多いと思いますが、本件では、ViewControllerとViewController間を結んでください。  
[![画像の説明をここに入力](https://i.stack.imgur.com/QhMia.png)](https://i.stack.imgur.com/QhMia.png)  
セグエを結んだら、セグエのIdentifierに、任意の文字列をつけます。つけないと、プログラムからセグエを識別することができません。（ここでは`GoNext`とします）  
[![画像の説明をここに入力](https://i.stack.imgur.com/zMpGH.png)](https://i.stack.imgur.com/zMpGH.png)  
そして、テーブルに関する処理をする、以下のコードを記述します。

[code]

    import UIKit
    
    class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
        // UITableViewDataSource
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 12
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
            cell.textLabel?.text = "No. \(indexPath.row)"
            // 偶数行にDetailボタンを表示する。
            if indexPath.row & 0x01 == 1 {
                cell.accessoryType = .detailButton
            } else {
                cell.accessoryType = .none
            }
    
            return cell
        }
    
        // UITableViewDelegate
        // アクセサリボタンをタップしたら……
        func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
            // セグエGoNextを実行する。
            performSegue(withIdentifier: "GoNext", sender: nil)
        }
    
        // セグエ実行時の処理は、ここに記述。
        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            // Do Anything
        }
    
    }
    
[/code]

`UIViewController`のメソッド`performSegue(withIdentifier:sender:)`が、セグエをプログラムで実行する、具体的なメソッドです。

* * *

質問と直接関係ないことで、気づいたことがあるので、アドバイスします。  
添付なさったStoryboardのスクリーンショットを拝見しましたが、A View Controllerと、B View
Controllerの間に、相互にセグエを結んでいますね？実は、これはやってはいけない典型的な例です。これをやってしまうと、

インスタンスa（A View Controller）→ インスタンスb（B View Controller）→ インスタンスa'（A View
Controller）→ インスタンスb'（B View Controller）→ インスタンスa''（A View Controller）→
インスタンスb''（B View Controller）→ ……

このように、新しいインスタンスを作りながら画面遷移していき、けっして元のインスタンスに戻ることがありません。意図しない挙動になりますし、メモリの圧迫、ひいてはメモリリークの原因になります。  
セグエ遷移元に戻るには、 **Unwind Segue**
を使ってください。これも、ネット検索すれば、いくつも情報がヒットします。「サンプルコードがObjective-
Cだから」という言い訳で、検索をサボってはいけません。（現在のところ）Swiftのコードであっても、ブリッジでObjective-
CのAPIを呼んでいるので、言語に関係なく、概要はまったく同じです。


CC BY-SA 3.0
2017-04-28T23:23:22.103
34365
2017-04-30T03:49:12.113
2017-04-30T03:49:12.113
18540
18540
34362
answer