Thread-safe NSMutableArray question

2019-06-14 12:35发布

问题:

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.

回答1:

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.



回答2:

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