簡體   English   中英

封閉中的自我弱和后果的例子

[英]Weak self in closures and consequences example

我已經完成了有關stackoverflow和Apple有關ARC和Weak / Unowned self的文檔的研究( 我們總是在Swift中使用[unowned self]內部封閉 )。 我得到了關於強引用周期的基本概念以及它們如何導致內存泄漏的不好之處。 但是,我試圖在封閉時使用Weak / Unowned self。 而不是進入“理論”,我認為如果有人可以用我最底層的三個案例來解釋它們,那真的會有所幫助。 我的問題是

  1. 把弱者放在所有人身上是否可以(我認為第二種情況是沒有必要的,因為我看到UIView與自我無關的某個地方?但是,如果我把弱自我放在那里,有什么可以導致的嗎?我頭痛?

  2. 如果答案是否定的話,你不能在所有三種情況下把弱自我放在任何地方,如果我這樣做會發生什么(示例響應會很受歡迎...例如,程序會在這個VC時崩潰....

  3. 這就是我計划在封閉之外使用weakSelf的方法,我把弱變量weakSelf = self然后用weakSelf替換所有自我的封閉? 可以嗎?

     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--我的大多數代碼看起來都是案例3,其中所有內容都包含在一個閉包中,該閉包在任何操作發生之前檢查是否存在互聯網連接。 所以我到處都可能有自己的弱點?

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

關於案例4的問題我是否正確地說,即使這個閉包沒有弱/無主自我,它也永遠不會創建強引用(和內存泄漏),因為即使VC在執行完成塊之前被解除,Xcode也會當我們確認互聯網狀態時,嘗試在完成塊內運行代碼,並且什么都不做(沒有崩潰),因為self不再存在。 一旦代碼到達閉包內的最后一行,對self的強引用就會被破壞,從而解除VC的負擔?

因此,在這種情況下放置[弱自我]只意味着xcode會忽略這些行(反對嘗試運行它並且沒有任何反應)這意味着更好的練習但是我的手上沒有任何問題

問題不應該是“我可以使用弱引用”,而是“我應該使用弱引用”。 您可以使用弱引用來避免強引用循環,或者在封閉處理之后保持封閉不會掛起。 但是,不要只是添加弱引用,因為你可以。

  1. 在案例1中,您可能確實想要使用[weak self] 為什么? 因為如果視圖控制器在授權過程中被解雇,你真的想保留對被解雇的視圖控制器的引用嗎? 可能不是在這種情況下。

  2. 在案例2中,理論上你可以在animation塊中使用[weak self] ,但為什么會這樣? 沒有理由。 弱引用是你用完成處理程序和/或閉包變量做的事情,但對於動畫塊它沒有提供實用程序,所以我不會那樣做。 在這里使用weak表示對所涉及的內存語義的誤解。

  3. 在案例3中,您有兩個不同的問題。

    • didSelectItemAtIndexHandler ,可能應該使用[unowned self]因為對象自己的閉包是指自己。

      這可能是一個沒有實際意義的問題,因為我沒有看到你實際使用那個BTNavigationDropdownMenu (也許初始化器正在將自己添加到導航控制器,但如果是這樣,那不是一個設計良好的初始化器,恕我直言)。

      但作為一般概念,當一個對象有一個只能在對象仍然存在時調用的處理程序閉包,但本身不應該調用該對象時,會使用[unowned self]

    • 在更廣泛的checkUserLoggedIn閉包中,問題是這是否是一個完成處理程序。 如果是這樣,你可能應該使用[weak self] ,因為這可以在self被解除時啟動並運行,並且你不希望checkUserLoggedIn保持對被解除的視圖控制器的引用。 但是你不想使用[unowned self]因為如果它在關閉運行時被釋放,那將會讓你留下懸空指針。

      另外,你考慮:

       weak var weakSelf = self 

      這有點不合時宜。 您將在checkUserLoggedIn閉包的開頭使用[weak self]模式。 如果你有一個例子,你很想使用weak var weakSelf = ... ,你應該編輯你的問題,包括你想要使用那個模式的例子。 但這不是其中之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM