简体   繁体   English

我们如何将 numberOfRowsInSection 同步到 cellForRowAtIndexPath?

[英]How do we sync numberOfRowsInSection to cellForRowAtIndexPath?

Our UITableView returns the number of rows for a given section.我们的 UITableView 返回给定部分的行数。 What we're experiencing is by the time cellForRowAtIndexPath is called, the number has changed so we end up getting array index out of bounds.我们正在经历的是,当 cellForRowAtIndexPath 被调用时,数字已经改变,所以我们最终得到了数组索引超出范围。

Is there a good way of syncing these two methods so the underlying data is not changed?有没有同步这两种方法的好方法,这样底层数据就不会改变? We considered using @synchronized, but not sure when you would release the lock.我们考虑过使用@synchronized,但不确定何时释放锁。

One other thing we're doing to refresh the table is this from a separate thread.我们正在做的另一件事是刷新表格,这来自一个单独的线程。

[self addUsers:usersToShow];       
[[self invokeOnMainThreadAndWaitUntilDone:NO] refresh:self]; // is this the issue?


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.users.count;  // returns 10 for example
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *newCell= nil;

    static NSString *cellId = @"cellId";

    cell = [tableView dequeueReusableCellWithIdentifier:cellId];
    if (cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:@"MyCell" owner:self options:nil];
        cell = newCell;
        self.newCell = nil;
    }

    User* user = [self.users objectAtIndex:indexPath.row]; // index out of bounds now because number of users has changed
}

Even though brain has already answered, I want to emphasize "update model in main thread" with example code.尽管大脑已经回答了,但我想用示例代码强调“在主线程中更新 model”。

You might encounter the problem because your model changed in some background thread.您可能会遇到问题,因为您的 model 在某些后台线程中发生了更改。 The timeline should look like this:时间线应如下所示:

{NSThread number = 1, name = main} -[ViewController tableView:numberOfRowsInSection:] (return 10 for example) {NSThread number = 1, name = main} -[ViewController tableView:numberOfRowsInSection:] (例如返回 10)

{NSThread number = 8, name = (null)} -[ViewController changeTheModel] (remove some objects from model, or get a new model with less than 10 objects) {NSThread number = 8, name = (null)} -[ViewController changeTheModel](从model中移除一些对象,或者得到一个少于10个对象的新model)

{NSThread number = 1, name = main} -[ViewController tableView:cellForRowAtIndexPath:] (get the index out of bound exception because 10th object does not exist) {NSThread number = 1, name = main} -[ViewController tableView:cellForRowAtIndexPath:] (获取索引越界异常,因为第 10 个 object 不存在)

To solve the problem, you should do something like this when you change your model:为了解决这个问题,当你改变你的 model 时,你应该这样做:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSArray* items = [self getNewModel];// get new model on background thread
    dispatch_async(dispatch_get_main_queue(), ^ {
        self.items = items;// replace the model with new one on main thread
        [self.tableView reloadData];// refresh table without index out of bound exception
    });
});

Hope this could help you.希望这可以帮助你。 :) :)

As you've kind of worked out for yourself, you can't use @synchronized because the scope extends beyond the method.正如您自己制定的那样,您不能使用@synchronized,因为 scope 超出了该方法。

You don't want to be trying to use a Lock object, locking it in numberOfRowsInSection and unlocking it cellForRowAtIndexPath.您不想尝试使用 Lock object,将其锁定在 numberOfRowsInSection 并解锁 cellForRowAtIndexPath。 It's not going to work.这是行不通的。 What you need to do is ensure that you do any locking you need to in cellForRowAtIndexPath and handle the fact that the row passed in might not be valid anymore eg:您需要做的是确保您在 cellForRowAtIndexPath 中执行任何您需要的锁定并处理传入的行可能不再有效的事实,例如:

User * user = nil;    
@synchronized(self.users) {
        if (indexPath.row < [self.users count]) {
             user = [self.users objectAtIndex:indexPath.row];
        }

}

if (user) {
    //configure cell
}
else {
    //set cell fields to be blank
}

Have you tried updating the model (self.users) only in the main thread?您是否尝试过仅在主线程中更新 model (self.users)? This should reduce the likely hood of your updates to the model from interleaving with calls to getNumberOfRows and configureCellAt.这应该可以减少您对 model 更新的可能影响,以免与对 getNumberOfRows 和 configureCellAt 的调用交错。 In the example you've given you are updating the model on a random thread and then reloading the data on the main thread.在您给出的示例中,您正在随机线程上更新 model,然后在主线程上重新加载数据。 I'd recommend ensuring that you're model is thread safe (or updated/read in only the main thread).我建议确保您的 model 是线程安全的(或仅在主线程中更新/读取)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将动态行和节数组传递给 numberOfRowsInSection 和 cellForRowAtIndexPath - How To Pass Dynamic row and Section Array to numberOfRowsInSection and cellForRowAtIndexPath 选择器在numberOfRowsInSection中被调用,但不在cellForRowAtIndexPath中被调用 - Selector gets called in numberOfRowsInSection but not in cellForRowAtIndexPath 在Apple的MultipleDetailViews示例中调用numberOfRowsInSection但不调用cellForRowAtIndexPath - numberOfRowsInSection called but not cellForRowAtIndexPath in MultipleDetailViews sample of apple iOS:在numberOfRowsInSection之后没有立即调用cellForRowAtIndexPath - iOS: cellForRowAtIndexPath not being called immediately after numberOfRowsInSection cellForRowAtIndexPath:被立即调用,而numberOfRowsInSection:不被调用 - cellForRowAtIndexPath: being called immediately while numberOfRowsInSection: is not called UITableViewController不会调用cellForRowAtIndexPath但是numberOfSectionsInTableView和numberOfRowsInSection确实设置得当 - UITableViewController will not call cellForRowAtIndexPath BUT numberOfSectionsInTableView and numberOfRowsInSection are indeed set properly 在调用 reloadData 时调用 numberOfRowsInSection 后有时不调用 cellForRowAtIndexPath - cellForRowAtIndexPath is not called sometimes after calling numberOfRowsInSection on calling reloadData UITableView,我如何知道cellForRowAtIndexPath期间的哪个部分? - UITableView, how do I know what Section during cellForRowAtIndexPath? 如何处理CellForRowAtIndexpath方法 - How to Handle CellForRowAtIndexpath method 如何使用NSMutableArray计数更新numberOfRowsInSection - How to update numberOfRowsInSection using NSMutableArray count
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM