Na stronie 17 tej prezentacji WWDC14 jest napisane
Pracujesz z Objective-C? Nadal trzeba zarządzać pulami automatycznych
wydań autoreasepool {/ * kod * /}
Co to znaczy? Czy to oznacza, że jeśli moja baza kodu nie ma żadnych plików Objective-C, autoreleasepool {}
jest niepotrzebna?
W odpowiedzi na powiązane pytanie znajduje się przykład, który autoreleasepool
może być przydatny:
- (void)useALoadOfNumbers {
for (int j = 0; j < 10000; ++j) {
@autoreleasepool {
for (int i = 0; i < 10000; ++i) {
NSNumber *number = [NSNumber numberWithInt:(i+j)];
NSLog(@"number = %p", number);
}
}
}
}
Jeśli powyższy kod zostanie przetłumaczony na Swift z autoreleasepool
upuszczeniem, czy Swift będzie wystarczająco inteligentny, aby wiedzieć, że number
zmienna powinna zostać wydana po pierwszej }
(podobnie jak niektóre inne języki)?
memory-management
swift
Ethan
źródło
źródło
autoreleasepool
w języku Swift nie ma dokumentacji . I rozszerzony na swoje pytanie i poprosił go na forach dev .Odpowiedzi:
autoreleasepool
Wzór jest stosowany w Swift po powrocieautorelease
przedmiotów (utworzone przez którąkolwiek kod Objective-C lub za pomocą klas kakao).autorelease
Wzór funkcje Swift podobnie jak ma to miejsce w Objective-C. Na przykład rozważmy tę wersję Swift swojej metody (tworzenie instancjiNSImage
/UIImage
obiektów):func useManyImages() { let filename = pathForResourceInBundle for _ in 0 ..< 5 { autoreleasepool { for _ in 0 ..< 1000 { let image = NSImage(contentsOfFile: filename) } } } }
Jeśli uruchomisz to w Instrumentach, zobaczysz wykres alokacji podobny do poniższego:
Ale jeśli zrobisz to bez puli autorelease, zobaczysz, że szczytowe użycie pamięci jest wyższe:
autoreleasepool
Pozwala wyraźnie zarządzać gdy autorelease obiekty są zwalniane w Swift, podobnie jak udało ci się w Objective-C.Uwaga: w przypadku obiektów natywnych języka Swift na ogół nie otrzymujesz obiektów z automatycznym zwalnianiem. Dlatego w prezentacji wspomniano o zastrzeżeniu, że potrzeba tego tylko podczas „pracy z Objective-C”, chociaż chciałbym, aby Apple było bardziej jasne w tej kwestii. Ale jeśli masz do czynienia z obiektami Objective-C (w tym klasami Cocoa), mogą to być obiekty autorelease, w takim przypadku ta szybka interpretacja
@autoreleasepool
wzorca Objective-C jest nadal przydatna.źródło
println
indeinit
, i staje się dość łatwo sprawdzić dokładnie, kiedy obiekty są zwalniane. Lub obserwuj to w Instrumentach. W odpowiedzi na twoje pytanie wydaje się, że obiekty Swift są zwracane z funkcji z liczbą zachowań +1 (nie obiektów autorelease), a wywołujący bezproblemowo zarządza własnością od tego momentu (np. Jeśli i kiedy zwrócony obiekt znajdzie się poza zakresem, jest natychmiast zwalniany, a nie umieszczany w puli automatycznego ładowania).NSImage
/UIImage
obiektami i bardziej konsekwentnie pokazałem problem (i szczerze mówiąc, jest to bardziej powszechny przykład problemu, ponieważ szczytowe użycie pamięci jest często problematyczne tylko w przypadku większych obiektów; praktycznym przykładem może być rutynowa zmiana rozmiaru grupy obrazów). Odtworzyłem również zachowanie wywołujące kod Objective-C, który jawnie tworzył obiekty autorelease. Nie zrozumcie mnie źle: myślę, że potrzebujemy puli autowydzielania w Swift rzadziej niż w Objective-C, ale nadal ma do odegrania rolę.pathForResource:ofType:
wielokrotnie dzwonić do NSBundle .pathForResource:ofType:
przykład nie działa już w Xcode 6.3 / Swift 1.2. :)Jeśli użyjesz go w równoważnym kodzie Objective-C, użyjesz go w języku Swift.
Tylko jeśli robi to Objective-C. Oba działają zgodnie z regułami zarządzania pamięcią Cocoa.
Oczywiście ARC wie, że
number
pod koniec tej iteracji pętli wychodzi poza zakres i jeśli ją zachowa, zwolni ją tam. Nie informuje to jednak o tym, czy obiekt został wydany automatycznie, ponieważ-[NSNumber numberWithInt:]
mógł, ale nie musi, zwrócić instancję wydaną automatycznie. Nie możesz tego wiedzieć, ponieważ nie masz dostępu do źródła-[NSNumber numberWithInt:]
.źródło
autoreleasepool
konstrukcja jest całkowicie niepotrzebna. Ale jeśli twój kod Swift obsługuje obiekty Objective-C (w tym obiekty Cocoa), te wykonują wzorce autorelease, a zatemautoreleasepool
konstrukcja staje się użyteczna.