在cellForRowAtIndexPath中执行繁重的计算

时间:2014-09-19 12:26:00

标签: ios uitableview core-data grand-central-dispatch

我有一个装有产品的表格视图。每个的价格需要一些繁重的计算,所以我想在主UI线程之外,因为否则滚动表非常非常不可能。无论我尝试什么,我都无法获得正确的语法和概念。我当前的代码确实加载了背景上的价格,但是当我滚动一些单元格时,会给出不属于它们的价格。我不知道如何调试这个。任何建议赞赏。

- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if ([self.products count] == 0) {
        UITableViewCell *cell = [[UITableViewCell alloc] init];
        return cell;
    }

    AvailableCustomerProductTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    cell.accessoryType = UITableViewCellAccessoryNone;

    cell.buttonAdd.tag = indexPath.row;
    [cell.buttonAdd addTarget: self action: @selector(addToSelectedProduct:) forControlEvents: UIControlEventTouchUpInside];

    Product *prod = nil;
    if (theTableView == self.searchDisplayController.searchResultsTableView) {
        prod = (Product *)[self.filteredProducts objectAtIndex:indexPath.row];
    } else {
        prod = (Product *)[self.products objectAtIndex:indexPath.row];
    }

    if (prod != nil) {
        cell.pNumber.text = prod.number;
        cell.description.text = prod.desc;

        if ([Common getProductPromotion:prod] != nil)  {
            cell.btnPromotionTag.hidden = NO;
            cell.btnPromotionTag.tag = indexPath.row;
            [cell.btnPromotionTag addTarget: self action: @selector(showPromotionDetails:) forControlEvents: UIControlEventTouchUpInside];
        }
        else{
            cell.btnPromotionTag.hidden = YES;
        }

        //Get the customer product price, first:
        //If if the product has a record in the productCustomerPrices list
        //if not get the price from the standard price.
        if (self.order.orderOrderCustomer != nil) {
            // Do the Customer price fetching in a background thread
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                CustomerPrice *custPrice = [Common getPriceForCustomer:self.order.orderOrderCustomer.customerId forProduct:prod.productId inManagedObjectContext:self.backgroundContext];

                // Return to the main thread to update the UI
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (custPrice) {
                        NSManagedObjectID *objId = custPrice.objectID;
                        CustomerPrice *custPrice = (CustomerPrice*)[self.managedObjectContext objectWithID:objId];

                        if (custPrice) {
                            // Check that the relevant data is still required and get the correct cell (it might have changed)
                            AvailableCustomerProductTableViewCell * correctCell = nil;
                            if ([[theTableView indexPathsForVisibleRows] containsObject:indexPath]) {
                                correctCell = (AvailableCustomerProductTableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];
                            }

                            [correctCell.btnPrice setTitle:[Common getCurrencyFormattedStringFromFloat:[custPrice.price floatValue]] forState:UIControlStateNormal];
                            [correctCell.btnPrice setTitleColor:[UIColor colorWithRed:0.01 green:0.65 blue:0.77 alpha:1] forState:UIControlStateNormal];
                            correctCell.btnPrice.enabled = NO;
                            [correctCell setNeedsLayout];
                        }                    }
                });
            });
        }
    }

    UISwipeGestureRecognizer* sgr = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(cellSwiped:)];
    [sgr setDirection:UISwipeGestureRecognizerDirectionRight];
    [cell addGestureRecognizer:sgr];

    return cell;
}

1 个答案:

答案 0 :(得分:1)

您是否尝试过几个步骤:

  1. 当你正在加载视图时(在viewWillAppear:中)加载你的产品列表以快速显示ListView,
  2. 在后台进行服务器调用,以便在单独的NSDictionary*prices productId中检索价格列表,并输入密钥[self.tableView reloadData]。计算结束后,您应该在主线程上调用cellForRowAtIndexPath:
  3. prices方法中,您应该只检查您是否有{{1}}词典中的价格并显示您的按钮。如果没有价格,请务必隐藏按钮,以避免在电池回收时出现显示故障。
  4. 像这样,你可以通过线路和关联避免一些复杂的重新加载,从而导致你的问题。