2016-09-05 11 views
7
protocols.forEach { $0.prop = nil } 

skutkuje:

Cannot assign to property: '$0' is immutable 

Pracowałem wokół to z:

protocols.forEach 
{ 
    var protocol = $0 

    protocol.prop = nil 
} 

Ale dlaczego kompilator w porządku z tym? Spodziewałbym się, że to rozwiąże.

+0

Czy obiekty są strukturami czy instancją klasy? – vacawama

+0

@vacawama Nie, dziękuję, że pytasz, w rzeczywistości są protokołami. –

+0

Dodaj '": class "' do twojego protokołu, jeśli wszystko, co implementuje twój protokół, jest klasą i będzie działać. – vacawama

Odpowiedz

17

Masz szereg elementów, które implementują protokół. Jeśli nie powiesz Swiftowi, że jest to protokół class, zakłada on, że może on zostać zaimplementowany przez struct.

W pętli forEach zasadniczo będzie istniała zmienna let (nazywana domyślnie $0) przypisana do każdej wartości w tablicy po kolei. Jeśli masz tablicę obiektów (instancji klasy), możesz zmodyfikować właściwości tego elementu. Jeśli masz tablicę elementów struct, to będą one niezmienne. Jeśli masz szereg elementów implementujących protokół, wówczas Swift potraktuje je jako bardziej restrykcyjne: struct, chyba że dodasz : class do definicji twojego protokołu.

Na przykład:

protocol Xyzzy: class { 
    var prop: Int? { get set } 
} 

class Fred: Xyzzy, CustomStringConvertible { 
    var description: String { return "\(prop)" } 
    var prop: Int? = 17 
} 

let objects: [Xyzzy] = [Fred(), Fred(), Fred()] 

print(objects) // [Optional(17), Optional(17), Optional(17)] 

objects.forEach { $0.prop = nil } 

print(objects) // [nil, nil, nil] 

Twój obejście:

protocols.forEach 
{ 
    var protocol = $0 

    protocol.prop = nil 
} 

prace dla obiektów klasy, ponieważ tworzy nową var wskaźnik do obiektu, a następnie, że pozwala na modyfikację obiektu. Uwaga: obejście to działa tylko w przypadku wystąpień klas. Jeśli Twój protokół jest zaimplementowany przez struct, nowa var będzie nową kopią elementu struct, a oryginalne w tablicy nie zostaną zmienione.

+0

Świetna odpowiedź, która pomaga uzyskać głębsze zrozumienie Swift. Dziękuję Ci! –