Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 使用NSXMLParser initWithStream:未收到任何解析器委托方法_Objective C_Cocoa_Nsxmlparser_Nsstream_Nsinputstream - Fatal编程技术网

Objective c 使用NSXMLParser initWithStream:未收到任何解析器委托方法

Objective c 使用NSXMLParser initWithStream:未收到任何解析器委托方法,objective-c,cocoa,nsxmlparser,nsstream,nsinputstream,Objective C,Cocoa,Nsxmlparser,Nsstream,Nsinputstream,我正在研究的基本问题是使用NSStream类解析传入的增量XML数据。数据从来不是一个完整的XML文档,但我希望根据套接字的读取量以增量块的形式接收和处理数据 查看NSXMLParser的文档,初始化NSXMLParser的initWithStream:方法似乎是解决我问题的完美方法。我可以使用NSInputStream初始化解析器,然后在通过套接字接收数据时调用NSXMLParser上的parse方法,然后调用NSXMLParser委托 但是,我没有看到任何委托被调用,我看到被调用的唯一方法是

我正在研究的基本问题是使用
NSStream
类解析传入的增量XML数据。数据从来不是一个完整的XML文档,但我希望根据套接字的读取量以增量块的形式接收和处理数据

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

但是,我没有看到任何委托被调用,我看到被调用的唯一方法是流委托
stream:handleEvent:
。苹果或其他开发人员似乎很少甚至没有这种API的例子。关于我做错了什么或者如何正确使用
initWithStream:
有什么想法吗

ContentParser.h

@interface ContentParser : NSObject <NSStreamDelegate, 
                                     NSXMLParserDelegate>
{
   NSInputStream *inputStream;
   NSOutputStream *outputStream;
   NSMutableData *receivedData;
   NSXMLParser *xmlParser;
}
- (void)initStream;
@interface ContentParser : NSObject <NSStreamDelegate, 
                                     NSXMLParserDelegate>
{
   NSInputStream *inputStream;
   NSOutputStream *outputStream;
   NSMutableData *receivedData;
   NSXMLParser *xmlParser;
}
- (void)initStream;
@接口ContentParser:NSObject
{
NSInputStream*inputStream;
NSOutputStream*outputStream;
NSMutableData*接收数据;
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
@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
@实现内容解析器
-(void)initStream
{    
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
(CFStringRef)@“,
, 
&读流,
&writeStream);
inputStream=(uu桥NSInputStream*)readStream;
outputStream=(uu桥NSOutputStream*)writeStream;
inputStream.delegate=self;
outputStream.delegate=self;
[inputStream ScheduleInRunLop:[nsrunlop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[outputStream ScheduleUnloop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[输入流打开];
[输出流打开];
xmlParser=[[NSXMLParser alloc]initWithStream:inputStream];
[xmlParser setDelegate:self];
}
-(void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName
namespaceURI:(NSString*)namespaceURI
限定名称:(NSString*)qName
属性:(NSDictionary*)属性指令
{
NSLog(@“didStartElement:%@,attributeDict:%@”,elementName,attributeDict);
}
-(void)解析器:(NSXMLParser*)解析器查找字符:(NSString*)字符串
{
NSLog(@“foundCharacters:%@”,字符串);
}
-(void)parser:(NSXMLParser*)parser didEndElement:(NSString*)elementName
namespaceURI:(NSString*)namespaceURI
限定名称:(NSString*)qName
{
NSLog(@“didEndElement:%@”,elementName);
}
-(void)解析器:(NSXMLParser*)解析器解析错误发生:(NSError*)解析错误
{
NSLog(@“错误%ld,说明:%@,行:%ld,列:%ld”,
[parserError code],[parser parserError]localizedDescription],
[分析器行号],[分析器列号];
}
-(void)流:(NSStream*)流句柄事件:(NSStreamEvent)事件代码
{
开关(事件代码){
案例NSTRAVENTHASBYTES可用:
{
如果(流==输入流){
NSInputStream*是=(NSInputStream*)流;
如果(接收数据==nil){
receivedData=[[NSMutableData alloc]init];
}
uint8_t buf[1024];
NSInteger bytesRead=[is read:buf maxLength:1024];
如果(字节读==-1){
NSLog(@“网络读取错误”);
}else if(bytesRead==0){
NSLog(@“未收到缓冲区”);
}否则{
[receivedData appendBytes:buf长度:字节读取];
BOOL parserResult=[xmlParser parse];
if(parserResult==否){
NSLog(@“无法解析XML”);
}
}
}
打破
}
违约:
打破
}
}
@结束

我不确定这一点,但我不认为每次流报告事件时都需要发送
parse
initWithStream:
文档意味着解析器本身将处理输入。我想你应该这样做:

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

而且不用担心流委托方法。当您获得
parserdinddocument:
时,您可以关闭流。

我找出了问题所在,并在这里回答,以防将来其他人遇到此问题,因为
+[NSXMLParser initWithStream]
没有太多文档

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

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

这是一个完整的工作示例,以防任何人都无法理解我上面发布的内容

ContentParser.h

@interface ContentParser : NSObject <NSStreamDelegate, 
                                     NSXMLParserDelegate>
{
   NSInputStream *inputStream;
   NSOutputStream *outputStream;
   NSMutableData *receivedData;
   NSXMLParser *xmlParser;
}
- (void)initStream;
@interface ContentParser : NSObject <NSStreamDelegate, 
                                     NSXMLParserDelegate>
{
   NSInputStream *inputStream;
   NSOutputStream *outputStream;
   NSMutableData *receivedData;
   NSXMLParser *xmlParser;
}
- (void)initStream;
@接口ContentParser:NSObject
{
NSInputStream*inputStream;
NSOutputStream*outputStream;
NSMutableData*接收数据;
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
@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
@实现内容解析器
-(void)initStream
{    
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFS