0

Swift と PFQueryTableViewController で parse.com フレームワークを使用していますが、ページネーションを設定すると機能しません。DB の行数が objectPerPage で設定された数よりも少ない場合は正常に動作しますが、それ以上の行があり、アプリを実行すると読み込み画面が表示され続け、何もダウンロードされず、「更新としてスワイプ」するとクラッシュします。 エラー

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 4]

ImagesTableViewController.swift

import UIKit
import Parse
import ParseUI
import Bolts

class ImagesTableViewController: PFQueryTableViewController {
@IBAction func unwindToSegue (segue : UIStoryboardSegue) {}

// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) {
    super.init(style: style, className: className)
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    // Configure the PFQueryTableView
    self.parseClassName = "Image"
    self.pullToRefreshEnabled = true
    self.paginationEnabled = true
    self.objectsPerPage = 5

}

// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
    var query = PFQuery(className: "Image")
    query.whereKey("deleted", notEqualTo: 1)
    query.orderByDescending("createdAt")
    return query
}

//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {

    var cell = tableView.dequeueReusableCellWithIdentifier("ImageCell") as! ImageTVCell!
    if cell == nil {
        cell = ImageTVCell(style: UITableViewCellStyle.Default, reuseIdentifier: "ImageCell")
    }

    // Extract values from the PFObject to display in the table cell HEADLINE
    if let caption = object?["caption"] as? String {
        cell?.headlineLabel?.text = caption
    }

    // Display image
    var initialThumbnail = UIImage(named: "question")
    cell.postImageView.image = initialThumbnail
    if let thumbnail = object?["image"] as? PFFile {
        cell.postImageView.file = thumbnail
        cell.postImageView.loadInBackground()
    }

    return cell
}

// if I remove this code pagination work but the cell height is wrong
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return calculateHeightForRowAtIndexPath(indexPath)
}


func calculateHeightForRowAtIndexPath(indexPath: NSIndexPath) -> CGFloat {
    if let ratio = objectAtIndexPath(indexPath)?["aspect"] as? Float {
        println("Ratio: \(ratio)")
        return tableView.bounds.size.width / CGFloat(ratio)
    } else {
        return 50.0
    }
}


@IBAction func addNewPhotoButton(sender: UIBarButtonItem) {
    self.tabBarController?.tabBar.hidden = true
    self.performSegueWithIdentifier("showUploadNewImage", sender: self)
}

}
4

2 に答える 2

0

この問題は、 にPFQueryTableViewControllerよる のメソッドの実装が原因で発生tableView:numberOfRowsInSectionUITableViewDataSourceます。を含む GitHub リポジトリからコピーして貼り付けましたPFQueryTableViewController.m

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSInteger count = [self.objects count];
    if ([self _shouldShowPaginationCell]) {
        count += 1;
    }
    return count;
}

表示するオブジェクトの数を返すだけですが (これは理にかなっています)、ページネーションが有効になっている場合は、追加のセルを表示する必要があります。これは、「データをさらに読み込む」などのテキストを含む別のセルを手動で作成する必要があることを意味します。これにより、更新がトリガーされます。


これを克服する方法はtableView:numberOfRowsInSection、次のように自分自身をオーバーライドすることです。

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

更新 1

前の回答では、事前に作成されParseたページネーション ボタンがなくなりました


次のコード スニペットを使用してセルの高さを計算し、事前に作成されたParseページネーション ボタンを表示します。

func calculateHeightForRowAtIndexPath(indexPath: NSIndexPath) -> CGFloat {
    // Special case for pagination, using the pre-built one by Parse
    if (indexPath.row >= objects!.count) { return 50.0 }

    // Determines the height if an image ratio is present
    if let ratio = objectAtIndexPath(indexPath)?["aspect"] as? Float {
        println("Ratio: \(ratio)")
        return tableView.bounds.size.width / CGFloat(ratio)
    } else {
        return 50.0
    }
}
于 2015-06-09T12:17:09.707 に答える
0

iOS 9.2 および Xcode 7.2 で Parse 1.11 を使用すると、Parse Pagination が完全に機能します。ユーザーが、Parse によって追加された "Load More ..." 行を適切に管理せずに、Parse 自体によって使用される関数をオーバーライドすると、問題が表面化します。私の場合、現在のユーザーがオブジェクトの ACL に従って行を削除できるかどうかを判断するために、tableView-canEditRowAtIndexPath をオーバーライドする必要がありました。私の最初の機能は次のとおりです。

オーバーライド func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {

    if let curUser = PFUser.currentUser() {
        let currentObject = objects![indexPath.row]
        if let acl = currentObject.ACL {
            return acl.getWriteAccessForUser(curUser)
        } else {
           return true
        }
    }
    return true
}

しかし、リストのスクロール中に Load More 行が満たされたときに、範囲外の indexpath の例外が発生しました。このテストを追加して問題を解決しました:

    if (indexPath.row == self.objects!.count) { // row "Load More ..."
        return true
    }

このコードがないと、Parse によって "Load More ..." 行が追加されませんでした!! したがって、完全な正しいオーバーライド機能は次のとおりです。

オーバーライド func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {

    if (indexPath.row == self.objects!.count) { // row "Load More ..."
        return true
    }
    if let curUser = PFUser.currentUser() {
        let currentObject = objects![indexPath.row]
        if let acl = currentObject.ACL {
            return acl.getWriteAccessForUser(curUser)
        } else {
           return true
        }
    }
    return true
}

一般的に言えば、heightForRowAtIndexpath を含むすべてのオーバーライドされた関数は、ページネーションが有効な場合に Parse によって追加された余分な行を処理する必要があります。

HTH

ロベルト・タルガ

于 2015-12-26T12:02:51.183 に答える