2009-05-26 305 views
2

我有一個類XMLParser。它只要能正常工作,因爲我不刪除,增加節點到NSMutableArray中該行的註釋:NSMutableArray addObject崩潰iPhone應用程序

[nodes addObject:self.currentNode]; 

如果我這樣做,應用程序崩潰 - 沒有留下任何痕跡的調試日誌。 這怎麼可能?

XMLParser.m:

#import "XMLParser.h" 
#import "MyViewController.h" 
#import "Node.h" 


@implementation XMLParser 
@synthesize currentNode, currentProperty, currentAddress, nodes; 


- (NSMutableArray *)parseNodeData:(NSString *)url { 
    NSURL *urlObj = [[NSURL alloc] initWithString:url]; 
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:urlObj]; 

    self.nodes = [[NSMutableArray alloc] init]; 

    [parser setDelegate:self]; 
    [parser setShouldProcessNamespaces:NO]; 
    [parser setShouldReportNamespacePrefixes:NO]; 
    [parser setShouldResolveExternalEntities:NO]; 
    [parser parse]; 
    NSLog(@"Proceeded from parser."); 

    NSLog(@"Returning %@ rows", [nodes count]); 
    //[parser release]; 
    return self.nodes; 
} 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
{ 
    if (self.currentProperty) { 
     [currentProperty appendString:string]; 
    } 
} 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { 
    if (qName) { 
     elementName = qName; 
    } 

    NSLog(@"<%@>", elementName); 

    if(self.currentNode) 
    { 
     if ([elementName isEqualToString:@"id"] || [elementName isEqualToString:@"name"]) 
     { 
      self.currentProperty = [NSMutableString string]; 
     } 
    } else { 
     // We are outside of everything, so we need a 
     // Check for deeper nested node 
     if ([elementName isEqualToString:@"node"]) { 
      self.currentNode = [[Node alloc] init]; 
      NSLog(@"Initialized new node..."); 
     } 
    } 
} 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
{ 
    if(self.currentNode) 
    { 
     if ([elementName isEqualToString:@"id"]) { 
      NSLog(@"Tried setting node id: %@", self.currentProperty); 
      self.currentNode.nodeId = self.currentProperty; 

     } else if ([elementName isEqualToString:@"name"]) { 
      NSLog(@"Tried setting node name: %@", self.currentProperty); 
      self.currentNode.name = self.currentProperty; 
     } else if ([elementName isEqualToString:@"node"]) { 
      NSLog(@"Adding node to array"); 
      //[nodes addObject:self.currentNode]; 
      self.currentNode = nil; 
     } 
    } 

    NSLog(@"</%@>", elementName); 

    self.currentProperty = nil; 
} 

- (void) dealloc { 
    [currentNode release]; 
    [currentAddress release]; 
    [currentProperty release]; 
    [super dealloc]; 
} 


@end 

XMLParser.h:

#import <UIKit/UIKit.h> 
#import "Address.h" 
#import "Node.h" 

@class XMLAppDelegate; 

@interface XMLParser : NSObject { 
    NSMutableString *currentProperty; 
    Address *currentAddress; 
    Node *currentNode; 
    NSMutableArray *nodes; 

} 

@property (nonatomic, retain) NSMutableString *currentProperty; 
@property (nonatomic, retain) Address *currentAddress; 
@property (nonatomic, retain) Node *currentNode; 
@property (nonatomic, retain) NSMutableArray *nodes; 

- (NSMutableArray *)parseNodeData:(NSString *)data; 

@end 

編輯:輸出調試日誌

