【发布时间】:2014-04-27 05:59:32
【问题描述】:
我的 iOS 程序正在接收 JSON 数据并尝试解析它,但由于某种我无法确定的原因总是失败。多个线程几乎同时调用此函数。奇怪的是,这只是在我切换到使用 GCDAsyncSocket 后才开始发生的。下面是接收和解析数据的相关代码:
// Called whenever I want my program to receive null-terminated data from the server:
[socket readDataToData:[NSData dataWithBytes:"\0" length:1] withTimeout:10 tag:0];
- (void)socket:(GCDAsyncSocket *)sender didReadData:(NSData *)data withTag:(long)tag{ // a GCDAsyncSocket delegate method
[self didReceiveNetworkData:data];
}
- (void)didReceiveNetworkData: (NSData*) data{
if (TESTING) NSLog(@"Received network data of length %lu===\n%@\n===", (unsigned long) data.length, [[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding]);
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData: data
options:kNilOptions
error:&error];
if (!json){
NSLog(@"Got an error parsing received JSON data: %@", error);
return;
}
// Then I handle the dictionary (omitted code)…
}
日志和断点调试器说这是接收到的数据:
{
"responseType": -1
}
确切地说,它的字节是“{\n\t\"responseType\":\t-1\n}\0”。一旦 JSONObjectWithData 函数运行,我就会得到这个“垃圾结束”错误:
Got an error parsing received JSON data: Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (Garbage at end.) UserInfo=0x10b203800 {NSDebugDescription=Garbage at end.}
根据在线 JSON 测试人员和我自己在单独项目中的简单测试,这是有效的 JSON。那么为什么我会收到错误消息?我认为它可能是在抱怨空终止符之后的额外字节,所以我尝试通过制作一个 NSString 然后将其转回 NSData 来修剪它,但这并没有帮助:
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData: [[[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding] dataUsingEncoding: NSUTF8StringEncoding]
options:kNilOptions
error:&error];
因为使用 GCDAsyncSocket 是这个问题的始作俑者,我想知道它是否与多线程有关,但我真的想不出有什么理由这么重要。有什么想法吗?
附:我使用 GCDAsyncSocket 因为我不知道如何处理 Objective-C 中的低级套接字,所以我的原始代码有很多奇怪的错误。
【问题讨论】:
-
你能在一个一次只做一个请求的简单测试项目中复制这个问题吗?
-
我只是尝试编辑现有的,所以它只会从服务器查询一件事,因此只收到一条消息,我验证只有一个线程在调用它。问题仍然存在。但我应该早点尝试。
-
\0 最后是垃圾。正如它所说的那样。 JSON 不想要 NUL 终止的数据并且不接受它。它不允许在 CR、LF 和 TAB 之后的 任何 控制字符。绝对没有 NUL 字节。
标签: ios objective-c json sockets