Обновление UIImageView после applicationWillEnterForeground

uiimageview
swift3

#14

Вы утверждаете, что такие ситуации отсутствуют в принципе, когда в замыкании возникает сильная ссылка? Поэтому писать [unowned self] не нужно никогда? Я утверждаю, что такие ситуации бывают, поэтому писать эти два слова нужно всегда на всякий случай (запомните - программирование это бесконечный рефакторинг), потому что находить ошибки утечек памяти очень трудно. Но учить вас не собираюсь, оставайтесь в своем неведении дальше.


#15

Где это я такое утверждаю?

В отличии от вас я знаю когда возникают такие ситуации и где нужно писать weak/unowned.

Это говорит о вашей некомпетентности, вчера свифт учить начали? Так подучите ещё, а потом уж спорьте :slight_smile:


#16

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

Поэтому у вас все в вакууме: ну возникнет такая ситуация, напишу [unowned self], какие проблемы? А пока писать не буду. Я же ведь великий и всегда начеку. И коллега пускай повнимательнее будет, глаза же ему на что-то даны. Не увидит, сам виноват будет. Вот так вы рассуждаете.

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

Это еще хорошо, что свифт язык безопасный. Мне страшно подумать, что бы вы с таким подходом наворотили на С/С++.


#17

Ну конечно, куда мне до вас и вашей команды, которая язык выучить не может и везде лепит unowned “на всякий случай” :slight_smile: Смех да и только.


#18

Ну так и быть, проведу ликбез. Специально для вас почти в три ночи родил пример. Вот у вас есть класс:

class Obj {
    private var _prop = "secret"
    
    lazy var getProp: () -> String = {
        var value = "some "
        return value
    }
}

Вот так вы его используете:

override func viewDidLoad() {
    super.viewDidLoad()
    let obj: Obj? = Obj()
    if let myValue = obj?.getProp {
        let result = myValue()
        print (result)
    }
}
```
И все у вас хорошо. Но через какое-то время, через недельку, исправляя другие баги или выполняя новые пожелания заказчика, вы вносите исправление:
```
class Obj {
    private var _prop = "secret"
    
    lazy var getProp: () -> String = {
        var value = "some "
        value += "\(self._prop) 123" // вот тут
        return value
    }
}
```
Вы можете поклясться себе, работодателю, заказчику и коллегам, что не забудете при этом написать [unowned self]? Если вы скажете "да", то программирование вам противопоказано.

В реальной жизни встречаются намного более запутанные случаи. Которые к тому же могут быть написаны не вами на 100%.

Поэтому мой вам совет (хотя давать вам какие-то советы бессмысленно, у вас случай клинический), всегда пишите [unowned self] сразу. Хотя бы для коллег. Потому что за ваши фокусы рано или поздно вас начнут бить, как Шуру Балаганова. Засранный вами код никому не понравится прибирать вечно.

Я себе представляю такую картину: тим-лидер забегает весь красный от тестировщиков и орет: "Опять где-то течет!!! Какой мудак опять напортачил?!!!" И все программеры сразу головы в вашу сторону поворачивают)))

#19

Утечки памяти - это самые противные ошибки. Как правило, их поиск сводится к тому, чтобы закомментировать разные участки кода и локализовать место утечки. Есть специальные инструменты, но и они далеко не всегда помогают быстро локализовать ошибку. Все равно придется помучиться.

Кстати, и тут создатели свифта нам помогли. У свифта есть чудесная особенность - можно делать вложенные комментарии, такие как

/*code 
/* code */ 
code*/

Это очень сильно помогает в поиске ошибок. Даже не приходит в голову никакой другой популярный язык, где разрешались бы вложенные комментарии. Может, кто подскажет?

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

У свифт-программиста, слава Богу, мало тонких мест, когда могут возникать утечки памяти. Навскидку:

  1. когда объекты ссылаются друг на друга циклически.
  2. когда замыкание захватывает ссылку на объект.
  3. когда сделали что-то вроде group.enter(), а group.leave() забыли.

Может, еще что-то, но не вспоминается из практики.

Эппл пытается нам помочь в каждом непростом случае. Например, вместо классов рекомендует использовать структуры, которые передаются by value, поэтому циклических ссылок возникнуть в структурах не может. В замыканиях требуется всегда писать явно self.myVar, это тоже не случайно.

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

Поэтому, уважаемые форумчане, не слушайте всяких проходимцев, и крайне осторожно подходите к коду, который может вызвать утечку. Используйте структуры вместо классов, если это возможно. Избегайте замыканий (если это не функции), а если используете, пишите всегда [unowned self]. Всегда проверяйте на парность group.enter()/group.leave().

И как можно чаще нажимайте в Xcode кнопочку “Debug memory graph”. Кнопочка эта очень маленькая, но крайне полезная. Чем раньше вы найдете утечку, тем лучше.

Желаю всем поменьше ошибок в коде. И не болейте, берегите себя.


#20

Перекреститесь, вдруг рефакторить станете меньше… Ну а так модульный подход/ нисходящее программирование… Ну и если TDD вдруг используете, Где бесконечный рефакторинг?

Порадовало вот это:

Кто у вас отвечал за кодревью, бухал видимо без остановки!


#21

Тогда задаю вам тот же вопрос. В примере, который я привел выше, вы гарантируете, что после изменений в коде поставите [unowned self]? Если отвечаете да, то программирование это не ваше.

А что бы вы сказали про код-ревью в Яндексе, когда бы прочитали эту статью?

Человек не смог пройти код-ревью, потому что не поставил пробел после function. Так что в больших компаниях сидят еще те параноики. И наверное, они знают, что делают.


#22

Не важно, что я отвечу. Мое, не мое, не вам решать. Вас ткнули носом в то, что не стоит везде лепить [unowned self]. Вы какой то пример “родили”, по Вашим словам. Но если Вы его рожали, то следовало аборт сделать и не мучаться.

И да, был тут у нас один сеньор недавно, который столько сеньоров сотворил. Но кроме срача он него не было пользы, помощи тоже.

Для вас ориентир большие команды? Тогда именно я Вам сочувствую. В Яндекс нет единого стиля, каждая команда работает как ей нравится. В том же Рамблер есть определенный стиль и требования. Кто прав? Да фиг знает, но в Рамблер легче заменить разработчика на проекте или добавить еще кого в проект.


#23

Никто меня ни во что не тыкал. Не надо мне говорить, что в большинстве случаев [unowned self] излишен, не мните о себе слишком много, что вы один понимаете, когда его нужно ставить, а когда нет. Я говорю лишь о том, что код постоянно меняется в процессе. И лучше заранее поставить [unowned self], даже если это претит вашим эстетическим чувствам. Потому отслеживать потом это будет очень тяжело, когда сроки горят, а мерджи идут за мерджами.

Замыкание - это одно из немногих тонких мест свифта, поэтому когда работаете с ними, надо повышать бдительность. Написать два “лишних” слова нетрудно. Зато трудно потом найти утечку. Видимо, вы никогда не искали (особенно такие, которые возникают периодически по неизвестной причине), поэтому относитесь к этому так халатно. Что говорит об отсутствии у вас опыта. Свифт это ваш первый язык программирования? Если да, тогда все понятно.


#24

Хорошо, видно просто так это не закончится. Любите примеры? До этого была задана дефолтная конфигурация Реалм для работы с сервером:

func setup() {
    SyncUser.logIn(with: credencial, server: authServerURL) { user, error in
      if let user = user {
        Realm.Configuration.defaultConfiguration = Realm.Configuration( syncConfiguration: SyncConfiguration(user: user, realmURL: realmURL) )
      }
    }
  }

Как известно, реалм имеет свою ивент-систему, умеющую динамично менять способ работы в данными, обновляемыми в реальном времени. Сервер/локальное хранилище.

func connect(block: @escaping (_ realm: Realm)->()) {
    let realm = try! Realm()
    block(realm)
  }

Также есть метод, который облегчает работу с множеством сущностей и позволяет не писать слишком громоздкий код при выборке:

static func objects<T: Object>(type: T.Type) -> Results<T>? {
    let realm = try? Realm()
    return realm?.objects(type)
  }

Исходя из перечисленного, стало возможно помимо выборки данных, работать с Реалм таким способом и не париться как Реалм синхронизирует данные:

@objc func update(updateBlock: @escaping () -> ()) {
    RealmManager.manager.connect { realm in
      try! realm.write(updateBlock)
    }
  }

То есть, в данном контексте обновление объекта происходит так:

let realmEntity = ......
realmEntity.update {
  realmEntity.propertyName = ....
}

Если на ревью я увижу здесь Ваш [unowned self], то вы язык учить все же пойдете! И не важно какой у меня по счету язык. Еще раз блеснете пафосом вроде:

Или:

Я лично спущу Вас с небес на землю. А то вы под ногами уже и земли не чувствуете!


#25

В Свифте ARC и утечки бывают только в результате цикла сильных ссылок (unsafe не берём в расчёт), если в результате захвата замыканием не возникает цикла сильных ссылок, то пусть оно хоть обзахватываеться ARC уничтожен все объекты.

Так никто не пишет, lazy здесь не нужен:

lazy var getProp: () -> String = {
}

Это тоже самое что это:

var getProp: () -> String = {
}

А тут всё просто, getProp сильная ссылка и self в замыкании будет сильной ссылкой.

Lazy var кстати пишется так:

lazy var getProp: String = {
}()

Очевидно что свифт вы знаете плохо, судя по тому что вы писали здесь iOS SDK тоже посредственно, если взглянуть на ваш код здесь думаю что про кодстайл вы и не слышали.

И что это за возможно и на всякий случай? Это новая методология программирования? В программирование всё чётко определено и нет никакого возможно и может быть. Если вы не знаете что такое цикл сильных ссылок, для вас это сплошная магия и вы не понимаете откуда берутся утечки памяти, так просто признайте это, в этом нет ничего постыдного.


#26

Можно также Ваш совет, по проблеме в коде? Если есть мысли. Спс


#27

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

Я задал простой вопрос: вы гарантируете, что после внесения изменений в код не забудете поставить unowned self?


#28

Я предложу его рефакторить, именно так поступают с быдлокодом.

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


#29

Мда. Рефакторить? А кто за это будет платить?))) Заказчик? Он подумает, что вы прикалываетесь. Работодатель? А если это не один класс, а целая гроздь классов в десятки тысяч строк кода? Тоже предложите отрефакторить? За свой счет, дома, когда напишете заявление об увольнении.

Насчет гарантий - вот этого и следовало ожидать)))


#30

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


#31

Юноша, вы с фриланса? В компаниях как раз и рефакторят, так как часто это приложение остается компании на поддержку и развитие. Я скажу еще одно ужасное слово… Они еще и тестами код покрывают, чтобы не возникало таких глупых ситуаций. Тесты отлично документируют код для будущих разработчиков. Если тесты писать как TDD, то можно вообще не париться, что приложение развалится из-за случайного быдлокодера


#32

Из javascript он и видимо не подозревает что ARC появился ещё в Objc и люди уже собаку съели на утечках и цикла сильных ссылок.


#33

Тогда понятно. Там вроде еще и с наследованием пляска. Вроде как наследник при изменении своих свойств, меняет свойства родителя и это может затронуть всех других наследников родительского класса