[Session started at 2009-05-26 23:31:26 +0200.] 
2009-05-26 23:31:28.352 HelloWorld[6914:20b] <response> 
2009-05-26 23:31:28.353 HelloWorld[6914:20b] <nodesearchresult> 
2009-05-26 23:31:28.354 HelloWorld[6914:20b] <resultsreturned> 
2009-05-26 23:31:28.354 HelloWorld[6914:20b] </resultsreturned> 
2009-05-26 23:31:28.354 HelloWorld[6914:20b] <resultsfound> 
2009-05-26 23:31:28.354 HelloWorld[6914:20b] </resultsfound> 
2009-05-26 23:31:28.355 HelloWorld[6914:20b] <nodes> 
2009-05-26 23:31:28.355 HelloWorld[6914:20b] <node> 
2009-05-26 23:31:28.356 HelloWorld[6914:20b] Initialized new node... 
2009-05-26 23:31:28.356 HelloWorld[6914:20b] <id> 
2009-05-26 23:31:28.356 HelloWorld[6914:20b] Tried setting node id: 614 
2009-05-26 23:31:28.356 HelloWorld[6914:20b] </id> 
2009-05-26 23:31:28.357 HelloWorld[6914:20b] <name> 
2009-05-26 23:31:28.357 HelloWorld[6914:20b] Tried setting node name: Roberts coffee 
2009-05-26 23:31:28.357 HelloWorld[6914:20b] </name> 
2009-05-26 23:31:28.358 HelloWorld[6914:20b] <address> 
2009-05-26 23:31:28.358 HelloWorld[6914:20b] <street> 
2009-05-26 23:31:28.358 HelloWorld[6914:20b] </street> 
2009-05-26 23:31:28.358 HelloWorld[6914:20b] <zipcode> 
2009-05-26 23:31:28.359 HelloWorld[6914:20b] </zipcode> 
2009-05-26 23:31:28.359 HelloWorld[6914:20b] </address> 
2009-05-26 23:31:28.359 HelloWorld[6914:20b] <position> 
2009-05-26 23:31:28.359 HelloWorld[6914:20b] <latitude> 
2009-05-26 23:31:28.360 HelloWorld[6914:20b] </latitude> 
2009-05-26 23:31:28.360 HelloWorld[6914:20b] <longitude> 
2009-05-26 23:31:28.360 HelloWorld[6914:20b] </longitude> 
2009-05-26 23:31:28.361 HelloWorld[6914:20b] </position> 
2009-05-26 23:31:28.361 HelloWorld[6914:20b] <phone> 
2009-05-26 23:31:28.361 HelloWorld[6914:20b] </phone> 
2009-05-26 23:31:28.363 HelloWorld[6914:20b] <nodetypes> 
2009-05-26 23:31:28.363 HelloWorld[6914:20b] <nodetype> 
2009-05-26 23:31:28.363 HelloWorld[6914:20b] </nodetype> 
2009-05-26 23:31:28.364 HelloWorld[6914:20b] </nodetypes> 
2009-05-26 23:31:28.364 HelloWorld[6914:20b] <rating> 
2009-05-26 23:31:28.364 HelloWorld[6914:20b] <score> 
2009-05-26 23:31:28.365 HelloWorld[6914:20b] </score> 
2009-05-26 23:31:28.365 HelloWorld[6914:20b] <votes> 
2009-05-26 23:31:28.366 HelloWorld[6914:20b] </votes> 
2009-05-26 23:31:28.366 HelloWorld[6914:20b] </rating> 
2009-05-26 23:31:28.366 HelloWorld[6914:20b] <teaser> 
2009-05-26 23:31:28.367 HelloWorld[6914:20b] </teaser> 
2009-05-26 23:31:28.367 HelloWorld[6914:20b] Adding node to array 
2009-05-26 23:31:28.367 HelloWorld[6914:20b] </node> 
2009-05-26 23:31:28.367 HelloWorld[6914:20b] <node> 
2009-05-26 23:31:28.368 HelloWorld[6914:20b] Initialized new node... 
2009-05-26 23:31:28.368 HelloWorld[6914:20b] <id> 
2009-05-26 23:31:28.368 HelloWorld[6914:20b] Tried setting node id: 326 
2009-05-26 23:31:28.368 HelloWorld[6914:20b] </id> 
2009-05-26 23:31:28.369 HelloWorld[6914:20b] <name> 
2009-05-26 23:31:28.369 HelloWorld[6914:20b] Tried setting node name: Sort kaffe & vinyl 
2009-05-26 23:31:28.369 HelloWorld[6914:20b] </name> 
2009-05-26 23:31:28.369 HelloWorld[6914:20b] <address> 
2009-05-26 23:31:28.370 HelloWorld[6914:20b] <street> 
2009-05-26 23:31:28.370 HelloWorld[6914:20b] </street> 
2009-05-26 23:31:28.371 HelloWorld[6914:20b] <zipcode> 
2009-05-26 23:31:28.371 HelloWorld[6914:20b] </zipcode> 
2009-05-26 23:31:28.372 HelloWorld[6914:20b] </address> 
2009-05-26 23:31:28.372 HelloWorld[6914:20b] <position> 
2009-05-26 23:31:28.372 HelloWorld[6914:20b] <latitude> 
2009-05-26 23:31:28.373 HelloWorld[6914:20b] </latitude> 
2009-05-26 23:31:28.373 HelloWorld[6914:20b] <longitude> 
2009-05-26 23:31:28.373 HelloWorld[6914:20b] </longitude> 
2009-05-26 23:31:28.374 HelloWorld[6914:20b] </position> 
2009-05-26 23:31:28.374 HelloWorld[6914:20b] <phone> 
2009-05-26 23:31:28.375 HelloWorld[6914:20b] </phone> 
2009-05-26 23:31:28.375 HelloWorld[6914:20b] <nodetypes> 
2009-05-26 23:31:28.375 HelloWorld[6914:20b] <nodetype> 
2009-05-26 23:31:28.375 HelloWorld[6914:20b] </nodetype> 
2009-05-26 23:31:28.376 HelloWorld[6914:20b] <nodetype> 
2009-05-26 23:31:28.376 HelloWorld[6914:20b] </nodetype> 
2009-05-26 23:31:28.376 HelloWorld[6914:20b] </nodetypes> 
2009-05-26 23:31:28.376 HelloWorld[6914:20b] <rating> 
2009-05-26 23:31:28.377 HelloWorld[6914:20b] <score> 
2009-05-26 23:31:28.377 HelloWorld[6914:20b] </score> 
2009-05-26 23:31:28.377 HelloWorld[6914:20b] <votes> 
2009-05-26 23:31:28.377 HelloWorld[6914:20b] </votes> 
2009-05-26 23:31:28.378 HelloWorld[6914:20b] </rating> 
2009-05-26 23:31:28.378 HelloWorld[6914:20b] <teaser> 
2009-05-26 23:31:28.379 HelloWorld[6914:20b] </teaser> 
2009-05-26 23:31:28.379 HelloWorld[6914:20b] Adding node to array 
2009-05-26 23:31:28.379 HelloWorld[6914:20b] </node> 
2009-05-26 23:31:28.380 HelloWorld[6914:20b] </nodes> 
2009-05-26 23:31:28.380 HelloWorld[6914:20b] </nodesearchresult> 
2009-05-26 23:31:28.381 HelloWorld[6914:20b] </response> 
2009-05-26 23:31:28.381 HelloWorld[6914:20b] Proceeded from parser. 

