Thread-safe NSMutableArray question
Asked Answered
D

2

0

I am developing a RSS reader which uses a NSMutableArray (_stories) to store the contents of the RSS Feed. This array is being used by two different threads in the application and may be accessed simultaneously in two occasions, since:

  1. It is the data-source of the UITableViewController (which reads it's content and shows the desired information to the user)
  2. It is used by the XMLParser (which downloads the content from the Internet, parses the XML Data and adds the contents to it).

Some piece of code is shown below:

In the UITableViewController class

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    [_stories count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // Update the Cell title, for example..
    [[cell title] setText:[[[_stories objectAtIndex: storyIndex] objectForKey: @"title"]];
}

In the XMLParser class

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI 
 qualifiedName:(NSString *)qName {    
    // after finished the parsing of an Item of the XML, add it "multi-threaded array"
    NSLog(@"[_stories addObject:_item]");
    [_stories addObject:_item];
}

If the user wants to load "More posts" from the RSS Feed I am starting another parse operation passing the _stories array as a reference to the parser, which appends other "posts" to the array. By the end of the parsing, the UITableViewController method reloadData is called and then the UITableView is updated.

What if the user scroll up/down the UITableView while the parsing is running? Will the UITableViewController attempt to access the _stories array (in order to create the cells) simultaneously and possibly crashing the Application (it occurs very sporadically but occurs)?

I though about the idea of using @synchronized blocks but I'm not quite sure where I'll have to put it exactly (the _stories array is accessed in many places of the code). Another question is: Where will I have to handle the exceptions that are possibly thrown by the @synchronized blocks? This may result in a lot of redundant code.

I also though about using @property without "nonatomic", but I don't think it is well suited for this problem.

Any idea of how to solve this? Thanks in advance.

Donndonna answered 9/11, 2009 at 19:48 Comment(0)
G
3

I just spotted this and I doubt you are still looking for an answer, but maybe this will be useful to someone else :)

On a quick look, how I would solve this is:

  • Have the new parsing run in a background thread, and have this load into another array.
  • When the new array has been loaded and you have all of your data, run a method on the main thread which adds the new array to your _stories array, then tells the UI to refresh.

You have now safely updated your _stories array and have displayed it, without any risk of concurrent access to the array.

Granada answered 26/4, 2010 at 22:55 Comment(0)
A
0

Why not make More Posts modal and show an activity indicator? After all if the user selects "more posts" she is willing to accept a certain amount of load time

Ackerley answered 9/11, 2009 at 19:56 Comment(1)
Actually I'd like to implement something similar to the Tweetie App. I'm detecting when the user reaches the end of the UITableView (the last one UITableViewCell) and, automatically, a new parser is started. At this point the _stories may be accessed simultaneously (by both the parser and the UITableView (if the user scrolls up)), where the problem may occur.Donndonna

© 2022 - 2024 — McMap. All rights reserved.