无法找出核心数据的EXC_BAD_ACCESS原因

时间:2011-01-12 05:12:59

标签: iphone core-data

我正在尝试从rss Feed导入数据。第一个记录插入正常,但第二个记录导致EXC_BAD_ACCESS异常。单步执行代码让我无法完成任务。失败点在于对managedObjectContext保存方法的调用。

我很感激任何帮助。

/* Workout.h */
#import <UIKit/UIKit.h>
@class Workout;

@interface WorkoutsController : UITableViewController <NSXMLParserDelegate> {
    NSFetchedResultsController *_fetchedResultsController;
    NSURLConnection *urlConnection;
    NSMutableData *xmlData;

    Workout *currentWorkout;
    NSMutableString *title;
    NSMutableString *link;
    NSMutableString *details;
    NSMutableString *currentElement;
}

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
@property (nonatomic, retain) NSURLConnection *urlConnection;
@property (nonatomic, retain) NSMutableData *xmlData;

@property (nonatomic, retain) Workout *currentWorkout;
@property (nonatomic, retain) NSMutableString *title;
@property (nonatomic, retain) NSMutableString *link;
@property (nonatomic, retain) NSMutableString *details;
@property (nonatomic, retain) NSMutableString *currentElement;

@end

/* Workout.m */
/**
 * Determine if the current element is an 'item'
 * <item>
 *  <title>...</title>
 *  <link>...</link>
 *  <content:encoded>...</content:encoded>
 */
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
                                        namespaceURI:(NSString *)namespaceURI 
                                       qualifiedName:(NSString *)qName 
                                          attributes:(NSDictionary *)attributeDict {

    // determine when parser is inside an item element
    if ([elementName isEqualToString:@"item"]) {
        self.currentWorkout = [[Workout alloc] initWithEntity:[[self.fetchedResultsController fetchRequest] entity]
                               insertIntoManagedObjectContext:[self.fetchedResultsController managedObjectContext]];
    }

    // only read child elements of the item element
    if (self.currentWorkout != nil) {
        if ([elementName isEqualToString:@"title"]) {
            self.title = [[NSMutableString alloc] init];
            self.currentElement = title;
        }
        else if ([elementName isEqualToString:@"link"]) {
            self.link = [[NSMutableString alloc] init];
            self.currentElement = link;
        }
        else if ([elementName isEqualToString:@"content:encoded"]) {
            self.details = [[NSMutableString alloc] init];
            self.currentElement = details;
        }
    }
}

/**
 * Finished reading the tag content
 */ 
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    // only read child elements of the item element
    if (self.currentWorkout != nil) {
        [self.currentElement appendString:string];
    }
}

/**
 * Extract the text for the following tags
 * <item>
 *  <title>...</title>
 *  <link>...</link>
 *  <content:encoded>...</content:encoded>
 */
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
                                      namespaceURI:(NSString *)namespaceURI 
                                     qualifiedName:(NSString *)qName {

    // determine if the item element is being closed
    // if so save the workout
    if ([elementName isEqualToString:@"item"]) {
        self.currentWorkout.title = self.title;
        self.currentWorkout.url = self.link;
        self.currentWorkout.details = self.details;

        NSLog(@"Completing: %@", self.currentWorkout.title);

        NSError *error;

        NSManagedObjectContext *moc = [self.fetchedResultsController managedObjectContext];

        /*** Line 206: Fails Here ***/
        if (![moc save:&error]) {
            NSLog(@"Failed to save to data store: %@ - %@", 
                  [error localizedDescription], [error userInfo]);
        }

        [self.currentElement release];
        self.currentElement = nil;  

        [self.title release];
        self.title = nil;

        [self.link release];
        self.link = nil;

        [self.details release];
        self.details = nil;

        [self.currentWorkout release];
        self.currentWorkout = nil;
    }
}

/* Backtrace */
(gdb) bt
#0  0x027b6903 in objc_msgSend ()
#1  0x00000007 in ?? ()
#2  0x023a2688 in _NSQLRow_dealloc_standard ()
#3  0x026730eb in __CFBasicHashRemoveValue ()
#4  0x0258a1e0 in CFBasicHashRemoveValue ()
#5  0x0259f7c8 in CFDictionaryRemoveValue ()
#6  0x02441724 in -[NSSQLCore managedObjectContextDidUnregisterObjectsWithIDs:] ()
#7  0x0243524a in -[NSPersistentStoreCoordinator(_NSInternalMethods) _informAffectedStoresOfInterestByChildContextInObjectsWithObjectIDs:withSelector:] ()
#8  0x0242e940 in -[NSPersistentStoreCoordinator(_NSInternalMethods) managedObjectContextDidUnregisterObjectsWithIDs:] ()
#9  0x02384396 in -[_PFManagedObjectReferenceQueue _processReferenceQueue:] ()
#10 0x023837f4 in -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] ()
#11 0x023bce55 in -[NSManagedObjectContext save:] ()
#12 0x000038e5 in -[WorkoutsController parser:didEndElement:namespaceURI:qualifiedName:] (self=0x633ca10, _cmd=0x178994, parser=0x632a0c0, elementName=0x634a850, namespaceURI=0x0, qName=0x0) at /Users/chris/Documents/Projects/iPhone/WorkoutApp/Classes/WorkoutsController.m:206
#13 0x000f13a9 in _endElementNs ()
#14 0x02ae6ea7 in xmlParseXMLDecl ()
#15 0x02af1bb1 in xmlParseChunk ()
#16 0x000f0baa in -[NSXMLParser parse] ()
#17 0x00003352 in -[WorkoutsController connectionDidFinishLoading:] (self=0x633ca10, _cmd=0x17ce32, connection=0x6343510) at /Users/chris/Documents/Projects/iPhone/WorkoutApp/Classes/WorkoutsController.m:132
#18 0x00059b96 in -[NSURLConnection(NSURLConnectionReallyInternal) sendDidFinishLoading] ()
#19 0x00059aef in _NSURLConnectionDidFinishLoading ()
#20 0x02c0d72f in URLConnectionClient::_clientDidFinishLoading ()
#21 0x02cd8fcf in URLConnectionClient::ClientConnectionEventQueue::processAllEventsAndConsumePayload ()
#22 0x02c02968 in URLConnectionClient::processEvents ()
#23 0x02c027e5 in MultiplexerSource::perform ()
#24 0x0263afaf in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#25 0x0259939b in __CFRunLoopDoSources0 ()
#26 0x02598896 in __CFRunLoopRun ()
#27 0x02598350 in CFRunLoopRunSpecific ()
#28 0x02598271 in CFRunLoopRunInMode ()
#29 0x02f3800c in GSEventRunModal ()
#30 0x02f380d1 in GSEventRun ()
#31 0x002c6af2 in UIApplicationMain ()
#32 0x000021b0 in main (argc=1, argv=0xbfffefdc) at /Users/chris/Documents/Projects/iPhone/WorkoutApp/main.m:14

1 个答案:

答案 0 :(得分:1)

我很确定你的崩溃来自于此:

    [self.currentElement release];
    self.currentElement = nil;  

基本上,这样的所有行都是错误的 - 它们应该是这样的:

    self.currentElement = nil;  

现在除此之外,您还需要自动释放通过属性设置的变量 - 所以此代码(以及所有类似的代码)都是错误的:

        self.title = [[NSMutableString alloc] init];
        self.currentElement = title;

它需要看起来像:

 self.title = [NSMutableString string];
 self.currentElement = title;

发生的事情是因为你将currentElement和title属性指向同一个可变字符串,当后来的代码出现时,释放currentElement AND title然后再用self.propertyname = nil释放它们,你过度释放了疯狂的对象。

内存规则非常简单 - 如果在离开方法后某些东西将“保留”某个对象,它将保留该对象,因此您不应该这样做。