0

I have a UITableView that populates the results of a search that the user looks up. In order to do this I am using a NSMutableArray of Dictionaries where objects are added for the first 10, and then when the user scrolls to the bottom it populates the next 10 until there are no results left to show.

This all works well and good but I started to notice that the more searches that are done, the slower the table gets. Here is some of the code:

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
    [self.objectsArray removeAllObjects];
    [self.objectsArray setArray:nil];
    [itemsTable reloadData];
    [itemsTable scrollRectToVisible:CGRectMake(0, 0, 0, 0) animated:false];

    [self loadItemsFromURL:searchURL withItemDescription:encodedString atStartRow:start andEndRow:end];
}

The above is when a new search is performed. It then does a NSURLConnection and responds with this:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    if (self.objectsArray == nil)
        self.objectsArray = [NSMutableArray array]; 
        // self.objectsArray = [[NSMutableArray alloc] init];
    NSError *error;
    NSDictionary *returnArray = [[NSJSONSerialization JSONObjectWithData:itemsData options:kNilOptions error:&error] valueForKey:@"items"];
    for (id key in returnArray)
    {
        [self.objectsArray addObject:[returnArray objectForKey:key]];
    }
    counter += 10;
    [itemsTable reloadData];
}

As you can see, if a user conducts a new search all objects are removed with [self.objectsArray removeAllObjects]and I even try to set the array to nil. If I perform multiple searches the UITableView gets slower and slower with scrolling each time. It is almost like the controller sees the array as getting larger and larger with each search even though I am removing all of the objects from it before the search. Any ideas or am I going about this the wrong way?

EDIT: Here is the cellForRowAtIndexPath: method. cell is a subclassed UITableViewCell.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Product Cell";
    static NSString *LoadCellIdentifier = @"Loading Cell";
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if ([self.objectsArray count] <= 0 )
    {
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        cell.itemName.text = @"No items found.";
        cell.itemPrice.text = @"";
        cell.itemLocation.text = @"";
        cell.addButton.hidden = YES;
    }
    else
    {
        if ([indexPath row] == [self.objectsArray count])
        {
            if ( [self.objectsArray count] >= 10 )
            {
                if ( [self.objectsArray count] < counter)
                {
                    cell = [tableView dequeueReusableCellWithIdentifier:LoadCellIdentifier];
                    [cell.loadingSpinner stopAnimating];
                    cell.itemName.text = @"No more items found.";
                }
                else
                {
                    if (!running)
                    {
                        [self loadItemsFromURL:searchURL withItemDescription:encodedString atStartRow:[self.objectsArray count] + 1 andEndRow:[self.objectsArray count] + 10];
                        cell = [tableView dequeueReusableCellWithIdentifier:LoadCellIdentifier];
                        cell.itemName.text = @"Loading more items...";
                        [cell.loadingSpinner startAnimating];
                        running = true;
                    }
                    else
                    {
                        cell = [tableView dequeueReusableCellWithIdentifier:LoadCellIdentifier];
                        [cell.loadingSpinner startAnimating];
                    }
                }
            }
        }
        else
        {
            cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
            NSArray *match = [self.objectsArray objectAtIndex:[indexPath row]];
            cell.addButton.hidden = NO;
            if ([match valueForKey:@"DESCRIPTION"] == [NSNull null] )
            {
                cell.itemName.text = @"Description not available.";
            }
            else
            {
                cell.itemName.text = [match valueForKey:@"DESCRIPTION"];
            }
            if ([match valueForKey:@"AD"] != [NSNull null])
            {
                NSMutableString *adString = [NSMutableString stringWithString:[match valueForKey:@"AD"]];
                NSRange textRange;
                textRange = [adString rangeOfString:@"1/"];
                if (textRange.location != NSNotFound)
                {
                    [adString replaceCharactersInRange:[adString rangeOfString:@"1/"] withString:@"$"];
                }
                else
                {
                    [adString replaceCharactersInRange:[adString rangeOfString:@"/"] withString:@"/$"];
                }
                cell.itemPrice.text = adString;
            }
            else if ([match valueForKey:@"REGULAR"] == [NSNull null])
            {
                cell.itemPrice.text = @"$ N/A";
            }
            else
            {
                NSNumberFormatter *currencyStyle = [[NSNumberFormatter alloc] init];
                [currencyStyle setFormatterBehavior:NSNumberFormatterBehavior10_4];
                [currencyStyle setNumberStyle:NSNumberFormatterCurrencyStyle];
                NSNumber *price = [NSNumber numberWithDouble:[[match valueForKey:@"REGULAR"] doubleValue]];
                NSString *stringPrice = [currencyStyle stringFromNumber:price];
                cell.itemPrice.text = [NSString stringWithFormat:@"%@", stringPrice];
            }
            if ([match valueForKey:@"AISLE"] == [NSNull null])
            {
                cell.itemLocation.text = @"Item location: N/A";
            }
            else
            {
                cell.itemLocation.text = [NSString stringWithFormat:@"Item Location: %@", [match valueForKey:@"AISLE"]];
            }
            match = nil;
        }
    }
    return cell;
}

EDIT 2: Here is a snippet of what the JSON looks like:

{
    items =     {
        263149 =         {
            AD = "###";
            AISLE = 6A;
            DESCRIPTION = "Cinnamon Toasters";
            R = 9;
            REGULAR = "#.##";
        };
        26599 =         {
            AD = "####";
            AISLE = 6A;
            DESCRIPTION = "Quaker Life Cereal";
            R = 2;
            REGULAR = "#.##";
        };
        40517 =         {
            AD = "###";
            AISLE = 6A;
            DESCRIPTION = "Toasted Oats";
            R = 1;
            REGULAR = "#.##";
        };
    };
}; 
4

2 に答える 2

0

の1行で問題を見つけることができましたcellForRowAtIndexPath:。私はコメントアウトしました:cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];上部で、それが一度だけ呼び出されることを確認しました。また、8vius で提案されているように、少しクリーンアップを行いましたが、そのメソッド呼び出しで NSString が割り当てられるのは 1 回だけです。これらの 2 つのことを実行すると、途切れることなく再び応答性が向上しました。

于 2012-10-01T18:58:12.250 に答える
0

わかりました、あなたの問題は Array オブジェクトの過剰な作成だと思います。したがって、配列を作成する代わりに、次のようにします。

NSDictionary *returnArray = [[NSJSONSerialization JSONObjectWithData:itemsData options:kNilOptions error:&error] valueForKey:@"items"];
for (NSDictionary *dict in returnArray in returnArray)
{
    [self.objectsArray addObject:dict];
}
counter += 10;
[itemsTable reloadData];

ご覧のとおり、オブジェクトの配列が得られますNSDictionary。返される配列は、既にNSDictionary辞書オブジェクトの配列です。また、少し観察しますが、どこでカウンターをリセットしていますか?

編集:NSDictionary fromの作成NSData:

[NSJSONSerialization JSONObjectWithData:self.requestData options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:&error]

requestData は、次のデリゲート メソッドを使用して生成されます。

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
  NSLog(@"In didReceiveResponse");
  [self.requestData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
  NSLog(@"In didReceiveData");
  [self.requestData appendData:data];
}
于 2012-09-26T20:03:12.313 に答える