gpt4 book ai didi

objective-c - 使用 NSXMLParser initWithStream : no parser delegate methods received

转载 作者:太空狗 更新时间:2023-10-30 04:00:23 25 4
gpt4 key购买 nike

我正在处理的基本问题是使用 NSStream 类来解析传入的增量 XML 数据。数据从来都不是完整的 XML 文档,但我想根据套接字可以读取的数量以增量 block 的形式接收和处理它。

查看 NSXMLParser 的文档,似乎使用 initWithStream: 方法来初始化 NSXMLParser 是解决我的问题的完美方法.我可以使用 NSInputStream 初始化解析器,然后在通过套接字接收数据时调用 NSXMLParser 上的 parse 方法,而套接字又会调用NSXMLParser 委托(delegate)。

但是,我没有看到任何委托(delegate)被调用,我看到被调用的唯一方法是流委托(delegate) stream:handleEvent:。 Apple 或其他开发人员似乎几乎没有此 API 的示例。关于我做错了什么或如何正确使用 initWithStream: 的任何想法?

ContentParser.h

@interface ContentParser : NSObject <NSStreamDelegate, 
NSXMLParserDelegate>
{
NSInputStream *inputStream;
NSOutputStream *outputStream;
NSMutableData *receivedData;
NSXMLParser *xmlParser;
}
- (void)initStream;

ContentParser.m

@implementation ContentParser

- (void)initStream
{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;

CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
(CFStringRef)@"<hostname>",
<port>,
&readStream,
&writeStream);

inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;

inputStream.delegate = self;
outputStream.delegate = self;

[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];

[inputStream open];
[outputStream open];

xmlParser = [[NSXMLParser alloc] initWithStream:inputStream];
[xmlParser setDelegate:self];
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
NSLog(@"didStartElement: %@, attributeDict: %@", elementName, attributeDict);
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSLog(@"foundCharacters: %@", string);
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
NSLog(@"didEndElement: %@", elementName);
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSLog(@"Error %ld, Description: %@, Line: %ld, Column: %ld",
[parseError code], [[parser parserError] localizedDescription],
[parser lineNumber], [parser columnNumber]);
}


- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventHasBytesAvailable:
{
if (stream == inputStream) {
NSInputStream *is = (NSInputStream *)stream;
if (receivedData == nil) {
receivedData = [[NSMutableData alloc] init];
}

uint8_t buf[1024];
NSInteger bytesRead = [is read:buf maxLength:1024];
if (bytesRead == -1) {
NSLog(@"Network read error");
} else if (bytesRead == 0) {
NSLog(@"No buffer received");
} else {
[receivedData appendBytes:buf length:bytesRead];
BOOL parserResult = [xmlParser parse];
if (parserResult == NO) {
NSLog(@"Unable to parse XML");
}
}
}
break;
}
default:
break;
}
}

@end

最佳答案

我弄清楚了问题所在并在这里回答它,以防将来其他人遇到这个问题,因为 +[NSXMLParser initWithStream] 没有很多文档。

我需要在分配 NSXMLParser 并将自己设置为委托(delegate)后立即调用 -[NSXMLParser parse]。但是因为它是一个同步函数,我需要调用它另一个线程,这样我就不会阻塞当前线程并且它可以接收 NSStream 事件。我也不需要让自己成为 NSInputStream 的委托(delegate)。

这可以很简单地使用 Grand Central Dispatch (GCD) 来完成,如下所示:

// alloc and init the xml parser
xmlParser = [[NSXMLParser alloc] initWithStream:inputStream];
[xmlParser setDelegate:self];

// block to execute
dispatch_block_t dispatch_block = ^(void)
{
[xmlParser parse];
};

// create a queue with a unique name
dispatch_queue_t dispatch_queue = dispatch_queue_create("parser.queue", NULL);

// dispatch queue
dispatch_async(dispatch_queue, dispatch_block);

// cleanup
dispatch_release(dispatch_queue);

这是完整的工作示例,以防万一有人无法理解我在上面发布的内容。

ContentParser.h

@interface ContentParser : NSObject <NSStreamDelegate, 
NSXMLParserDelegate>
{
NSInputStream *inputStream;
NSOutputStream *outputStream;
NSMutableData *receivedData;
NSXMLParser *xmlParser;
}
- (void)initStream;

ContentParser.m

@implementation ContentParser

- (void)initStream
{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;

CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
(CFStringRef)@"<hostname>",
<port>,
&readStream,
&writeStream);

inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;

outputStream.delegate = self;

[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];

[inputStream open];
[outputStream open];

xmlParser = [[NSXMLParser alloc] initWithStream:inputStream];
[xmlParser setDelegate:self];

dispatch_block_t dispatch_block = ^(void)
{
[xmlParser parse];
};
dispatch_queue_t dispatch_queue = dispatch_queue_create("parser.queue", NULL);
dispatch_async(dispatch_queue, dispatch_block);
dispatch_release(dispatch_queue);
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
dispatch_block_t dispatch_block = ^(void)
{
NSLog(@"didStartElement: %@, attributeDict: %@",
elementName, attributeDict);
};
dispatch_queue_t main_queue = dispatch_get_main_queue();
dispatch_async(main_queue, dispatch_block);
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
dispatch_block_t dispatch_block = ^(void)
{
NSLog(@"foundCharacters: %@", string);
};
dispatch_queue_t main_queue = dispatch_get_main_queue();
dispatch_async(main_queue, dispatch_block);
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
dispatch_block_t dispatch_block = ^(void)
{
NSLog(@"didEndElement: %@", elementName);
};
dispatch_queue_t main_queue = dispatch_get_main_queue();
dispatch_async(main_queue, dispatch_block);
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
dispatch_block_t dispatch_block = ^(void)
{
NSLog(@"Error %ld, Description: %@, Line: %ld, Column: %ld",
[parseError code], [[parser parserError] localizedDescription],
[parser lineNumber], [parser columnNumber]);
};
dispatch_queue_t main_queue = dispatch_get_main_queue();
dispatch_async(main_queue, dispatch_block);
}

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventHasSpaceAvailable:
{
/* write bytes to socket */
break;
}
default:
break;
}
}

@end

关于objective-c - 使用 NSXMLParser initWithStream : no parser delegate methods received,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10777604/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com