2017-07-06 8 views
0

Ich habe mit einem Problem zu kämpfen. Ich möchte eine Struktur an verbundene Geräte senden.Swift 3, Multipeer, sende struct als Daten

ist hier der Code, den ich in Spielplatz

Im Code

ich einige Erweiterung der Datenklasse kopiert verwenden für die Codierung/Decodierung hinzugefügt. Ich erstelle ein Dictionary von [String: Player] und benutze NSKeyedArchiver, um einen zu sendenden Datensatz zu erstellen.

Ich mache das hier nicht senden, aber in meinem Programm tue ich. Hier auf dem Spielplatz funktioniert der Code/Decodierung gut. Wenn ich es in meinem Programm mache, schlägt die Decodierung fehl, wenn der Player aus Daten extrahiert wird. Es schlägt fehl mit: EXC_BAD_ACCESS

Wenn ich eine Zeichenfolge anstelle der Player-Struktur verwenden, dekodiert es in der DidReceive-Datenfunktion. Fällt nur bei Verwendung eines Struct.

Jeder mit einigen Vorschlägen?

//: 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" 

Antwort

1

Was für mich funktionierte, war eine benutzerdefinierte Klasse, die von NSObject erbt und NSCoding entspricht.

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") } 
    } 
} 

Stellen Daten senden:

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

Daten zurück an einen Spieler:

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

Vielen Dank! Das funktioniert genau so, wie ich es will, ohne Fehler! – teho

+0

Ich fand hier eine bessere Lösung: https://stackoverflow.com/a/41538762/2957546 – teho