Po pierwsze: wykonanie defer
, ponieważ wyraźnie widać, dodając do niego .
teraz wyjaśnić, dlaczego zwrócona wartość nie odzwierciedla wartości Zmieniono:
Powodem tego jest to, że String
jest niezmienna - kiedy piszesz str += something
utworzyć zupełnie nową String
instancji i przechowywać go wewnątrz str
.
Jeśli napiszesz return str
, która zwróci bieżące wystąpienie str
, które jest 123yyy4
. Następnie wywoływana jest nazwa defer
i przypisuje ona zupełnie nową i niepowiązaną ze sobą definicję: String
123yyy4xxx
do . Ale to nie zmienia poprzedniego obiektu String
przechowywanego wewnątrz str
, po prostu go zastępuje i dlatego nie ma wpływu na return
, który już "zdarzył się".
przypadku zmiany sposobu korzystania z NSMutableString
zamiast będziesz zawsze działają na samym instancji, a wynik będzie zatem poprawnie wyjście 123yyy4xxx
:
func branch() -> NSMutableString {
var str = NSMutableString()
defer { str.appendString("xxx") }
str.appendString("1")
let counter = 3;
if counter > 0 {
str.appendString("2")
defer { str.appendString("yyy") }
str.appendString("3")
}
str.appendString("4")
return str
}
let bran1 = branch()
W tym kodzie Zwraca instancję przechowywane w str
i odracza zmianę tej instancji , nie przypisuje nowej instancji, ale zmienia już istniejącą.
Przez wzgląd na wyjaśnienie można spróbować zobaczyć adres pamięci str
na różnych etapach:
- w czasie
return
- przed zmianą
str
w bloku defer
- po zmianie go
Dla NSMutableString
wszystkie trzy przypadki dadzą taki sam adres pamięci w g, że instancja pozostaje taka sama. Ten jednak drukuje dwa różne adresy pamięci, w wyniku czego zwracany łańcuch wskazuje na someAddress
, a ten z opóźnieniem wskazuje na someOtherAddress
.
to działa, ale 'defer' jest wywoływana _after_ zakres wybiega zatem pierwszy Wywoływany jest 'return str', a następnie zakres kończy się i wywołuje twoje' odroczenie' i dodaje '' xxx' 'do instancji lokalnej, która się dzieje po powrocie wartości. – holex