我试图在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),甚至不需要这种奇怪的结构。

10-05 20:45
查看更多