Weak self in an example of closure and consequences

I did a study on stackoverflow and apple documentation on ARC and Weak / Unowned ( Should we always use [unowned self] inside closure in Swift ). I get the basic idea of ​​a strong reference loop and, as it is not good, as they cause memory leaks. However, I try to get hold of my head when I need to use Weak / Unowned self in closure. Instead of going into “theory,” I think it would really help if someone could kindly explain them in terms of the bottom three cases that I have. My questions

  • Is it possible to put a weak self in all of them (I think that for the second case there is no need, because I saw somewhere that the UIView is not connected with itself?). However, what if I put the weak I am there, is there anything that can cause me a headache?

  • Tell me if there is a “No” answer, you cannot put a weak “I” in all three cases, what happens if I do this (for example, the answer would be very appreciated ... For example, the program will crash when this VC ....

  • This is how I plan to use weakSelf Outside of closure, I set the weak var weakSelf = self Then replace all the "I" in the closure with "weak"? Is this ok to do?

    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-- Most of my code looks like case 3, where everything closes in a closure that either checks if there is an Internet connection before any action is performed. So, could I have a weak body all over the world?

- 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") } } 

Question about case 4. Am I saying correctly that even if this closure does not have a weak / unoccupied self, it will never create a strong link (and memory leak), because even if VC is fired before the completion block is completed, Xcode will try run the code inside the completion block when we have confirmed the status of the Internet and will not do anything (without failures), because it itself no longer exists. And as soon as the code reaches the last line inside the closure, the strong reference to the ego will be destroyed, which means it will free VC?

So the old [weak self] in this case would simply mean that xcode would ignore these lines (how to resist trying to start it and nothing would happen), which would mean best practice, but no problem on my arm anyway

+7
closures automatic-ref-counting swift
source share
2 answers

The question should not be “can I use a weak link”, but rather “should I use a weak link”. You use weak references to avoid strong reference loops, or to keep the closure from happening after something is posted. But don't just add weak links because you can.

  • In case 1, you probably want to use [weak self] . What for? Because if the view manager was fired during authorization, do you really want to keep the link to the view controller that was fired? Probably not in this case.

  • In case 2, you could theoretically use [weak self] in the animation block, but why would you? There is no reason. A weak link is what you do with completion handlers and / or closing variables, but it does not offer any utility for the animation block, so I would not do that. Using weak here implies a misunderstanding of memory semantics.

  • In case 3, you have two separate problems.

    • In didSelectItemAtIndexHandler , you should probably use [unowned self] because the object's own closure refers to itself.

      This can be a controversial issue, because I don’t see that you really use this BTNavigationDropdownMenu (perhaps this initializer adds itself to the navigation controller, but it is not a well-designed initializer, if yes, IMHO).

      But as a general concept, when an object has a handler closure that can only be called when the object is still around, but should not by itself, cause the object to be saved, you should use [unowned self] .

    • The wider closure of checkUserLoggedIn raises the question of whether this checkUserLoggedIn handler is. If so, you should probably use [weak self] , because it can be triggered and started by the time self expires, and you do not want checkUserLoggedIn keep a reference to the view controller that was fired. But you would not want to use [unowned self] because it would leave you with dangling pointers if it were released at the time of closing.

      Aside, you contemplate:

       weak var weakSelf = self 

      This is a little unattractive. You should use the [weak self] pattern at the start of the checkUserLoggedIn closure. If you have an example when you are trying to use weak var weakSelf = ... , you should edit your question, including an example of where you want to use this template. But this is not one of these cases.

+13
source share

Weak links

A weak link is a link that does not hold strong binding to the instance to which it refers, and therefore does not stop ARC from disposing of the reference instance. This behavior prevents the link from becoming part of a strong reference loop. You specify a weak link by placing the weak keyword before the declaration of a property or variable.

For clarity of the weak read the document here .

-one
source share

All Articles