Fork me on GitHub

自定义内存释放池内元素上限

- (void)downloadAndParse:(NSURL *)url {
self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];
done = NO;
self.parseFormatter = [[[NSDateFormatter alloc] init] autorelease];
[parseFormatter setDateStyle:NSDateFormatterLongStyle];
[parseFormatter setTimeStyle:NSDateFormatterNoStyle];
// necessary because iTunes RSS feed is not localized, so if the device region has been set to other than US
// the date formatter must be set to US locale in order to parse the dates
[parseFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@"US"] autorelease]];
self.characterBuffer = [NSMutableData data];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:url];
// create the connection with the request and start loading the data
rssConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
// This creates a context for "push" parsing in which chunks of data that are not "well balanced" can be passed
// to the context for streaming parsing. The handler structure defined above will be used for all the parsing.
// The second argument, self, will be passed as user data to each of the SAX handlers. The last three arguments
// are left blank to avoid creating a tree in memory.
context = xmlCreatePushParserCtxt(&simpleSAXHandlerStruct, self, NULL, 0, NULL);
[self performSelectorOnMainThread:@selector(downloadStarted) withObject:nil waitUntilDone:NO];
if (rssConnection != nil) {
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
} while (!done);
}
// Release resources used only in this thread.
xmlFreeParserCtxt(context);
self.characterBuffer = nil;
self.parseFormatter = nil;
self.rssConnection = nil;
self.currentSong = nil;
[downloadAndParsePool release];
self.downloadAndParsePool = nil;
}

 

static void    endElementSAX(void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI) {    
LibXMLParser *parser = (LibXMLParser *)ctx;
if (parser.parsingASong == NO) return;
if (prefix == NULL) {
if (!strncmp((const char *)localname, kName_Item, kLength_Item)) {
[parser finishedCurrentSong];
parser.parsingASong = NO;
} else if (!strncmp((const char *)localname, kName_Title, kLength_Title)) {
parser.currentSong.title = [parser currentString];
} else if (!strncmp((const char *)localname, kName_Category, kLength_Category)) {
parser.currentSong.category = [parser currentString];
}
} else if (!strncmp((const char *)prefix, kName_Itms, kLength_Itms)) {
if (!strncmp((const char *)localname, kName_Artist, kLength_Artist)) {
parser.currentSong.artist = [parser currentString];
} else if (!strncmp((const char *)localname, kName_Album, kLength_Album)) {
parser.currentSong.album = [parser currentString];
} else if (!strncmp((const char *)localname, kName_ReleaseDate, kLength_ReleaseDate)) {
NSString *dateString = [parser currentString];
parser.currentSong.releaseDate = [parser.parseFormatter dateFromString:dateString];
}
}
parser.storingCharacters = NO;
}



 

static const NSUInteger kAutoreleasePoolPurgeFrequency = 20;

- (void)finishedCurrentSong {
[self performSelectorOnMainThread:@selector(parsedSong:) withObject:currentSong waitUntilDone:NO];
// performSelectorOnMainThread: will retain the object until the selector has been performed
// setting the local reference to nil ensures that the local reference will be released
self.currentSong = nil;
countOfParsedSongs++;
// Periodically purge the autorelease pool. The frequency of this action may need to be tuned according to the
// size of the objects being parsed. The goal is to keep the autorelease pool from growing too large, but
// taking this action too frequently would be wasteful and reduce performance.
if (countOfParsedSongs == kAutoreleasePoolPurgeFrequency) {
[downloadAndParsePool release];
self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];
countOfParsedSongs = 0;
}
}

 

- (void)parsedSong:(Song *)song {
NSAssert2([NSThread isMainThread], @"%s at line %d called on secondary thread", __FUNCTION__, __LINE__);
[self.parsedSongs addObject:song];
if (self.parsedSongs.count > kCountForNotification) {
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(parser:didParseSongs:)]) {
[self.delegate parser:self didParseSongs:parsedSongs];
}
[self.parsedSongs removeAllObjects];
}
}

 

 

- (void)parser:(iTunesRSSParser *)parser didParseSongs:(NSArray *)parsedSongs {
[songs addObjectsFromArray:parsedSongs];
// Three scroll view properties are checked to keep the user interface smooth during parse. When new objects are delivered by the parser, the table view is reloaded to display them. If the table is reloaded while the user is scrolling, this can result in eratic behavior. dragging, tracking, and decelerating can be checked for this purpose. When the parser finishes, reloadData will be called in parserDidEndParsingData:, guaranteeing that all data will ultimately be displayed even if reloadData is not called in this method because of user interaction.
if (!self.tableView.dragging && !self.tableView.tracking && !self.tableView.decelerating) {
self.title = [NSString stringWithFormat:NSLocalizedString(@"Top %d Songs", @"Top Songs format"), [songs count]];
[self.tableView reloadData];
}
}




posted on 2012-03-06 15:35  pengyingh  阅读(220)  评论(0)    收藏  举报

导航