Coc*_*ica 3 xml core-data objective-c nsxmlparser ios
我的应用程序有一个问题,它采用XML提要,解析它,并将结果存储到Core Data中.
问题仅发生在应用程序的第一次运行时,当商店中没有任何内容并且整个订阅源被解析和存储时.问题只是内存分配累积起来,直到50%的尝试崩溃应用程序,通常大约10Mb.分配的对象似乎是CFData(存储)对象,我似乎无法找到任何强制释放它们的方法.如果你可以让它运行一次并成功完成解析并保存到核心数据,那么每次后续启动都没问题,内存使用量永远不会超过2.5Mb
这是我们进入代码之前的一般方法:将feed添加到NSData对象中.使用NSFileManager将其存储为文件.从文件路径创建URL并将其提供给parseXMLFile:方法.代表是自我.在到达解析器时:didStartElement:namespaceURI:qualifiedName:attributes:我创建一个字典来捕获我需要的标签中的数据.解析器:foundCharacters:方法将标记的内容保存到字符串解析器:didEndElement:...方法然后确定标记是否是我们需要的东西.如果是这样的话,它会将它添加到字典中,否则它会忽略它.一旦它到达项目的末尾,它就会调用一种方法将其添加到核心数据存储中.
通过查看示例代码和其他人发布的帖子,似乎一般方法中没有任何错误.
代码如下,它来自视图控制器的更大上下文,但我省略了任何不直接相关的内容.
就我已经尝试的事情而言:feed是XML,没有转换为JSON的选项,抱歉.这不是在共享文档区域中找到并存储的图像.
关于它可能是什么的线索:这是我从Instruments获得的最大数量最多的东西(每件256k):
对象地址类别创建时间实时大小负责图书馆负责人
1 0xd710000 CFData(store)16024774912•262144 CFNetwork URLConnectionClient :: clientDidReceiveData( _CFData const*,URLConnectionClient :: ClientConnectionEventQueue*)
这是代码,为内容的匿名编辑;)
-(void)parserDidStartDocument:(NSXMLParser *)feedParser { }
-(void)parserDidEndDocument:(NSXMLParser *)feedParser { }
-(void)parser:(NSXMLParser *)feedParser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
eachElement = elementName;
if ( [eachElement isEqualToString:@"item" ] )
{
//create a dictionary to store each item from the XML feed
self.currentItem = [[[NSMutableDictionary alloc] init] autorelease];
}
}
-(void)parser:(NSXMLParser *)feedParser foundCharacters:(NSString *)feedString
{
//Make sure that tag content doesn't line break unnecessarily
if (self.currentString == nil)
{
self.currentString = [[[NSMutableString alloc] init]autorelease];
}
[self.currentString appendString:feedString];
}
-(void)parser:(NSXMLParser *)feedParser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
eachElement = elementName;
NSString *tempString = [self.currentString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ( [eachElement isEqualToString:@"title"] )
{
//skip the intro title
if (![tempString isEqualToString:@"Andy Panda UK"])
{
//add item to di citonary output to console
[self.currentItem setValue:tempString forKey:eachElement];
}
}
if ( [eachElement isEqualToString:@"link"] )
{
//skip the intro link
if (![tempString isEqualToString:@"http://andypanda.co.uk/comic"])
{
//add item to dicitonary output to console
[self.currentItem setValue:tempString forKey:eachElement];
}
}
if ( [eachElement isEqualToString:@"pubDate"] )
{
//add item to dicitonary output to console
[self.currentItem setValue:tempString forKey:eachElement];
}
if ( [eachElement isEqualToString:@"description"] )
{
if ([tempString length] > 150)
{
//trims the string to just give us the link to the image file
NSRange firstPart = [tempString rangeOfString:@"src"];
NSString *firstString = [tempString substringFromIndex:firstPart.location+5];
NSString *secondString;
NSString *separatorString = @"\"";
NSScanner *aScanner = [NSScanner scannerWithString:firstString];
[aScanner scanUpToString:separatorString intoString:&secondString];
//trims the string further to give us just the credits
NSRange secondPart = [firstString rangeOfString:@"title="];
NSString *thirdString = [firstString substringFromIndex:secondPart.location+7];
thirdString = [thirdString substringToIndex:[thirdString length] - 12];
NSString *fourthString= [secondString substringFromIndex:35];
//add the items to the dictionary and output to console
[self.currentItem setValue:secondString forKey:@"imageURL"];
[self.currentItem setValue:thirdString forKey:@"credits"];
[self.currentItem setValue:fourthString forKey:@"imagePreviewURL"];
//safety sake set unneeded objects to nil before scope rules kick in to release them
firstString = nil;
secondString = nil;
thirdString = nil;
}
tempString = nil;
}
//close the feed and release all the little objects! Fly be free!
if ( [eachElement isEqualToString:@"item" ] )
{
//get the date sorted
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"EEE, dd MMM yyyy HH:mm:ss ZZZZ";
NSDate *pubDate = [formatter dateFromString:[currentItem valueForKey:@"pubDate"]];
[formatter release];
NSArray *fetchedArray = [[NSArray alloc] initWithArray:[fetchedResultsController fetchedObjects]];
//build the string to make the image
NSString *previewURL = [@"http://andypanda.co.uk/comic/comics-rss/" stringByAppendingString:[self.currentItem valueForKey:@"imagePreviewURL"]];
if ([fetchedArray count] == 0)
{
[self sendToCoreDataStoreWithDate:pubDate andPreview:previewURL];
}
else
{
int i, matches = 0;
for (i = 0; i < [fetchedArray count]; i++)
{
if ([[self.currentItem valueForKey:@"title"] isEqualToString:[[fetchedArray objectAtIndex:i] valueForKey:@"stripTitle"]])
{
matches++;
}
}
if (matches == 0)
{
[self sendToCoreDataStoreWithDate:pubDate andPreview:previewURL];
}
}
previewURL = nil;
[previewURL release];
[fetchedArray release];
}
self.currentString = nil;
}
- (void)sendToCoreDataStoreWithDate:(NSDate*)pubDate andPreview:(NSString*)previewURL {
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[fetchedResultsController fetchRequest] entity];
newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
[newManagedObject setValue:[NSDate date] forKey:@"timeStamp"];
[newManagedObject setValue:[[currentItem valueForKey:@"title"] description] forKey:@"stripTitle"];
[newManagedObject setValue:[[currentItem valueForKey:@"credits"] description] forKey:@"stripCredits"];
[newManagedObject setValue:[[currentItem valueForKey:@"imageURL"] description] forKey:@"stripImgURL"];
[newManagedObject setValue:[[currentItem valueForKey:@"link"] description] forKey:@"stripURL"];
[newManagedObject setValue:pubDate forKey:@"stripPubDate"];
[newManagedObject setValue:@"NO" forKey:@"stripBookmark"];
//**THE NEW SYSTEM**
NSString *destinationPath = [(AndyPadAppDelegate *)[[UIApplication sharedApplication] delegate] applicationDocumentsDirectory];
NSString *guidPreview = [[NSProcessInfo processInfo] globallyUniqueString];
NSString *guidImage = [[NSProcessInfo processInfo] globallyUniqueString];
NSString *dpPreview = [destinationPath stringByAppendingPathComponent:guidPreview];
NSString *dpImage = [destinationPath stringByAppendingPathComponent:guidImage];
NSData *previewD = [NSData dataWithContentsOfURL:[NSURL URLWithString:previewURL]];
NSData *imageD = [NSData dataWithContentsOfURL:[NSURL URLWithString:[currentItem valueForKey:@"imageURL"]]];
//NSError *error = nil;
[[NSFileManager defaultManager] createFileAtPath:dpPreview contents:previewD attributes:nil];
[[NSFileManager defaultManager] createFileAtPath:dpImage contents:imageD attributes:nil];
//TODO: BETTER ERROR HANDLING WHEN COMPLETED APP
[newManagedObject setValue:dpPreview forKey:@"stripLocalPreviewPath"];
[newManagedObject setValue:dpImage forKey:@"stripLocalImagePath"];
[newManagedObject release];
before++;
[self.currentItem removeAllObjects];
self.currentItem = nil;
[self.currentItem release];
[xmlParserPool drain];
self.xmlParserPool = [[NSAutoreleasePool alloc] init];
}
Run Code Online (Sandbox Code Playgroud)
[编辑] @Rog我试过玩NSOperation但到目前为止没有运气,同样的我,ory用相同的物品建立,每个约256k.这是代码:
- (void)sendToCoreDataStoreWithDate:(NSDate*)pubDate andPreview:(NSString*)previewURL
{
NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[fetchedResultsController fetchRequest] entity];
newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
[newManagedObject setValue:[NSDate date] forKey:@"timeStamp"];
[newManagedObject setValue:[[currentItem valueForKey:@"title"] description] forKey:@"stripTitle"];
[newManagedObject setValue:[[currentItem valueForKey:@"credits"] description] forKey:@"stripCredits"];
[newManagedObject setValue:[[currentItem valueForKey:@"imageURL"] description] forKey:@"stripImgURL"];
[newManagedObject setValue:[[currentItem valueForKey:@"link"] description] forKey:@"stripURL"];
[newManagedObject setValue:pubDate forKey:@"stripPubDate"];
[newManagedObject setValue:@"NO" forKey:@"stripBookmark"];
NSString *destinationPath = [(AndyPadAppDelegate *)[[UIApplication sharedApplication] delegate] applicationDocumentsDirectory];
NSString *guidPreview = [[NSProcessInfo processInfo] globallyUniqueString];
NSString *guidImage = [[NSProcessInfo processInfo] globallyUniqueString];
NSString *dpPreview = [destinationPath stringByAppendingPathComponent:guidPreview];
NSString *dpImage = [destinationPath stringByAppendingPathComponent:guidImage];
//Create an array and send the contents off to be dispatched to an operation queue
NSArray *previewArray = [NSArray arrayWithObjects:dpPreview, previewURL, nil];
NSOperation *prevOp = [self taskWithData:previewArray];
[prevOp start];
//Create an array and send the contents off to be dispatched to an operation queue
NSArray *imageArray = [NSArray arrayWithObjects:dpImage, [currentItem valueForKey:@"imageURL"], nil];
NSOperation *imagOp = [self taskWithData:imageArray];
[imagOp start];
[newManagedObject setValue:dpPreview forKey:@"stripLocalPreviewPath"];
[newManagedObject setValue:dpImage forKey:@"stripLocalImagePath"];
//[newManagedObject release]; **recommended by stackoverflow answer
before++;
[self.currentItem removeAllObjects];
self.currentItem = nil;
[self.currentItem release];
[xmlParserPool drain];
self.xmlParserPool = [[NSAutoreleasePool alloc] init];
}
- (NSOperation*)taskWithData:(id)data
{
NSInvocationOperation* theOp = [[[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(threadedImageDownload:)
object:data] autorelease];
return theOp;
}
- (void)threadedImageDownload:(id)data
{
NSURL *urlFromArray1 = [NSURL URLWithString:[data objectAtIndex:1]];
NSString *stringFromArray0 = [NSString stringWithString:[data objectAtIndex:0]];
NSData *imageFile = [NSData dataWithContentsOfURL:urlFromArray1];
[[NSFileManager defaultManager] createFileAtPath:stringFromArray0
contents:imageFile
attributes:nil];
//-=====0jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjmn **OLEG**
}
Run Code Online (Sandbox Code Playgroud)
小智 7
您可以禁用缓存:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
[sharedCache release];
Run Code Online (Sandbox Code Playgroud)
或清除它:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
Run Code Online (Sandbox Code Playgroud)
这应该可以解决您的问题.
| 归档时间: |
|
| 查看次数: |
1954 次 |
| 最近记录: |