使用 NSXMLParser initWithStream:未收到解析器委托方法

2023-12-06

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

查看文档NSXMLParser,看起来像initWithStream:方法来初始化一个NSXMLParser将是我的问题的完美解决方案。我可以用一个初始化解析器NSInputStream然后调用parse方法上NSXMLParser每当我通过套接字接收数据时,该数据应该依次调用NSXMLParser代表们。

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

内容解析器.h

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

内容解析器.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 parse]在我分配之后NSXMLParser并指定我自己为代表。但因为它是一个同步函数,所以我需要在另一个线程中调用它,这样我就不会阻塞当前线程并且它可以接收NSStream事件。我也不需要让自己成为代表NSInputStream.

使用 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);

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

内容解析器.h

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

内容解析器.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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 NSXMLParser initWithStream:未收到解析器委托方法 的相关文章

  • Xcode 6.4 Swift 单元测试无法编译:“GPUImage.h 未找到”“无法导入桥接标头”

    我的 Xcode 项目构建并运行良好 它有 Swift 和 Objective C 代码 它已安装 GPUImage 我向它添加了单元测试 现在它将不再编译 找不到 GPUImage h 文件 导入桥接标头失败 以下是我发现并尝试过的解决方
  • 在后台每 X 分钟执行一次函数不起作用

    我使用此代码每 X 分钟执行一次函数 void executeEveryOneMinute self myFunction dispatch after dispatch time DISPATCH TIME NOW int64 t 60
  • 使用 iPhone 控制蓝牙音频设备

    我正在寻找为 iPhone 编写应用程序 它将能够控制汽车中的收音机和 CD 播放器 收音机和播放器具有可用的蓝牙连接 我开始这个问题是为了获得这个地方所需的所有信息 我有几个问题 但如果您发现任何我没有要求的对我开始开发此应用程序不重要的
  • 如何读取 Xcode 6.1 Instruments .trace 文件?

    我一直在尝试阅读 trace文件 我使用生成的custom仪器模板 仪器 自动机 分配 Leaks using 仪器 https developer apple com library mac documentation Developer
  • 如何将数据从一个视图传递到下一个视图?

    我正在制作一个下载排队系统来下载视频 处理下载的排队代码位于另一个视图控制器中 现在我的问题是如何将下载的 URL 传递到另一个视图而不推送到另一个视图控制器 如下所示 ViewConntroller View ViewConntrolle
  • 如何将 CIFilter 输出到相机视图?

    我刚刚开始使用 Objective C 我正在尝试创建一个简单的应用程序 它显示带有模糊效果的相机视图 我得到了与 AVFoundation 框架一起使用的相机输出 现在 我正在尝试连接 Core 图像框架 但不知道如何连接 Apple 文
  • iOS:我如何知道某个属性是否符合 KVO 标准?

    In the 键值观察编程指南 https developer apple com library archive documentation Cocoa Conceptual KeyValueObserving KeyValueObser
  • 如何生成Mac应用程序的安装包?

    如何为 OS X 二进制文件以及一些配置和脚本文件创建单个安装程序包 最终文件夹应如下所示 任何帮助 将不胜感激 谢谢 如果您希望将各种东西放置在不同的位置 安装程序在这里 文档在那里 支持文件在这里等等 它们也非常适合提供安装体验的可配置
  • Cocoa 基于文档的应用程序中的 MVC

    我目前正在对我的应用程序进行重构和重组 我意识到模型和视图及其控制器之间的一些分离已经减少 我希望进行一些清理 我的应用程序中使用了几个关键类 NSPersistentDocument NSWindowController 和模型类 NSP
  • 如何检测 UISearchBar/UITextField 输入中的暂停?

    我有以下 UISearchbar 代码 void searchBar UISearchBar searchBar textDidChange NSString searchText UIApplication sharedApplicati
  • 在 Swift 中使用 commitEditingStyle 动态删除 UITable 部分

    我正在处理一个无法解决的问题 我有一个来自客户数据库数组的名称表 每个客户在其他数据成员中都有一个名称属性 我可以成功删除某个部分中的行 但我不能删除该部分 当该部分中的最后一行被删除时 该部分必须消失 I got NSInternalIn
  • 显示器连接或断开连接时的通知

    我正在开发一个 OS X 应用程序 该应用程序在所有连接的显示器的所有可用空间上显示自定义窗口 我可以通过调用 NSScreen Screens 获取可用显示对象的数组 我目前缺少的是一种判断用户是否将显示器连接到系统或从系统断开屏幕的方法
  • 为什么没有收到(UDP 多播)数据包?

    所以 我一直试图弄清楚为什么这不起作用 但我没有任何线索 我已经成功地从 iPhone 发送数据包并在 Mac 上接收它们 根据 tcpdump 我的 mac 正确发送数据包 此外 如果我在模拟器中运行它 它工作得很好 这让我相信这是一个网
  • CGContextSelectFont 等效项

    在 iOS 7 CGContext SelectFont 中已弃用 已弃用的消息说我必须使用 Core Text 但我不知道哪一个与这段代码完全相同 CGContextSelectFont context Helvetica kBarLab
  • Xcode 4 调试器代码完成

    首先 很高兴他们尝试在 Xcode 4 中的 gdb 命令提示符上完成代码 但在当前状态下 它使得使用命令提示符来调查目标 c 对象几乎不可能 当我打字时 它自动将单词补全为我不想要的内容 并且如果不手动选择文本并将其删除 然后重新开始 则
  • 使用自动布局、IB 和字体大小时表头视图高度错误

    我正在尝试为我的 uiTableView 创建一个标题视图 不是节标题 我已经有了 我已经在界面生成器中设置了一个 XIB 所有的连接都已连接好并且运行良好 除了桌子没有给它足够的空间 我的问题是表格顶部与表格标题有一点重叠 我的 XIB
  • 如何为图层阴影不透明度设置动画?

    我有一个视图 我已将 LayerOpacity 设置为 1 theView layer shadowOpacity 1 0 当视图位于屏幕下方时 这看起来很好 当我将此视图向上移动以与另一个有阴影的视图齐平时 它们看起来不太好 有没有办法让
  • 如何检索 iPhone 的区域设置

    我用谷歌搜索过它 但令我有点惊讶的是我找不到它 我只想访问设备配置的区域设置 我试图找到如何列出所有系统属性 以防我能在那里找到区域设置 但甚至找不到如何做到这一点 我知道 认为 我之前检索过系统属性 但我也记得在谷歌搜索时找到该信息并不容
  • WiFi 网络变化是否有 NSNotificationCenter 通知?

    我想在我的 Cocoa 应用程序中订阅 WiFi 网络更改 但我无法找到合适的事件来订阅 WiFi 网络变化是否有 NSNotificationCenter 通知 据我所知 我会用CoreWLAN https developer apple
  • 在成为FirstResponder或resignFirstResponder的情况下将对象保持在键盘顶部?

    我目前在键盘顶部有一个 UITextField 当您点击它时 它应该粘在键盘顶部并平滑地向上移动 我不知道键盘的具体时长和动画类型 所以确实很坎坷 这是我所拥有的 theTextView resignFirstResponder UIVie

