【问题标题】:objectForKey error with NSXMLParserNSXMLParser 的 objectForKey 错误
【发布时间】:2012-03-06 06:12:13
【问题描述】:

我收到以下错误:

“这个类不符合键 temp_f 的键值编码”

我的 AppDelegate 类文件:

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    IBOutlet NSTableView *tableView;
    NSArray *current;
}

@property (assign) IBOutlet NSWindow *window;
@end

#import "AppDelegate.h"
#import "CurrentWeather.h"
#import "XMLCurrent.h"

@implementation AppDelegate

@synthesize window = _window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    XMLCurrent *currentXML = [[XMLCurrent alloc] init];
    NSError *error = nil;

    current = [currentXML fetchCurrentWithError:&error];
    [tableView reloadData];
}

- (NSInteger)numberOfRowsInTableView:(NSTableView *)theTableView {
    return [current count];
}

- (id)tableView:(NSTableView *)theTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    CurrentWeather *c = [current objectAtIndex:row];
    return [c valueForKey:[tableColumn identifier]];
}
@end

我的 CurrentWeather 类文件:

#import <Foundation/Foundation.h>

@interface CurrentWeather : NSObject {
    NSString *location;
    NSString *weather;
    NSString *degreesF;
}

@property (nonatomic, copy) NSString *location;
@property (nonatomic, copy) NSString *weather;
@property (nonatomic, copy) NSString *degreesF;

@end

#import "CurrentWeather.h"

@implementation CurrentWeather

@synthesize location, weather, degreesF;

@end

我的 XMLCurrent 类文件:

#import <Foundation/Foundation.h>

@interface XMLCurrent : NSObject <NSXMLParserDelegate> {
    NSMutableArray *current;
    NSMutableString *currentString;
    NSMutableDictionary *currentFields;
}

- (NSArray *)fetchCurrentWithError:(NSError **)outError;

@end

#import "XMLCurrent.h"
#import "CurrentWeather.h"

@implementation XMLCurrent

- (id)init {
    self = [super init];

    if (self) {
        current = [[NSMutableArray alloc] init];
    }
    return self;
}

- (NSArray *)fetchCurrentWithError:(NSError **)outError {
    BOOL success;

    NSURL *xmlURL = [NSURL URLWithString:@"http://www.weather.gov/xml/current_obs/KCLT.xml"];

    NSURLRequest *req = [NSURLRequest requestWithURL:xmlURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30];

    NSURLResponse *resp = nil;

    NSData *data = [NSURLConnection sendSynchronousRequest:req returningResponse:&resp error:outError];
    if (!data) {
        return nil;
    }

    [current removeAllObjects];

    NSXMLParser *parser;
    parser = [[NSXMLParser alloc] initWithData:data];
    [parser setDelegate:self];

    success = [parser parse];
    if (!success) {
        *outError = [parser parserError];
        return nil;
    }

    NSArray *output = [current copy];
    return output;
}

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

    if ([elementName isEqual:@"current_observation"]) {
        currentFields = [[NSMutableDictionary alloc] init];
    }
}

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

    if ([elementName isEqual:@"current_observation"]) {
        CurrentWeather *currentCond = [[CurrentWeather alloc] init];
        [currentCond setLocation:[currentFields objectForKey:@"location"]];
        [currentCond setWeather:[currentFields objectForKey:@"weather"]];
        [currentCond setDegreesF:[currentFields objectForKey:@"temp_f"]];

        [current addObject:currentCond];
        currentCond = nil;
        currentFields = nil;
    } else if (currentFields && currentString) {
        NSString *trimmed;
        trimmed = [currentString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        [currentFields setObject:trimmed forKey:elementName];
    }
    currentString = nil;
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (!currentString) {
        currentString = [[NSMutableString alloc] init];
    }
    [currentString appendString:string];
}
@end

键在表格视图中用作“标识符”。出于某种原因,如果键中有下划线(例如 temp_f),我会收到错误消息。下划线是必需的,因为它是 XML 文件中元素的名称。如果没有下划线,则没有错误。如何从包含下划线的 XML 元素中获取数据?

正在从http://www.weather.gov/xml/current_obs/KCLT.xml解析xml数据

【问题讨论】:

  • 什么 currentFields?它是在哪里创建的?
  • 请将设置 currentFields 的代码贴出来。
  • 好的,现在你在哪里向 currentFields 添加对象?
  • 只是当问题可能出在我们无法阅读的代码中时,很难帮助找到问题。您尚未发布实际显示使用-setObject:forKey: 添加到 currentFields 的对象的代码。这就是我们需要看到的。
  • 我在您粘贴的代码中根本看不到任何 KVC,但是您遇到的错误是由 KVC 引发的。它显然是由您未粘贴的代码抛出的。

标签: objective-c cocoa nsxmlparser


【解决方案1】:

CurrentWeather 有一个 degreesF 属性,您可以通过 temp_f XML 字段设置该属性。您需要将表列的标识符设置为“degreesF”而不是“temp_f”。这与包含下划线的temp_f 无关。相反,问题在于 CurrentWeather 不符合键“temp_f”的键值编码(正如错误所述),因为它没有名为“temp_f”的属性。

进一步详细解释,在您的 -tableView:objectValueForTableColumn: 方法中,您使用列的标识符作为进入 CurrentWeather 实例的键。由于标识符是“temp_f”,因此您正在这样做:[c valueForKey:@"temp_f"]。这会引发异常,因为 CurrentWeather 没有 temp_f 属性。

【讨论】:

  • 啊啊啊啊!谢谢,做到了!
猜你喜欢
  • 1970-01-01
  • 2012-06-02
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多