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

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

ただいまの
回答率

90.84%

  • Swift

    6485questions

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

tableView余白(Cellがない部分)タップで特定の処理をしたい。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 91

tyobigorou

score 301

お世話になります。
cellをタップすると、タップされたcellが存在するTableViewを編集対象にするという処理をしているのですが、
tableViewのcellが存在しない余白部分をタップした際に、同じような挙動を得る為に良い方法はないでしょうか?

tableViewのカスタムクラスを作成して、tableViewにタグを付け、touchesBeganをオーバーライドする方向で勧めてみたのですが、
カスタムクラス内からViewControllerのプロパティへのアクセス、メソッドを動かすところで詰まっています。
カスタムクラス内からviewControllerのプロパティ書き換え、メソッドを呼び出すにはどうすればよいでしょうか?

tapRecognizerは他の処理に使用しているので避けたいのですが、tapRecognizerを絡めないと無理でしょうか?

イメージ説明

class CustomTableView: UITableView {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        for touch: UITouch in touches {
            let tag = touch.view!.tag
            //let sender = touch.view!
            switch tag {
            case 3:
                let vc = ViewController() 
         // vc = nilなので記述方法が間違っている
         // 新規にVCを生成してるだけ?
                print("vc.targetTableView:",vc.targetTableView)
                vc.targetTableView = true
                print("vc.targetTableView:",vc.targetTableView)
            case 4:
                let vc = ViewController()
                print("vc.targetTableView:",vc.targetTableView)
                vc.targetTableView = false
                print("vc.targetTableView:",vc.targetTableView)
            default: break
            }
        }
    }
}
import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var jpWordChainTableView: UITableView!
    @IBOutlet weak var enWordChainTableView: UITableView!

    var targetTableView: Bool = true

    let jpWordChainItems = ["きつね","ねずみ","みみずく","くま","まんもす"]
    let enWordChainItems = ["bird","dog","giraffe","elephant","Tiger"]

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if tableView == jpWordChainTableView {
            return jpWordChainItems.count
        } else {
            return enWordChainItems.count
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if tableView == jpWordChainTableView {
            let cell = tableView.dequeueReusableCell(withIdentifier: "JpWordChainCell", for: indexPath)
            cell.textLabel?.text = jpWordChainItems[indexPath.row]
            return cell
        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: "EnWordChainCell", for: indexPath)
            cell.textLabel?.text = enWordChainItems[indexPath.row]
            return cell
        }
    }
    // tableViewへの視覚効果変更
    func changeTableViewAppearance(active: UITableView, deactive: UITableView) {
        // セルの選択状態を解除する
        if let indexPathForSelectedRow = deactive.indexPathForSelectedRow {
            deactive.deselectRow(at: indexPathForSelectedRow, animated: true)
        }
        // セルの透明度を変更する
        UIView.animate(withDuration: 0.3, delay: 0.0, options: [.curveEaseIn], animations: {deactive.alpha = 0.4}, completion: nil)
        UIView.animate(withDuration: 0.3, delay: 0.0, options: [.curveEaseIn], animations: {active.alpha = 1.0 }, completion: nil)
    }

    // cellがタップされた場合にtargetTableViewの値を書き換える
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if tableView == jpWordChainTableView {
            targetTableView = true
            changeTableViewAppearance(active: jpWordChainTableView, deactive: enWordChainTableView)
        } else {
             targetTableView = false
            changeTableViewAppearance(active: enWordChainTableView, deactive: jpWordChainTableView)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        changeTableViewAppearance(active: jpWordChainTableView, deactive: enWordChainTableView)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

check解決した方法

0

自らの力量不足を呪いつつ。
NotificationでカスタムクラスからviewControllerに処理を丸投げしました。

import UIKit
class CustomTableView: UITableView {

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        for touch: UITouch in touches {
            let tag = touch.view!.tag
            switch tag {
            case 3:
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "jpWordChainTableViewTapped"), object: nil)
            case 4:
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "enWordChainTableViewTapped"), object: nil)
            default: break

            }
        }
    }
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

おっしゃられているように

let vc = ViewController() 


だと新しいViewControllerを作成しているだけになるかと思いますので、CustomTableViewにViewControllerを参照する変数を持つ必要があります。(循環参照に注意が必要です。)

また、storyboardを使用されている場合、ViewControllerは下記のようにすれば取得できると思います。

// Main.storyboardを使用しているとします。
let storyboard = UIStoryboard(name: "Main", bundle: nil)

// ViewControllerという名前でStoryboardIDを設定しているとします。
let vc = storyboard.instantiateViewController(withIdentifier: "ViewController")

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/28 13:41 編集

    回答ありがとうございます。

    viewControllerは、遷移しているわけではなく、ずっと存在しているので、この場合インスタンス化しても仕方がないのか?と思い、いろいろやってみたのですが。

    とりあえず、viewControllerのプロパティtargetTableViewには、宣言をstatic var targetTableViewと
    することでカスタムクラスから値の書き換えができるようになりました。

    viewControllerのメソッドをカスタムクラスから呼び出すと、viewControllerにoutlet接続されている
    tableViewに変更を加えるところでランタイムエラーになってしまって困っています。

    たとえば、
    func printYes(){
    print("YES")
    }

    などは、カスタムクラスから、viewController().printYes()と呼び出せるのですが、

    func changeTableViewAlpha(){
    UIView.animate(withDuration: 0.3, delay: 0.0, options: [.curveEaseIn], animations: {self.jpWordChainTableView.alpha = 0.4}, completion: nil)
    }

    などは、カスタムクラスから、viewController().changeTableViewAlpha()と呼び出すと
    jpWordChainTableViewが予期せぬnilでランタイムエラーになってしまいます。

    キャンセル

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

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

関連した質問

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

  • Swift

    6485questions

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