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

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

ただいまの
回答率

90.04%

Swift2 TableViewの引っ張って更新の実現方法がわからない・

解決済

回答 2

投稿 編集

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

m_tsukasa

score 5

前提・実現したいこと

TableViewのデータの更新を「引っ張って更新」で行いたい。

発生している問題・エラーメッセージ

更新をかけようとしたところ、インデックスエラーが表示される状態です。

該当のソースコード

import UIKit

class TableViewController: UITableViewController {

    var bbsData:[BbsData] = [BbsData]()
    var offset = 0
    var userId: String?
    @IBOutlet var filterBtn: UIBarButtonItem!

    func getData(){
        let url = NSURL(string:"データを取得するPHPへのURL")
        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session = NSURLSession(configuration: config)
        let req = NSMutableURLRequest(URL: url!)
        req.HTTPMethod = "POST"
        req.HTTPBody = ("データの絞込み用POSTパラメータ").dataUsingEncoding(NSUTF8StringEncoding)
        let task = session.dataTaskWithRequest(req, completionHandler: {
            (data,resp,err) in
            do{
                let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
                if json.count > 0{
                    if let bbsDatas = json["bbsData"] as? NSArray{
                            self.offset +=  bbsDatas.count
                            for data1 in bbsDatas{
                            let basebaseUrl: String = "DBからの画像を表示するPHPへのURL"
                            let commentId = data1["commentId"] as! String
                            let baseUrl = basebaseUrl + commentId
                            let url = baseUrl as NSString
                            let nameStr = data1["userName"] as? NSString
                            let ageStr = data1["age"] as? NSString
                            let prefStr = data1["pref"] as? NSString
                            let commentStr = data1["comment"] as? NSString
                            let userId = data1["userListId"] as? NSString
                            let gender = data1["gender"] as? NSString
                            self.setupBbsDatas(url, nameStr: nameStr, ageStr: ageStr, prefStr: prefStr, commentStr: commentStr, userId: userId, gender: gender)
                        }
                    }
                    self.tableView.reloadData()
                }
            }catch{
                print("error")
            }
        })
        task.resume()

    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.refreshControl = UIRefreshControl()
        self.refreshControl?.attributedTitle = NSAttributedString(string: "引っ張って更新")
        self.refreshControl?.addTarget(self, action: #selector(TableViewController.refresh), forControlEvents: UIControlEvents.ValueChanged)
        self.tableView.addSubview(refreshControl!)
        let backBtn = UIBarButtonItem()
        backBtn.title = "戻る"
        self.navigationItem.backBarButtonItem = backBtn
        getData()
    }

    func refresh(){
        self.refreshControl?.endRefreshing()
        bbsData = []
        for i:NSInteger in 0 ..< tableView.numberOfSections {
            for j:NSInteger in 0 ..< tableView.numberOfRowsInSection(i){
                bbsData.removeAtIndex(j)
                tableView.cellForRowAtIndexPath(NSIndexPath(forRow: j, inSection: i))?.removeFromSuperview()
            }
        }

        let ending = bbsData.count
        for i in 0 ..< ending {
            self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        }

        self.offset = 0
        getData()

    }

    @IBAction func filterClick(sender: UIBarButtonItem){
        let storyboard = UIStoryboard(name:"Main",bundle:nil)
        let nextView:UIViewController = storyboard.instantiateViewControllerWithIdentifier("filterSelect")
        nextView.modalTransitionStyle = UIModalTransitionStyle.PartialCurl
        navigationController?.pushViewController(nextView, animated: true)
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        userId = bbsData[indexPath.row].userId as String
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
        let storyboard = UIStoryboard(name:"DetailProf",bundle:nil)
        let nextView:UIViewController = storyboard.instantiateViewControllerWithIdentifier("detailProfile")
        nextView.modalTransitionStyle = UIModalTransitionStyle.PartialCurl
        let viewController = nextView as! DetailProf
        viewController.userListId = userId
        navigationController?.pushViewController(nextView, animated: true)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

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


    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell: bbsTableCell = tableView.dequeueReusableCellWithIdentifier("bbsDataCell", forIndexPath: indexPath) as! bbsTableCell
        cell.setCell(bbsData[indexPath.row])
        if (self.bbsData.count - 1) == indexPath.row {
            getData()
        }
        return cell
    }

    func setupBbsDatas(bbsImage: NSString, nameStr: NSString?, ageStr: NSString?, prefStr: NSString?, commentStr: NSString?, userId: NSString?, gender: NSString?){
        let data = BbsData(bbsImage: bbsImage, nameStr: nameStr, ageStr: ageStr, prefStr: prefStr, commentStr: commentStr, userId: userId, gender: gender)
        bbsData.append(data)
    }
}

bbsTableCell.swift

import UIKit

class bbsTableCell: UITableViewCell {

