0

我正在解析提要中的字符串,将它们转换为 URL,并将它们存储为 FeedItem 的属性。最初,它们已成功转换为 URL 并存储,但后来,当我访问该属性时,它是 nil。

饲料项目.h

@interface FeedItem : NSObject

@property (nonatomic, strong) NSString* author;
@property (nonatomic, strong) NSURL* imageURL;
@property (nonatomic, strong) NSString* datePublished;

@end

解析器

- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
 namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
{
// Custom blog object initialized here
if ([elementName isEqualToString:@"entry"]) {
    self.blogEntry = [[FeedItem alloc] init];
}

// Parse image URL that accompanies some blog entries
self.blogEntry.imageURL = [NSURL URLWithString:[attributeDict objectForKey:@"url"]];
if ([[NSURL URLWithString:[attributeDict objectForKey:@"url"]] isKindOfClass:[NSURL class]]) {
    NSLog( @"converted to a url" );

    if ([self.blogEntry.imageURL isKindOfClass:[NSURL class]]) {
        NSLog(@"property of object is url");
    }else if (!self.blogEntry.imageURL) {
        NSLog(@"url becomes nil");
    }else{
        NSLog(@"property of object is NOT url");
    }
}
}

每次它应该打印“转换为 url”和“对象的属性是 url”。但是,稍后在同一文件中:

- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {

if([elementName isEqualToString:@"entry"]) {
    // An individual blog has been parsed and a pointer to it is added to the parsedResults array

    if ([self.blogEntry.imageURL isKindOfClass:[NSURL class]]) {
        NSLog( @"URL passed" );
    }else if (!self.blogEntry.imageURL) {
        NSLog( @"is nil" );
    }else{
        NSLog(@"no luck");
    }

    [self.parsedResults  addObject:self.blogEntry];

}
}

每次都会打印“is nil”。

这是正在解析的 URL 之一的示例: url=' http://2.bp.blogspot.com/-HlNeYKf6Jyk/URKJ0NzA_kI/AAAAAAAAADY/AAkM6mNITlo/s72-c/Ananya's+Illustration.jpg '

我知道如果 URL 具有特殊字符可能会出现问题,但是因为它一开始是成功的,所以我认为这不应该是问题。

我是objective-c的新手……我错过了什么?

4

3 回答 3

0

在您的parser:didStartElement:namespaceURI:qualifiedName:attributes:方法中,您为每个元素设置 self.blogEntry.imageURL。有些元素不包含 url 属性,当字典不包含特定键时,它会返回nil- 清除您之前存储在那里的任何值。

为了克服这个问题,你需要这样的代码:

- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName 
attributes:(NSDictionary *)attributeDict
{
    // Custom blog object initialized here
    if ([elementName isEqualToString:@"entry"]) {
        self.blogEntry = [[FeedItem alloc] init];
    }

    // Only allow the element containing the url we want to effect the value
    // of imageURL through
    if ([elementName isEqualToString:@"media"]) {

        self.blogEntry.imageURL = [NSURL URLWithString:[attributeDict objectForKey:@"url"]];
        if ([[NSURL URLWithString:[attributeDict objectForKey:@"url"]] isKindOfClass:[NSURL class]]) {
            NSLog( @"converted to a url" );

            if ([self.blogEntry.imageURL isKindOfClass:[NSURL class]]) {
                NSLog(@"property of object is url");
            }else if (!self.blogEntry.imageURL) {
                NSLog(@"url becomes nil");
            }else{
                NSLog(@"property of object is NOT url");
            }
        }

    }
}

考虑查看 Xcode 中的断点以帮助调试此类问题。

于 2013-02-13T09:39:49.323 回答
0

您的以下代码不能保证实际创建了 blogEntry 对象。

// Parse image URL that accompanies some blog entries
self.blogEntry.imageURL = [NSURL URLWithString:[attributeDict objectForKey:@"url"]];
if ([[NSURL URLWithString:[attributeDict objectForKey:@"url"]] isKindOfClass:[NSURL class]]) {
    NSLog( @"converted to a url" );

    if ([self.blogEntry.imageURL isKindOfClass:[NSURL class]]) {
        NSLog(@"property of object is url");
    }else if (!self.blogEntry.imageURL) {
        NSLog(@"url becomes nil");
    }else{
        NSLog(@"property of object is NOT url");
    }
}

仅当开始元素是“条目”时才创建 blogEntry 对象,但您在该块之外访问它而没有任何检查。不保证当您尝试设置图像 URL 时会创建 blogEntry 对象。

尽管这并不能解释为什么您的 imageURL 对象在 didStartElement 回调中有效,但在 didEndElement 回调中无效。我只是说它容易出错。

于 2013-02-12T18:08:31.280 回答
0

我的猜测是它self.blogEntry正在被释放。

这一行:

self.blogEntry = [[FeedItem alloc] init];

正在替换以前的self.blogEntry. 在调用“didEndElement”方法之前,您的解析器是否可能多次调用它?

或者,被指定blogEntry为? 如果没有,它可能会在创建后在方法结束时被释放。strongself

于 2013-02-12T17:27:53.593 回答