Swift 2 + Parse:数组索引超出范围

时间:2016-01-15 19:09:12

标签: uitableview parse-platform swift2

有时刷新的作品有时候不会

我有let blurEffect = UIBlurEffect(style: .Light) let visualEffect = UIVisualEffectView(effect: blurEffect) visualEffect.frame = cell.attachedImage.bounds cell.attachedImage.addSubview(visualEffect) 基本上是新闻Feed。我还实现了一个pull to refresh功能。但是有时候当我拉动刷新它会给我错误

  

'数组索引超出范围'。

我知道这意味着它试图得到的物品不存在,但你能告诉我为什么吗?这是我的代码:

UITableViewController

和refresh()函数:

override func viewDidLoad() {
    super.viewDidLoad()

    refresher = UIRefreshControl()
    refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
    refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
    self.tableView.addSubview(refresher)
    refresh()

    tableView.delegate = self
    tableView.dataSource = self
}

func refresh() {

    //disable app while it does stuff
    UIApplication.sharedApplication().beginIgnoringInteractionEvents()

    //get username and match with userId
    let getUser = PFUser.query()
    getUser?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in

        if let users = objects {

            //clean arrays and dictionaries so we dont get indexing error???
            self.messages.removeAll(keepCapacity: true)
            self.users.removeAll(keepCapacity: true)
            self.usernames.removeAll(keepCapacity: true)

            for object in users {

                if let user = object as? PFUser {

                    //make userId = username
                    self.users[user.objectId!] = user.username!
                }
            }
        }
    })

    let getPost = PFQuery(className: "Posts")
    getPost.findObjectsInBackgroundWithBlock { (objects, error) -> Void in

        if error == nil {
        if let objects = objects {

            self.messages.removeAll(keepCapacity: true)
            self.usernames.removeAll(keepCapacity: true)

            for object in objects {

                self.messages.append(object["message"] as! String)
                self.usernames.append(self.users[object["userId"] as! String]!)

                self.tableView.reloadData()
            }
        }
        }
    }

    self.refresher.endRefreshing()
    UIApplication.sharedApplication().endIgnoringInteractionEvents()
}

4 个答案:

答案 0 :(得分:1)

如果您正在执行两项后台任务,则会遇到竞争条件,其中第二项任务取决于从第一项返回的值。 getUser?.findObjectsInBackgroundWithBlock将立即返回,getPost.findObjectsInBackgroundWithBlock将开始执行。 getPost应位于getUser的块内,以确保序列正确。 同样,以下两行应位于第二个块内:

self.refresher.endRefreshing()
UIApplication.sharedApplication().endIgnoringInteractionEvents()

给定错误行,您可能还会在两个后台任务之间出现争用条件并显示tableView。我倾向于尝试:

func tableView(tableView:UITableView!, numberOfRowsInSection section:Int) {
   return self.refresher.refreshing ? 0 : self.usernames.count
}

这样,在后台刷新完成之前,您不会触摸self.usernames(只要您记得将endRefreshing放在第二个块中,该块也放在第一个块内。 / p>

答案 1 :(得分:0)

我相信在self.users[user.objectId!] = user.username!中,user.ObjectId是由parse分配的一些随机值,如下所示:" 34xcf4"。这就是您可能获得'Array index out of range'

的原因

答案 2 :(得分:0)

配置UITableView有两个必需的方法

  • tableView(_:cellForRowAtIndexPath:)
  • tableView(_:numberOfRowsInSection:)

在您的代码中,您只提供一个必需的方法,如果您没有实施第二种方法,那么可能会导致错误。

查看以下文档: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/#//apple_ref/occ/intfm/UITableViewDataSource/tableView:cellForRowAtIndexPath

答案 3 :(得分:0)

您在对阵列的每次添加时调用self.tableView.reloadData(),并在后台线程中执行此操作。

作为一般规则,您不应在后台线程中进行UI更新。当你清除self.messages和self.usernames时,因为你在后台线程中,没有什么能阻止tableview尝试在索引中获取一个不再包含数组中任何数据的单元格。

如果你想将你的代码保存在后台线程中(尽管可能存在风险),你至少应该在重新加载数组之前调用.beginUpdates并等到它们全部完成后再调用reload和endUpdates。