[Session started at 2009-05-26 23:31:28 +0200.] 
Loading program into debugger… 
GNU gdb 6.3.50-20050815 (Apple version gdb-962) (Sat Jul 26 08:14:40 UTC 2008) 
Copyright 2004 Free Software Foundation, Inc. 
GDB is free software, covered by the GNU General Public License, and you are 
welcome to change it and/or distribute copies of it under certain conditions. 
Type "show copying" to see the conditions. 
There is absolutely no warranty for GDB. Type "show warranty" for details. 
This GDB was configured as "i386-apple-darwin".warning: Unable to read symbols for "/System/Library/Frameworks/UIKit.framework/UIKit" (file not found). 
warning: Unable to read symbols from "UIKit" (not yet mapped into memory). 
warning: Unable to read symbols for "/System/Library/Frameworks/CoreLocation.framework/Versions/A/CoreLocation" (file not found). 
warning: Unable to read symbols from "CoreLocation" (not yet mapped into memory). 
warning: Unable to read symbols for "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics" (file not found). 
warning: Unable to read symbols from "CoreGraphics" (not yet mapped into memory). 
Program loaded. 
sharedlibrary apply-load-rules all 
Attaching to program: `/Users/philipdahlstrm/Library/Application Support/iPhone Simulator/User/Applications/6BD1CC99-F133-4B97-A041-1D210851B6C6/HelloWorld.app/HelloWorld', process 6914. 
(gdb) 
+0

調試日誌中沒有跟蹤?所以你甚至不會在控制檯上看到「添加節點到陣列」,當程序崩潰時你也看不到堆棧跟蹤?嘗試清理您的項目並從「運行」菜單中選擇「調試」。 – 2009-05-26 20:56:08

+0

此外,我建議NSLogging self.nodes和self.currentNode之前,該註釋行,導致崩潰,以確保他們是有效的對象指針。 – 2009-05-26 20:57:30

+1

不知道這可能與這個問題有什麼關係,但是你的代碼泄露了'Node'對象。當你用alloc創建它並將其賦值給屬性'currentNode'時,它的保留計數增加(你在2上)。後來,當您將它添加到數組中時,它會再次遞增,計數爲3,並且您永遠不會釋放該對象,而是將引用設置爲nil。 – pgb 2009-05-26 21:16:31

回答

3

你的錯誤是在最後的NSLog:

NSLog(@"Returning %@ rows", [nodes count]); 

%@採用指向的對象。 [nodes count]返回一個無符號整數,然後您將其作爲指針解除引用。沒關係,如果節點是空的,因爲-count返回0,這是零,這可以通過這種方式解除引用。您應該在此處使用%d而不是%@

調試器堆棧應該已經向您顯示了發生的確切位置。我通過查看日誌的最後一行並查看之後立即發生的事情找到了它。

你在這裏泄漏了大量的記憶,順便說一句。如果您在保留訪問者(如self.nodes =...)的分配中使用Three Magic Words之一,則需要autorelease

self.currentNode = [[Node alloc] init]; 

應該是:

self.currentNode = [[[Node alloc] init] autorelease]; 

而且你應該總是使用存取的高德。切勿直接以您的方式訪問節點(除了在訪問器中和dealloc)。