我试图在Swift中编写一个Mac应用程序,该应用程序通过http://rsms.me/peertalk/提供的名为PeerTalk的库与iOS设备进行通信,因此我一直试图在Swift中重写PeerTalk示例项目。我的Swift重写可以正确连接并从iOS设备接收消息,但无法读取消息而不会崩溃。
struct PTExampleTextFrame {
let length: UInt32
let utf8text: [UInt8]
}
func ioFrameChannel(channel: PTChannel?, didReceiveFrameOfType type: UInt32, tag: UInt32, payload: PTData?) {
if (type == PTExampleFrameTypeDeviceInfo) {
let deviceInfo: NSDictionary? = NSDictionary(contentsOfDispatchData: payload!.dispatchData)
self.presentMessage(NSString(format: "Connected to %@", deviceInfo!.description), isStatus:true)
} else if (type == PTExampleFrameTypeTextMessage) {
let textFramePointer = UnsafeMutablePointer<PTExampleTextFrame>(payload!.data)
let textFrameOptional: PTExampleTextFrame? = textFramePointer.memory
let textFrame: PTExampleTextFrame
if textFrameOptional != nil {
textFrame = textFrameOptional!
println(ntohl(textFrame.length))
println(textFrame.utf8text)
} else {
println("Recieved bad packet")
}
} else if (type == PTExampleFrameTypePong) {
self.pongWithTag(tag, error:nil)
}
}
以下是我遇到的唯一问题和结构。
let textFramePointer = UnsafeMutablePointer<PTExampleTextFrame>(payload!.data)
let textFrameOptional: PTExampleTextFrame? = textFramePointer.memory
let textFrame: PTExampleTextFrame
if textFrameOptional != nil {
textFrame = textFrameOptional!
println(ntohl(textFrame.length))
println(textFrame.utf8text)
} else {
println("Recieved bad packet")
}
当我的应用收到消息时,ioFrameChannel函数将成功调用,并在崩溃之前打印发送的消息的正确长度。
Thread 1: EXC_BAD_ACCESS (code=1, address=0x10)
当打印textFrame.utf8text的行运行时。
用不包含数组的struct替换struct可以按预期方式成功打印消息的第一个字符的UTF-8表示形式。
struct PTExampleTextFrame {
let length: UInt32
let utf8text: UInt8
}
上面的工作在Objective C中完成,如下面的示例项目所示
//PTExampleProtocol.h
typedef struct _PTExampleTextFrame {
uint32_t length;
uint8_t utf8text[0];
} PTExampleTextFrame;
//PTAppDelegate.m
- (void)ioFrameChannel:(PTChannel*)channel didReceiveFrameOfType:(uint32_t)type tag:(uint32_t)tag payload:(PTData*)payload {
//NSLog(@"received %@, %u, %u, %@", channel, type, tag, payload);
if (type == PTExampleFrameTypeDeviceInfo) {
NSDictionary *deviceInfo = [NSDictionary dictionaryWithContentsOfDispatchData:payload.dispatchData];
[self presentMessage:[NSString stringWithFormat:@"Connected to %@", deviceInfo.description] isStatus:YES];
} else if (type == PTExampleFrameTypeTextMessage) {
PTExampleTextFrame *textFrame = (PTExampleTextFrame*)payload.data;
textFrame->length = ntohl(textFrame->length);
NSString *message = [[NSString alloc] initWithBytes:textFrame->utf8text length:textFrame->length encoding:NSUTF8StringEncoding];
[self presentMessage:[NSString stringWithFormat:@"[%@]: %@", channel.userInfo, message] isStatus:NO];
} else if (type == PTExampleFrameTypePong) {
[self pongWithTag:tag error:nil];
}
}
我预计崩溃与Swift不知道数组何时停止有关。如何在Swift中读取整个消息而又不会导致应用程序崩溃?
最佳答案
当我进一步了解Swift时,似乎长度为0的ObjC结构作为零元组导入了swift中。固定长度数组作为元组导入,因为固定长度数组在Swift中不存在。我假设一个指向零元组的指针可以达到这个目的。但是,我没有进行测试,因为没有使用此协议(protocol),而是重写了iOS应用并完全更改了协议(protocol),甚至不需要这种奇怪的结构。