2017-07-06 4 views
0

私は問題に苦しんでいます。私は接続されたデバイスに構造体を送りたい。ここSwift 3、Multipeer、データを構造体として送信

私は使用コードはコードで遊び場

にコピーされるIは、符号化/復号化するためのデータクラスにいくつかの拡張機能を追加しました。 [String:Player]の辞書を作成し、NSKeyedArchiverを使用して送信するデータレコードを作成します。

ここでは送信しませんが、私のプログラムでは行いません。ここでは、プレイグラウンドでコード/デコードが正常に動作します。私のプログラムでそれを行うと、データからPlayerを抽出するときにデコードが失敗します。それは失敗します:EXC_BAD_ACCESS

Playerの代わりにStringを使用すると、didReceiveデータ関数で正常にデコードされます。構造体を使用する場合にのみ失敗します。

提案がありますか?

//: Playground - noun: a place where people can play 
import UIKit 

// Player structure 
struct Player { 
    var initials : String 
    var name : String 
} 

// 
// Data extension 
// 
extension Data { 

    // struct 
    init<T>(from value: T) { 
     var value = value 
     self.init(bytes: &value, count: MemoryLayout<T>.size) 
    } 

    // extract Struct 
    func extract<T>(from: T.Type) -> T { 
     return self.withUnsafeBytes { $0.pointee } // FAILS HERE: EXC_BAD_ACCESS 
    } 
} 

// Make a data record for sending 
let sply = Player(initials: "PN", name: "Player Name") 
let spda = Data(from: sply) 
let sdic : [String:Data] = ["Player" : spda] 
let sdta : Data = NSKeyedArchiver.archivedData(withRootObject: sdic) 

// Do the sending 
// ... send... 

//Decode 
// The following code that is used on the receiving device in 
// the "didReceive data" function. 
let rdic = NSKeyedUnarchiver.unarchiveObject(with: sdta) as! [String : Data] 
let rdta = rdic["Player"]! 
let rply = rdta.extract(from: Player.self) 
print(rply.name)  // Prints: "Player Name" 

答えて

1

私にとっては、NSObjectを継承し、NSCodingに準拠したカスタムクラスがありました。

class Player: NSObject, NSCoding { 
    var initials: String! 
    var name: String! 

    required convenience init(coder decoder: NSCoder) { 
     self.init() 
     self.initials = decoder.decodeObject(forKey: "initials") as! String 
     self.name = decoder.decodeObject(forKey: "name") as! String 
    } 

    convenience init(initials: String, name: String) { 
     self.init() 
     self.initials = initials 
     self.name = name 
    } 

    func encode(with aCoder: NSCoder) { 
     if let initials = initials { aCoder.encode(initials, forKey: "initials") } 
     if let name = name { aCoder.encode(name, forKey: "name") } 
    } 
} 

は、データを送信するようにしてください:

let data = NSKeyedArchiver.archivedData(withRootObject: Player(initials: "PN", name: "Player Name")) 

Playerに戻ってデータを取得します。

guard let player: Player = NSKeyedUnarchiver.unarchiveObject(with: data) as! Player? else { return } 
+0

おかげでたくさん!この作業は、私が間違いなく欲しいのと同じように! – teho

+0

私はここでより良い解決策を見つけました:https://stackoverflow.com/a/41538762/2957546 – teho

関連する問題