繁体   English   中英

如何将包含字符串的消息结构作为NSData发送给Game Center

[英]How to send message struct containing a string as NSData for Game Center

我正在尝试创建一个多人游戏,该游戏将使用Game Center在玩家之间传送动作。 我仍然在学习编程方面的很多知识,所以,如果我的问题格式错误,请原谅。 另外,我对Obj-C不太熟悉,因此Swift的回答会很棒。

在我的玩具程序中尝试自我教,的过程中,我尝试通过此处的GameKitHelper类遵循Shayne Meyer所使用的策略: https : //github.com/shaynemeyer/SwiftCircuitRacer/tree/master/SwiftCircuitRacer

使用这种方法,Shayne使用NSData发送的结构将消息在线发送给其他玩家。 我能够发送整数(例如ILoveYou消息),但不能发送带有字符串属性的消息(例如,感谢消息)。 在后一种情况下,我在“ var messageThanks = UnsafePointer,MesssageThanks>(data.bytes).memory”行得到“线程1:EXC_BAD_ACCESS(code = 1,地址= 0x78674100)”。

最终,我想发送同时提供字符串和整数的游戏动作。 当属性还包含字符串时,如何将消息结构作为NSData发送? 其次,如果有人可以帮助我从根本上理解打包数据时正在发生的事情以及UnsafePointer与通过Game Center发送数据有关的情况,我将不胜感激。

谢谢。 悬崖

enum MessageType: Int {
    case ILoveYou, Thanks
}

struct Message {
    let messageType: MessageType
}    
struct MessageILoveYou {
    let message: Message
    let messageSenderNumber: UInt32    
}

struct MessageThanks {
    let message: Message
    let messageSenderName: String
    let messageSenderNumber: UInt32    
}

func sendILoveYou() {    
    println("sendILoveYou:")
    let nameNumber = UInt32(56)
    var message = MessageILoveYou(message: Message(messageType: MessageType.ILoveYou), messageSenderNumber: nameNumber)
    let data = NSData(bytes: &message, length: sizeof(MessageILoveYou))
    sendData(data)    
}

func sendThanks() {
    println("sendThanks:")
    let nameString = "Don J"
    let senderNumberInt = UInt32(88)
    var message = MessageThanks(message: Message(messageType: MessageType.Thanks), messageSenderName: nameString, messageSenderNumber: senderNumberInt)        
    let data = NSData(bytes: &message, length: sizeof(MessageThanks))
    sendData(data)        
}

func matchReceivedData(match: GKMatch, data: NSData, fromPlayer player: String) {

    println("matchReceivedData:")
    var message = UnsafePointer<Message>(data.bytes).memory        
    if message.messageType == MessageType.ILoveYou {            
        println("messageType == ILoveYou")
        let messageILoveYou = UnsafePointer<MessageILoveYou>(data.bytes).memory
        iLoveYouThanksDelegate?.iLoveYouReceived(from: messageILoveYou.messageSenderNumber)

    } else if message.messageType == MessageType.Thanks {            
        println("messageType == Thanks")
        var messageThanks = UnsafePointer<MessageThanks>(data.bytes).memory
        iLoveYouThanksDelegate?.thanksReceived(from: messageThanks.messageSenderName)
    }
}

func sendData(data: NSData) {
    var sendDataError: NSError?
    let gameKitHelper = GameKitHelper.sharedInstance

    if let multiplayerMatch = gameKitHelper.multiplayerMatch {
        let success = multiplayerMatch.sendDataToAllPlayers(data, withDataMode: .Reliable, error: &sendDataError)
        if !success {
            if let error = sendDataError {
                println("Error:\(error.localizedDescription)")
                matchEnded()
            }
        }
    }
}

这里的问题是,当您在Swift中创建一个String时,它本身会分配一点内存,然后使用该内存来存储字符串的实际字符。 字符串值真正保留的只是代表该内存的指针的一些数据和其他一些信息(例如已分配了多少内存,以便可以正确释放它)。

您可以在这里看到:

let str = "This is quite a long string, certainly more than 24 bytes"
sizeofValue(str)  // and yet this only returns 24

当您将变量填充到NSData对象中时,初始化程序将使用一个指针,该指针指向保存这些指针的字符串变量的内存, 而不是字符本身:

// only storing those 24 bytes, not the actual string
let data = NSData(bytes: &str, length: sizeofValue(str))

注意, bytes参数的类型是UnsafePointer<Void> 这表明您正在进入棘手的领域。

然后,当您在另一端解组数据时,您的接收器将获得的只是指向随机存储器的指针(可悲的是,另一用户设备上的存储器!)。

如果要将字符串值放入NSData对象,则需要首先将它们编组为原始数据。 例如,您可以将它们编码为一个数组:

let data = Array(str.utf8).withUnsafeBufferPointer { buf in
    NSData(bytes: buf.baseAddress, length: buf.count)
}

碰巧的是,由于这是常见的事情,因此有一种直接执行此操作的方法:

let data = str.dataUsingEncoding(NSUTF8StringEncoding)

然后,要解压缩数据,可以从NSData对象使用NSString的构造函数:

let newStr = NSString(data: data, encoding: NSUTF8StringEncoding)

编辑:如果您想在单个NSData编码多个字符串,则可以按照以下方式做一些事情……我应该说,我从来没有自己做过这个事情,所以我对标准做法一点都不熟悉为此,可能会有更好的技术或助手类/功能。 希望有更多经验的人可以编辑以显示如何正确执行此操作:)

var type = MessageType.Thanks

// start the data with the type
let data = NSMutableData(bytes: &type, length: sizeofValue(type))

// then append the string
data.appendData(Array(str.utf8).withUnsafeBufferPointer { buf in
    NSMutableData(bytes: buf.baseAddress, length: buf.count)
    })

switch UnsafePointer<MessageType>(data.bytes).memory {
case .ILoveYou:
// ...
case .Thanks:
    let str = NSString(data: data.subdataWithRange(NSMakeRange(1, data.length-1)), encoding: NSUTF8StringEncoding)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM