2016-01-11 8 views
17

Jeśli utworzyć szybką struct bez init, to mogę zadzwonić do kompilatora generowane domyślny memberwise initialiser, tak:swift - czy mogę wywołać init domyślny struct z mojej niestandardowej metody init?

struct OrderFill { 
    let price:Int 
    let qty: Int 
    let timeStamp: NSDate 
} 
let o = OrderFill(price: 2, qty: 1, timeStamp: someDate) 

Co chciałbym zrobić, to stworzyć metodę wygoda startowy do deserialise od słownik, który następnie łączy się z domyślnym init. Coś jak

struct OrderFill { 
    let price:Int 
    let qty: Int 
    let timeStamp: NSDate 

    init(dict:[String:AnyObject]) throws { 
     self.init(
      price: dict["price"] as! Int 
      qty: dict["qty"] as! Int 
      timeStamp: try parseDate(dict["ts"] as! String) 
    } 
} 
let o = OrderFill(someDict) 

Kiedy próbuję napisać ten kod choć kompilator (Xcode 7.2) daje mi błąd „dodatkowy argument«qty»na wezwanie”, jakby to nie widzi domyślny memberwise i próbuje rekurencyjnie wywoływać init(dictionary)

Potrafię napisać własny init użytkownika, lub mogę po prostu przypisać właściwości bezpośrednio z mojego init(dictionary), ale byłoby miło, gdybym mógł nawiązać połączenie. Czy jest jakikolwiek sposób zrobić to szybko?

Odpowiedz

40

Dodaj własny inicjator jako rozszerzenie do struktury. Rozszerzenia nie mogą usunąć istniejących funkcjonalności, więc zachowa domyślny inicjator struktury.

struct OrderFill { 
    let price: Int 
    let qty: Int 
    let timeStamp: NSDate 
} 

extension OrderFill { 

    init(dict: [String: AnyObject]) throws { 
     self.init(
      price: dict["price"] as! Int, 
      qty: dict["qty"] as! Int, 
      timeStamp: try parseDate(dict["ts"] as! String) 
     ) 
    } 
} 

let o = OrderFill(someDict) 
+2

To rodzaj hacky ale faktycznie działa ...: O – luk2302

+2

Może wydawać hacky, ale jest również w książce ... '' 'UWAGA Jeśli chcesz, aby Twój typ wartości, która ma zostać initializable z domyślny inicjator i inicjator członkowski, a także własne niestandardowe inicjatory, napisz niestandardowe inicjalizatory w rozszerzeniu, a nie jako część oryginalnej implementacji typu wartości. Aby uzyskać więcej informacji, zobacz Rozszerzenia – rob5408

5

Od the apple docs about Initialization:

rodzaje Struktura automatycznie otrzyma inicjator memberwise jeśli nie definiuje każdy z własnymi niestandardowymi inicjalizatorów

i

Zauważ, że jeśli zdefiniować niestandardowy inicjator dla typu wartości, nie będziesz już mieć dostępu do domyślnego inicjalizatora (lub inicjatora członka, jeśli jest to struktura) dla ten typ. Ograniczenie to zapobiega sytuacji, w której dodatkowy element niezbędny w bardziej złożonym inicjalizatorze jest obchodzony przez przypadkowo używającego jednego z automatycznych inicjalizatorów.

Dlatego odpowiedź brzmi: NO. Nie można dostarczyć niestandardowego inicjalizatora i używać inicjatora członka w tym samym czasie.

To brzmi jak this swift evolution proposal mówi o rozszerzeniu możliwości bieżącego inicjatora członka. Ale oczywiście to jeszcze nie jest możliwe, możesz jednak wciąż sprawdzić, jakie są ograniczenia obecnej sytuacji.

Powiązane problemy