2014-09-22 2 views
10

Я пытаюсь разрешить сильный опорный цикл закрытия в Swift.
В приведенном ниже коде объект хранится с помощью контроллера представления. ProgressHUD - это UIView, который также хранится у владельца. ProgressHUD просачивается каждый раз, когда вызывается обработчик завершения. При использовании новой функции захвата закрытия объявление self как слабое или неактивное не устраняет утечку памяти.Swift Closures - Захват себя как слабый

object.setCompletionHandler { [weak self] (error) -> Void in 
    if(!error){ 
     self?.tableView.reloadData() 
    } 
    self?.progressHUD?.hide(false) 
} 

Однако, если я объявляю слабое склонение для себя вне закрытия, он фиксирует утечку памяти, например:

weak var weakSelf = self 
object.setCompletionHandler { (error) -> Void in 
    if(!error){ 
     weakSelf?.tableView.reloadData() 
    } 
    weakSelf?.progressHUD?.hide(false) 
} 

Любые идеи, почему это не работает с Swift захвата ?

+0

не должно быть сохранить цикл – newacct

ответ

-3

Попробуйте следующее:

object.setCompletionHandler { [unowned self] (error) ->() in 
    if(!error){ 
     weakSelf?.tableView.reloadData() 
    } 
    weakSelf?.progressHUD?.hide(false) 
} 
+0

как уже отмечалось в первоначальном посте, ни слабая или бесхозный устраняет утечку памяти. Спасибо хоть. –

11

Если присвоить замыкание свойству экземпляра класса, и закрытие фиксирует этот экземпляр со ссылкой на экземпляр или его членов, вы будете создавать сильный опорный цикл между закрытием и экземпляром. Swift использует списки захвата, чтобы разбить эти сильные ссылочные циклы. source Apple

source sketchyTech Во-первых, важно, чтобы понять, что вся эта проблема касается только закрытия, где мы присваиваем «замыкание на свойство экземпляра класса». Помните об этом с каждым правилом. Правила:

  1. использовать слабый захват, если экземпляр класса или свойство является необязательным
  2. использование бесхозный, если экземпляр класса или свойство не обязательным и не может быть установлен в ноль
  3. «вы должны ... используйте ключевое слово in, даже если вы опускаете имена параметров, типы параметров и тип возврата «

В ответе на ваш вопрос не должно быть цикла удержания.

4

Вы заявили, что progressHUD удерживаются контроллером вида владеющего (сам) и вы ссылаетесь его в закрытии ... так что добавьте его в список захвата, а затем использовать захваченный переменный в замыкании следующим образом:

object.setCompletionHandler { [weak self] (error) -> Void in 
    if(!error){ 
     self?.tableView.reloadData() 
    } 
    self?.progressHUD.hide(false) 
} 
+0

Незанятые ссылки неявно разворачиваются, поэтому 'self? .tableView' следует изменить на' self.tableView'. –

+0

вы правы @zxzxlch, я отредактировал свое решение, изменив незанятое «я» на слабое «я» и отбросив progressHUD из списка захвата. Не должно быть никакого цикла удержания. – dferrero

-1

Это, как я делал это:

object.setCompletionHandler { [weak self] (error) -> Void in 
    if let weakSelf = self { 
     if (!error) { 
      weakSelf.tableView.reloadData() 
     } 

     weakSelf.progressHUD?.hide(false) 
    } 
} 
+3

Это точно в обратном направлении. Переименуйте 'weakSelf' в 'strongSelf'. «Пусть» дает вам хорошую ссылку. –