    @IBOutlet var postImage: UIImageView!
    @IBOutlet var nameLabel: UILabel!
    @IBOutlet var ageLabel: UILabel!
    @IBOutlet var prefLabel: UILabel!
    @IBOutlet var commentLabel: UILabel!
    @IBOutlet var genderImage: UIImageView!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    func setCell(bbsData: BbsData){

        nameLabel.text = bbsData.nameStr as String
        ageLabel.text = bbsData.ageStr as String + "才"
        prefLabel.text = bbsData.prefStr as String
        commentLabel.text = bbsData.commentStr as String
        switch bbsData.gender {
            case "男性":
            genderImage.image = UIImage(named: "genderMale")

            case "女性":
            genderImage.image = UIImage(named: "genderFemale")

        default:
            genderImage.image = UIImage(named: "genderNodisplay")

        }
        let url = NSURL(string: bbsData.bbsImage as String)
        let requestUrl = NSURLRequest(URL: url!)
        NSURLConnection.sendAsynchronousRequest(requestUrl, queue: NSOperationQueue.mainQueue()){(response,data,error) -> Void in
            if error != nil{
                //print(error)
            }else{
                if let dlImage = UIImage(data: data!){
                    self.postImage.image = dlImage
                }
            }
        }

    }

}

考察してみたこと

Android版を作成した時に行った方法として、
TableView(ListView)のリセット(全削除) → 再データセットの流れで実現できたので、
同じような処理ができないかと模索した結果
TableViewのリセット(全削除)の方法がわからない状態でいまに至ってます。

補足情報(言語/FW/ツール等のバージョンなど)

Xcode7.3 
Swift2.*

できればもうひとつの質問もよろしくお願いいたします。

https://teratail.com/questions/39264

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

check解決した方法

0

ご教授頂いたコードを以下のように修正したところ
希望通りの動作をいたしましました。

func refresh() {
    bbsData = [] //全データ削除
  tableView.reloadData() //表示のリロード <- 追加
    getData()    //データ更新
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

refreshの中で何やらややこしいことをしていますが、セルを作り直す必要はなく、元データ(bbsData)を更新して、テーブルをリロードしてやるだけでいいです。

ちゃんとソース読んでないですが、

func refresh() {
    bbsData = [] //全データ削除
    getData()    //データ更新
}

これでいけそうな気がしないでもないです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/06/27 14:41

    早速のご回答ありがとうございます。
    上記のソースに変更で実行してみたのですが
    index out of rangeのエラーが出て更新されないです。

    キャンセル

  • 2016/06/27 15:19

    どこでエラーが出ているかくらい書きませんか。

    キャンセル

  • 2016/06/27 15:24

    すみません、更新をするために引っ張り更新のマークが表示されたあと
    手を離すと、数秒後にエラーを出力する形です。

    キャンセル

  • 2016/06/27 16:09

    エミュレータ環境で実行したところ、
    cellForRowAtIndexPath内の
    cell.setCell(bbsData[indexPath.row])にて Index out of rangeのエラーが出ます、
    該当クラスメソッドは別ファイルのため、上記質問に追記いたしました。

    キャンセル

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

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