когда я должен использовать «я», «незанятое я» и «слабое я» в быстром? [Дубликат]

Поверните строку в список; то вы можете изменить символы в отдельности. Затем вы можете вернуть его вместе с .join:

s = 'a;b;c;d'
slist = list(s)
for i, c in enumerate(slist):
    if slist[i] == ';' and 0 <= i <= 3: # only replaces semicolons in the first part of the text
        slist[i] = ':'
s = ''.join(slist)
print s # prints a:b:c;d
361
задан Ryan Heitner 16 May 2017 в 11:30
поделиться

7 ответов

Нет, есть определенные моменты, когда вы не хотели бы использовать [unowned self]. Иногда вы хотите, чтобы замыкание захватывало себя, чтобы убедиться, что оно все еще вокруг к тому времени, когда вызывается замыкание.

Пример: Выполнение асинхронного запроса сети

Если вы делая запрос асинхронной сети, вы хотите, чтобы закрытие сохраняло self, когда запрос заканчивается. Этот объект может быть иначе освобожден, но вы все еще хотите иметь возможность обрабатывать завершение запроса.

Когда использовать unowned self или weak self

Единственный раз, когда вы действительно хотите использовать [unowned self] или [weak self], когда вы создадите сильный ссылочный цикл . Сильный ссылочный цикл - это когда существует право собственности на объекты, в которых объекты становятся друг с другом (может быть, через третью сторону), и поэтому они никогда не будут освобождены, потому что они оба гарантируют, что друг друга будут придерживаться.

В конкретном случае закрытия вам просто нужно понять, что любая переменная, на которую ссылаются внутри нее, получает «собственность» по закрытию. Пока закрытие вокруг, эти объекты гарантированно будут вокруг. Единственный способ остановить это право собственности - сделать [unowned self] или [weak self]. Поэтому, если класс владеет закрытием, и это закрытие фиксирует сильную ссылку на этот класс, тогда у вас есть сильный ссылочный цикл между закрытием и классом. Это также включает в себя, если классу принадлежит то, что принадлежит закрытию.

В частности, в примере из видео

В примере на слайде TempNotifier владеет закрытием через onChange. Если они не объявили self как unowned, замыкание также будет иметь self, создавая сильный опорный цикл.

Разница между unowned и weak

Разница между unowned и weak заключается в том, что weak объявляется как необязательный, а unowned - нет. Объявив это weak, вы получите дело с тем, что в какой-то момент он может остаться в закрытии. Если вы попытаетесь получить доступ к переменной unowned, которая будет равна нулю, это приведет к сбою всей программы. Поэтому используйте unowned, когда вы уверены, что переменная всегда будет вокруг, а закрытие вокруг

685
ответ дан drewag 18 August 2018 в 04:25
поделиться
  • 1
    Здравствуй. Отличный ответ. Я изо всех сил пытаюсь понять себя. Причиной использовать weakSelf просто «я» становится необязательным », для меня недостаточно. Почему я специально хочу использовать «unowned self» stackoverflow.com/questions/32936264/… – user 5 October 2015 в 13:41
  • 2
    @robdashnash. Преимущество использования незанятого «я» заключается в том, что вам не нужно разворачивать дополнительный, который может быть ненужным кодом, если вы точно знаете по дизайну, что он никогда не будет никчемным. В конечном счете, незанятое «я» используется для краткости и, возможно, также как намек будущим разработчикам, что вы никогда не ожидаете нулевого значения. – drewag 5 October 2015 в 23:48
  • 3
    Случай использования [weak self] в асинхронном сетевом запросе находится в контроллере представления , где этот запрос используется для заполнения представления. Если пользователь отступает, нам больше не нужно заполнять представление, и нам не нужна ссылка на контроллер вида. – David James 30 March 2016 в 14:41
  • 4
    weak ссылки также устанавливаются на nil, когда объект освобождается. unowned ссылок нет. – BergQuester 2 November 2017 в 17:16
  • 5
    Я немного смущен. unowned используется для non-Optional, а для Optional используется weak, поэтому наш self равен Optional или non-optional? – Muhammad Nayab 16 January 2018 в 14:25

Вот блестящие цитаты из Форумы разработчиков Apple описали вкусные детали:

unowned vs unowned(safe) vs unowned(unsafe)

unowned(safe) - это ссылка, не относящаяся к владельцам, которая утверждает, что объект все еще жив. Это похоже на слабую необязательную ссылку, которая неявно распаковывается с x! каждый раз, когда к ней обращаются. unowned(unsafe) походит на __unsafe_unretained в ARC - это не-владеющая ссылка, но нет проверки времени выполнения, что объект все еще жив при доступе, поэтому оборванные ссылки попадут в мусорную память. unowned всегда является синонимом для unowned(safe) в настоящее время, но предполагается, что он будет оптимизирован для unowned(unsafe) в сборках -Ofast, когда проверки времени выполнения отключены.

unowned vs weak

unowned фактически использует гораздо более простую реализацию, чем weak. Объекты Native Swift несут два подсчета ссылок, а ссылки unowned нажимают недостоверный счетчик ссылок вместо значения strong . Объект деинициализируется, когда его число strong достигает нуля, но оно фактически не освобождается до тех пор, пока счетчик ссылок unowned также не достигнет нуля. Это приводит к тому, что память удерживается немного дольше, когда есть неопубликованные ссылки, но обычно это не проблема, когда используется unowned, потому что связанные объекты должны иметь почти равные сроки жизни в любом случае, и это намного проще и ниже накладных расходов чем реализация на стороне стола, используемая для обнуления слабых ссылок.

Обновление: в современном Swift weak внутренне используется тот же механизм, что и unowned. . Таким образом, это сравнение неверно, поскольку оно сравнивает Objective-C weak с Swift unonwed.

Причины

Какова цель сохранения памяти в памяти после владения ссылками достигают 0? Что произойдет, если код попытается что-то сделать с объектом, используя неопубликованную ссылку после того, как он деинициализирован?

Память сохраняется в памяти, так что ее значения сохранения остаются доступными. Таким образом, когда кто-то пытается сохранить сильную ссылку на незарегистрированный объект, среда выполнения может проверить, что сильный счетчик ссылок больше нуля, чтобы гарантировать сохранность объекта.

Что происходит с владением или отсутствием ссылки на объект? Является ли их время жизни отделенным от объекта, когда он деинициализирован или их память также сохраняется до тех пор, пока объект не будет освобожден после того, как будет освобождена последняя незанятая ссылка?

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

Возбуждено, да?

42
ответ дан Community 18 August 2018 в 04:25
поделиться

Если self может быть nil в использовании замыкания [слабый self].

Если self никогда не будет nil в закрытии использовать [unowned self].

Документация Apple Swift имеет большой раздел с изображениями, объясняющими разницу между использованием сильных, слабых и незанятых в замыканиях:

https://developer.apple.com/library/content/documentation/Swift/Conceptual/ Swift_Programming_Language / AutomaticReferenceCounting.html

56
ответ дан Cœur 18 August 2018 в 04:25
поделиться

Согласно Apple-doc

  • Слабые ссылки всегда имеют необязательный тип и автоматически становятся нулями, когда экземпляр, который они ссылаются, освобождается.
  • Если захваченное задание никогда не станет нулевым, оно всегда должно быть записано как неосновная ссылка, а не слабая ссылка

Пример -

    // if my response can nil use  [weak self]
      resource.request().onComplete { [weak self] response in
      guard let strongSelf = self else {
        return
      }
      let model = strongSelf.updateModel(response)
      strongSelf.updateUI(model)
     }

    // Only use [unowned self] unowned if guarantees that response never nil  
      resource.request().onComplete { [unowned self] response in
      let model = self.updateModel(response)
      self.updateUI(model)
     }
2
ответ дан Jack 18 August 2018 в 04:25
поделиться

Я думал, что добавлю некоторые конкретные примеры специально для контроллера вида. Многие объяснения, а не только здесь, о переполнении стека, действительно хороши, но я лучше работаю с примерами реального мира (на самом деле у @drewag было хорошее начало):

  • Если у вас есть закрытие для обработки ответа от сетевых запросов используйте weak, поскольку они долговечны. Контроллер вида может закрыться до завершения запроса, поэтому self больше не указывает на действительный объект при вызове закрытия.
  • Если у вас есть закрытие, которое обрабатывает событие на кнопке. Это может быть unowned, поскольку, как только контроллер просмотра уйдет, кнопка и любые другие элементы, которые она может ссылаться на self, уходят одновременно. Блок блокировки также уйдет в одно и то же время.
    class MyViewController: UIViewController {
          @IBOutlet weak var myButton: UIButton!
          let networkManager = NetworkManager()
          let buttonPressClosure: () -> Void // closure must be held in this class. 
    
          override func viewDidLoad() {
              // use unowned here
              buttonPressClosure = { [unowned self] in
                  self.changeDisplayViewMode() // won't happen after vc closes. 
              }
              // use weak here
              networkManager.fetch(query: query) { [weak self] (results, error) in
                  self?.updateUI() // could be called any time after vc closes
              }
          }
          @IBAction func buttonPress(self: Any) {
             buttonPressClosure()
          }
    
          // rest of class below.
     }
    
31
ответ дан possen 18 August 2018 в 04:25
поделиться
  • 1
    Этого нужно больше. Два твердых примера, показывающих, как закрытие кнопки не будет существовать за пределами срока действия контроллера представления, и поэтому могут использовать незаслуженные, но большинство сетевых вызовов, которые требуют обновления интерфейса, должны быть слабыми. – Tim Fuqua 15 November 2017 в 03:51
  • 2
    Итак, просто для того, чтобы уточнить, всегда ли мы используем unowned или слабый при вызове self в блоке закрытия? Или есть время, когда мы не будем называть слабым / неумелым? Если да, можете ли вы привести пример для этого? – luke 13 December 2017 в 10:48
  • 3
    Огромное спасибо. – Shawn Baek 29 April 2018 в 10:03
  • 4
    Это дало мне более глубокое понимание о [слабом я] и [незадействованном я] Спасибо большое @possen! – Tommy 4 July 2018 в 00:47

Здесь есть несколько отличных ответов. Но недавние изменения в том, как Swift реализуют слабые ссылки, должны изменить все слабое самосогласование или несостоявшиеся решения для самопомощи. Раньше, если бы вам нужна была лучшая производительность с использованием незадействованного «я», это было бы лучше слабого «я», если бы вы могли быть уверены, что «я» никогда не будет никчемным, потому что доступ к незаслуженному «я» намного быстрее, чем доступ к слабому «я».

Но Майк Эш задокументировал, как Swift обновил реализацию слабых варов для использования боковых столов и как это существенно улучшает слабую самоэффективность.

https://mikeash.com/pyblog/friday- qa-2017-09-22-swift-4-weak-references.html

Теперь, когда нет значительного снижения производительности для слабого пользователя, я считаю, что мы должны по умолчанию использовать его идти вперед. Преимущество слабого «я» заключается в том, что он является дополнительным, что значительно упрощает создание более правильного кода, в основном это причина, по которой Свифт - такой замечательный язык. Вы можете подумать, что знаете, какие ситуации безопасны для использования незадействованного «я», но мой опыт, рассматривающий множество других кодексов разработчиков, больше всего этого не делает. Я зафиксировал много сбоев, когда незанятое я было освобождено, обычно в ситуациях, когда фоновый поток завершается после того, как контроллер освобожден.

Ошибки и сбои - это наиболее трудоемкие, болезненные и дорогие части программирования. Сделайте все возможное, чтобы написать правильный код и избежать их. Я рекомендую сделать это правилом, чтобы никогда не приводить в действие разворот оппонентов и никогда не использовать незадействованное я, а не слабое я. Вы не потеряете ничего, потеряв время, когда разворачивается сила, и незанятое я действительно безопасно. Но вы получите много от устранения трудно найти и отладить сбои и ошибки.

17
ответ дан Randy Hill 18 August 2018 в 04:25
поделиться
  • 1
    Благодарим вас за обновление и Amen в последнем абзаце. – motto 23 March 2018 в 21:26

Обновление 11/2016

Я написал статью об этом расширении этого ответа (глядя на SIL, чтобы понять, что делает ARC), проверьте здесь .

Оригинальный ответ

Предыдущие ответы не дают прямых правил о том, когда использовать друг друга и почему, поэтому позвольте мне добавить несколько вещей.

Непринятые или слабое обсуждение сводится к вопросу о времени жизни переменной и замыкания, которое ссылается на нее.

Сценарии

У вас может быть два возможных сценария:

  1. Закрытие имеет одинаковое время жизни переменной, поэтому замыкание будет доступно только до тех пор, пока переменная не будет достижима . Переменная и замыкание имеют одинаковое время жизни. В этом случае вы должны объявить ссылку как незаслуженную. Общим примером является [unowned self], используемый во многих примерах небольших замыканий, которые делают что-то в контексте их родителя и что нигде не упоминаются нигде, не переживают своих родителей.
  2. Время жизни закрытия не зависит от одна из переменных, на закрытие все еще можно ссылаться, когда переменная недоступна. В этом случае вы должны объявить ссылку слабым и проверить, что это не ноль, прежде чем использовать его (не принудительно разворачивать). Общим примером этого является [weak delegate], который вы можете увидеть в некоторых примерах замыкания, ссылаясь на полностью не связанный (пожизненный) объект делегирования.

Фактическое использование

Котировка Джо Гроффа из твиттера :

Unowned быстрее и позволяет неизменность и неоптимальность.

Если вам не нужен слабый, не используйте его.

Вы найдете больше о неработающих внутренних функциях * здесь .

* Обычно также упоминается как незаслуженный (безопасный), указывающий, что проверки выполнения (которые приводят к сбою за недопустимые ссылки) выполняются перед доступом к незаслуженному ссылка.

136
ответ дан Umberto Raimondi 18 August 2018 в 04:25
поделиться
  • 1
    Я устал слышать объяснение попугая и использовать неделю, если я мог бы быть нулевым, использовать незаслуженно, когда он никогда не может быть ник ». Хорошо, мы поняли, что это миллион раз! Этот ответ на самом деле копает глубже, когда я может быть nil на простом английском, что напрямую отвечает на вопрос OP. Спасибо за это замечательное объяснение !! – TruMan1 12 May 2016 в 12:28
  • 2
    Спасибо @ TruMan1, я на самом деле пишу сообщение об этом, которое скоро появится в моем блоге, обновит ответ ссылкой. – Umberto Raimondi 23 May 2016 в 06:58
  • 3
    Хороший ответ, очень практичный. Я вдохновлен на то, чтобы переключить некоторые из моих уязвимых слабых варов, которые сейчас не работают. – Charlesism 14 July 2016 в 09:45
  • 4
    «Время жизни замыкания не зависит от одного из переменных» У вас есть опечатка? – Honey 7 August 2016 в 20:35
  • 5
    Отбросив в сторону нет, я имел в виду, что слабо захваченная переменная не может быть доступна (она была выпущена), когда закрытие все еще доступно, и кто-то ее вызывает. – Umberto Raimondi 1 September 2016 в 10:57
Другие вопросы по тегам:

Похожие вопросы: