![](/img/trans.png)
[英]How to Covert struct with an Array of string to NSData and vice versa Swift
[英]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.