Reputation: 7685
I'm making a search function for my application that I want to highlight the search string in the cell.
To do this, I save the search string to a global variable activeSearchString
that can be accessed by tableView:cellForRowAtIndexPath
.
tableView:cellForRowAtIndexPath
then highlights the content of activeSearchString
in the cell it will return.
However, it isn't working. If you check the log, it seems like reloadData is performed asynchronous (so after activeSearchString
has been deallocated).
Because of this, my app also crashes.. Any solution to perform reloadData
synchronous or another approach? Thanks!
Code:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(){
// Get the products asynchronous
NSString* searchString = [NSString stringWithString:@"A search string"];
NSArray* searchResults = [[ProductServer sharedServer] productsForSearchString:searchString];
dispatch_sync(dispatch_get_main_queue(), ^(){
DLog(@"Begin");
activeSearchString = [searchString retain];
products = [searchResults retain];
[ibTableView reloadData];
[activeSearchString release];
DLog(@"End");
});
});
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
DLog();
ProductTableViewCell* tableViewCell = [tableView dequeueReusableCellWithIdentifier:@"productCell" forIndexPath:indexPath];
Product* product = [products objectAtIndex:[indexPath row]];
NSDictionary* highlightAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[UIColor colorWithRed:49.f/255.f green:110.f/255.f blue:184.f/255.f alpha:1.f], NSBackgroundColorAttributeName, nil];
NSMutableAttributedString* mutableAttributedTitle = [[[NSMutableAttributedString alloc] initWithString:[product title]] autorelease];
[mutableAttributedTitle setAttributes:highlightAttributes range:[[mutableAttributedTitle string] rangeOfString:activeSearchString options:NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch]];
[(UILabel*)[tableViewCell titleLabel] setAttributedText:mutableAttributedTitle];
return tableViewCell;
}
Log:
2012-11-13 14:56:00.783 ****[5810:c07] __58-[TVCurrentlyViewController searchBarSearchButtonClicked:]_block_invoke_2 [Line 190] Begin
2012-11-13 14:56:00.783 ****[5810:c07] __58-[TVCurrentlyViewController searchBarSearchButtonClicked:]_block_invoke_2 [Line 197] End
2012-11-13 14:56:00.783 ****[5810:c07] -[TVCurrentlyViewController tableView:cellForRowAtIndexPath:] [Line 117]
2012-11-13 14:56:00.786 ****[5810:c07] -[TVCurrentlyViewController tableView:cellForRowAtIndexPath:] [Line 117]
2012-11-13 14:56:00.787 ****[5810:c07] -[TVCurrentlyViewController tableView:cellForRowAtIndexPath:] [Line 117]
2012-11-13 14:56:00.789 ****[5810:c07] -[TVCurrentlyViewController tableView:cellForRowAtIndexPath:] [Line 117]
2012-11-13 14:56:00.790 ****[5810:c07] *** -[CFString length]: message sent to deallocated instance 0x75d6d00
Upvotes: 1
Views: 2496
Reputation: 10782
You shouldn't be releasing a global there. Use a synthesized property with retain semantics and release in the view controller's dealloc method.
Edit:
Use dispatch_async()
instead of dispatch_sync()
in your call back to the main thread. dispatch_sync()
will block the global background queue while the main thread finishes updating the tableview.
Upvotes: 4