Zrobiłem trochę badań nad stackoverflow i dokumentacji Apple o ARC i Weak/Unowned siebie (Shall we always use [unowned self] inside closure in Swift). Mam podstawowe pojęcie o silnym cyklu odniesienia i o tym, że nie jest ono dobre, ponieważ powoduje wycieki pamięci. Jednak staram się zrozumieć, kiedy używać słabego/niezasilanego siebie w zamknięciach. Zamiast wchodzenia w "teorię", myślę, że naprawdę pomogłoby, gdyby ktoś mógł wyjaśnić je w kategoriach trzech ostatnich spraw, które mam. Moje pytania toSłabe samo w zamknięciach i przykładach konsekwencji
Czy można umieścić słaby siebie w każdym z nich (myślę, że dla przypadku dwóch nie ma potrzeby, bo widziałem gdzieś, że UIView nie jest związany z siebie ?. Jednak to, co jeśli kładę słabe ja, czy jest coś, co może wywołać ból głowy?
Powiedz, jeśli odpowiedź brzmi "Nie", nie możesz umieścić słabego ja w każdym z trzech przypadków, co by się stało, gdybym to zrobiła (przykładowa reakcja byłaby bardzo doceniana. ..Na przykład, program ulegnie awarii, gdy ten VC ...
Oto, w jaki sposób mam zamiar użyć weakSelf Poza zamknięciem, kładę słabe var weakSelf = self Następnie wymienić wszystkie self w zamknięciu z weakSelf? Czy to jest w porządku?
Case 1: FIRAuth.auth()?.signInWithCredential(credential, completion: { (user: FIRUser?, error: NSError?) in self.activityIndicatorEnd() self.performSegueWithIdentifier(SEGUE_DISCOVER_VC, sender: self) }) Case 2: UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.1, animations: { self.messageLbl.alpha = 0.5 }) Case 3: //checkUserLoggedIn sends a request to firebase and waits for a response to see if the user is still authorised checkUserLoggedIn { (success) in if success == false { // We should go back to login VC automatically } else { self.discoverTableView.delegate = self self.discoverTableView.dataSource = self // Create dropdown menu let menuView = BTNavigationDropdownMenu(navigationController: self.navigationController, title: self.dropDownItems.first!, items: self.dropDownItems) menuView.didSelectItemAtIndexHandler = {[weak self] (indexPath: Int) ->() in if indexPath == 0 { self?.mode = .Closest self?.sortByDistance() } else if indexPath == 1 { self?.mode = .Popular self?.sortByPopularity() } else if indexPath == 2 { self?.mode = .MyPosts self?.loadMyPosts() } else { print("Shouldnt get here saoihasiof") } } // Xib let nib = UINib(nibName: "TableSectionHeader", bundle: nil) self.xibRef = nib.instantiateWithOwner(self, options: nil)[0] as? TableSectionHeader self.discoverTableView.registerNib(nib, forHeaderFooterViewReuseIdentifier: "TableSectionHeader") // Set location Manager data self.locationManager.delegate = self self.locationManager.desiredAccuracy = kCLLocationAccuracyBest // Check location service status if self.locationAuthStatus == CLAuthorizationStatus.AuthorizedWhenInUse { // Already authorised self.displayMessage.hidden = false } else if self.locationAuthStatus == CLAuthorizationStatus.NotDetermined { // Have not asked for location service before let storyboard = UIStoryboard(name: "Main", bundle: nil) let vc = storyboard.instantiateViewControllerWithIdentifier("LocationVC") as! LocationVC vc.locationVCDelegate = self self.presentViewController(vc, animated: true, completion: nil) } else { let alertController = UIAlertController(title: "Enable Location", message: "location is required to load nearby posts", preferredStyle: .Alert) let cancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: nil) let settingsAction = UIAlertAction(title: "Settings", style: .Default, handler: { (action: UIAlertAction) in let settingsUrl = NSURL(string: UIApplicationOpenSettingsURLString) if let url = settingsUrl { UIApplication.sharedApplication().openURL(url) } }) alertController.addAction(settingsAction) alertController.addAction(cancelAction) self.presentViewController(alertController, animated: true, completion: nil) self.displayMessage.hidden = false self.displayMessage.text = "Could not determine your location to find nearby posts. Please enable location Service from settings" } // Styling self.refreshBtn.tintColor = COLOR_NAVIGATION_BUTTONS self.discoverTableView.backgroundColor = COLOR_DISCOVERVC_TABLEVIEW_BACKGROUND // Allow navigation bar to hide when scrolling down self.hidingNavBarManager = HidingNavigationBarManager(viewController: self, scrollView: self.discoverTableView) // Allow location to start updating as soon as we have permission self.locationManager.startUpdatingLocation() } }
--Update-- Większość mojego kodu wygląda przypadek 3, w którym wszystko jest owinięty wewnątrz zamknięcia, które albo sprawdzić, czy nie ma połączenia z Internetem, zanim którykolwiek z działaniem jest dokonany. Więc mogę mieć słabe jaźń wszędzie?
--update 2--
Case 4:
// The haveInternetConnectivity function checks to see if we can reach google within 20 seconds and return true if we can
haveInternetConnectivity { (success) in
if success == false {
self.dismissViewControllerAnimated()
} else {
self.label.text = "You are logged in"
self.performSegueWithIdentifier("GoToNextVC")
}
}
Pytanie o wypadku 4. mam rację powiedzieć, że mimo to zamknięcie nie ma słabą/pozostawiony siebie, to nigdy tworzyć silne odniesienia (i pamięci wyciek), ponieważ nawet jeśli VC zostanie odwołany przed wykonaniem bloku zakończenia, Xcode spróbuje uruchomić kod wewnątrz bloku zakończenia, gdy potwierdzimy status Internetu i po prostu nie zrobimy nic (bez awarii), ponieważ self już nie istnieje. A kiedy kod dotrze do ostatniej linii wewnątrz zamknięcia, silne odniesienie do siebie zostanie zniszczone, a więc zwolnić VC?
więc oddanie [słabą Jaźni] w tym przypadku byłoby to po prostu oznacza, że Xcode ignoruje te linie (jak sprzeciwiać, aby spróbować go uruchomić i nic się nie dzieje), co oznaczałoby lepsze praktyki, ale żadnych problemów na ręku albo sposób
Proszę wyjaśnić, co rozumiecie przez "nie oferuje użyteczności". Czy można uczciwie powiedzieć, że każde zamknięcie, które obejmuje każdy rodzaj czekania z Internetu, zawsze musi być słabe lub niezarejestrowane? I czy to prawda, że prawie we wszystkich przypadkach byłaby to słaba jaźń? – user172902
Słabe referencje w zamknięciach 'animation' nie oferujących użyteczności: Zamknięcie' animation' dostarczone do 'animateWithDuration' nie jest programem obsługi zakończenia, który jest uruchamiany później (chociaż istnieje oddzielne zamknięcie' complete', ale jest to oddzielna kula wosku całkowicie). Nazywa się to natychmiast, a animacja jest inicjowana, ale zamknięcie nie zachowuje żadnych silnych odniesień do "ja" na czas trwania animacji. – Rob
Zamknięcia sieci re są zawsze słabe/niezarejestrowane: Nie, z pewnością tak nie jest.Na przykład, możesz zrobić coś w tym zamknięciu, które powinno być uruchomione (np. Zaktualizuj lokalną bazę danych dotyczącą zakończenia żądania sieciowego, zapisz pobrany obraz do pamięci podręcznej, itp.). Używaj tylko słabych _ jeśli nie potrzebujesz/chcesz, aby kod znajdował się w zamknięciu, aby zachować odniesienie do obiektu_ (np. Po prostu aktualizujesz interfejs użytkownika, ale nie aktualizujesz pamięci podręcznych lub baz danych lub struktur modelu). Nie używaj bezmyślnie słaby ": patrz na to, co jest w zamknięciu i zdecyduj, czy powinno być (lub musi być) słabe, czy nie. – Rob