随机推荐

  • 需要使用TypeORM/NestJS在PostgreSQL数据库中上传文件

    任何人都可以帮忙解决这个问题吗 我需要使用 TypeORM NestJS 将文件上传到 PostgreSQL 数据库 文件是表单的一部分 我已经采取了以下实体类 export class Certificate ApiProperty Pr
  • 如何在R中写出具有不同文件名的多个文件

    我有一个大文件 gt 10000 行数据 我想按 ID 写出一个单独的文件 我有 50 个唯一的 ID 名称 我想要为每个名称创建一个单独的文本文件 这是我到目前为止所得到的 但我不断收到错误 我的ID实际上是字符串 如果我能用该字符串命名
  • 使用 sqlalchemy 和 mysql unix 时间戳定义表

    背景 MySQL 中有多种存储日期的方法 作为字符串 例如 2009 年 9 月 9 日 作为使用函数 UNIX TIMESTAMP 的整数 这被认为是传统的 UNIX 时间表示 您知道自纪元加 减闰秒以来的秒数 作为MySQL TIMES
  • HTML5发布及修改时间

    我想包括一篇文章的发表和修改时间 我查看了文档 但找不到有关此的信息 到目前为止 我得到了这个
  • QFile::flush() 与 QFile::close()

    我正在类中实现一个方法 它将数据从 TableView 对象写入 CSV 文件 然而 当程序运行时 程序以非常慢的速度 3或4秒 将数据写入USB驱动器上的文件 但在系统的内部驱动器上运行良好 这是因为我在写入文件后没有使用flush 或c
  • 如何在 Android Gridview 中设置替代行颜色?

    如何在网格视图中设置替代行颜色 我搜索了很多关于如何设置网格视图行颜色的教程 但没有关于网格视图行颜色的信息 我得到的列表视图仅具有替代行颜色 我需要交替行应该是白色和黑色 在这里我包括我的代码 请帮我 这是 Java 类 public c
  • 正则表达式用逗号替换客户评论中的一些点

    我需要写一个正则表达式来替换 with 在一些患者对药物的评论中 他们应该在提到副作用后使用逗号 但其中一些使用了点 例如 text the drug side effects are night mare nausea night swe
  • 透明地记录下载的最佳方式?

    我有一个个人项目 已经上线一段时间了 我一直通过这样做来记录下载量 当用户单击下载链接时 它会点击一个 PHP 脚本 该脚本将一些信息写入表中 写入数据后 脚本将返回实际文件的路径 然后 用户可以将文件保存到硬盘上 就像下载任何其他文件一样
  • ListViewAnimations 库导致顶级异常

    我正在尝试将此库嵌入到我的 Android 项目中 正如他们的 wiki 中所说 我做了很少的事情 添加了 gradle 编译行compile com nhaarman listviewanimations library 2 6 0 然后
  • 新的 iOS 应用程序与 Facebook Graph api v2.0 作斗争

    我是应用程序开发新手 我一直在构建一个社交 iOS 应用程序 需要发送 Facebook 邀请才能加入该应用程序 昨天发布的 Facebook Graph API 2 0 似乎对如何邀请尚未参与游戏的人提出了更严格的要求 我正在尝试激活 m
  • 如何使设备顶部面板(状态栏)与flutter中的AppBar具有相同的背景颜色?

    如何使设备顶部面板 状态栏 与flutter中的AppBar具有相同的背景颜色 设备顶部面板的颜色始终比 AppBar 背景颜色深 多谢 在 iOS 上 这已经是事实了 在 Android 上 添加以下内容onCreate in MainA
  • Apache RewriteRule 用于删除任何域名上的端口

    我有一台具有一个 IP 地址的虚拟服务器 为几个不同的站点提供服务 其中之一带有 SSL 证书 我需要在第二个域上添加 SSL 证书供我自己私人使用 由于我只有一个 IP 地址 所以我将其添加到端口 8080 上 这很好用 我现在的问题是
  • 为什么flink容器vcore大小始终为1

    我在yarn上运行flink 更准确地说是在AWS EMRyarn集群中 我阅读了flink文档和源代码 默认情况下 对于每个任务管理器容器 当从yarn请求资源时 flink将请求每个任务管理器的插槽数量作为vcore的数量 而且我也从源
  • 如何在R中将二进制小数转换为十进制小数?

    我需要编写一个函数 将二进制小数转换为 R 中的十进制小数 f 0 001 0 125 我做了什么 我搜索了R包中的相关函数 DescTools BinToDec 0 001 NA DescTools BinToDec 0 001 NA b
  • React Ionic 5:如何将对象从App组件传递到Tab组件

    我使用 Ionic 5 选项卡模板创建了一个 Ionic React 应用程序 我想将一个对象从应用程序组件传递到选项卡组件 有什么办法可以做到吗 Tab1 和 Tab2 是我的选项卡组件 Note 我希望这个对象在两个选项卡组件中使用两种
  • 扫描直到新行

    我想读取输入的所有文本 直到输入新行字符 这是我的代码 int i 0 char ch MAX printf Enter the text n while true scanf c ch i if ch i n break i 但当我尝试执
  • Clang 3.7.0 抱怨类不是字面意思,因为它不是聚合并且没有 constexpr 构造函数

    以下代码在 GCC 4 9 3 和 VC 19 00 23506 中编译良好 但在 Clang 3 7 0 中给出这些错误 错误 constexpr 函数的返回类型 Foo 不是文字类型 注意 Foo 不是字面意思 因为它不是聚合并且没有
  • C++ 中的向量初始化

    我在代码中使用向量 导致错误的行如下 vector
  • 如何使用 Vbscript 重写和写入文本文件

    我使用以下 VBscript 在 commonapplicationdatafolder 中创建了一个文本文件 list txt 我正在显示一些 通过写入文本文件来获取变量 strlist 的值 Const Value H23 Const
  • 使用 NSXMLParser initWithStream:未收到解析器委托方法

    我正在解决的基本问题是使用NSStream用于解析传入的增量 XML 数据的类 数据从来都不是完整的 XML 文档 但我希望根据套接字可以读取的数据量以增量块的形式接收和处理它 查看文档NSXMLParser 看起来像initWithStr