Это потому, что ARC все еще соблюдает соглашения об именах управления памятью Какао.
В соответствии с этими соглашениями метод с именем +create
возвращает ссылку +0.Таким образом, при реализации метода ARC должен сбалансировать +1 ссылку пары alloc
/ init
путем автоматического освобождения ссылки.
Затем в main()
ARC должен принять этополучил +0 ссылку от звонка на +create
.Если бы ему понадобилась ссылка, чтобы выжить в текущей области, она бы сохранила ее, но это не так.Второй экземпляр GAObject
будет освобожден при истощении пула автоматического выпуска, но этого никогда не произойдет, потому что UIApplicationMain()
никогда не вернется.Если вы используете два отдельных пула автоматического выпуска, один для кода, связанного с GAObject
s, а другой для вызова UIApplicationMain()
, я ожидаю, что вы получите ожидаемый результат.
Если ARC действительно понадобилсяссылка на выживание, она будет сохранена при присвоении сильной переменной и будет освобождена, когда этой переменной будет присвоено новое значение (включая nil
) или она выйдет из области видимости.У ARC есть оптимизация во время выполнения, при которой авто-выпуск-возврат в вызываемом объекте и сохранение возвращенного значения в вызывающем объекте взаимно отменяют друг друга, так что объект никогда не помещается в пул авто-выпуска.Если бы это происходило, вы бы получили ожидаемые результаты.
На самом деле, я ожидаю, что компилятор первоначально будет генерировать, что сохраняет и освобождает даже в вашем случае, но последующий проход удаляет избыточные удержания и освобождения.В вашем примере выпуск сразу же следует за сохранением, что делает для компилятора еще более очевидным, что пара является избыточной.Поскольку сохранение удаляется, эта оптимизация автоматического выпуска не включается, и ссылка на ваш объект действительно помещается в пул автоматического выпуска.
Если ваш метод был назван +newGAObject
, тогда соглашения о присвоении именозначает, что он возвращает +1 ссылку, и это все меняется.(Конечно, в своем нынешнем виде ваш +create
метод делает то же самое, что и встроенный +new
метод, за исключением автоматического выпуска, который должен добавить ARC. Таким образом, вы можете просто изменить вызывающий код для использования+new
и это также обойдёт эту проблему.)
Я не знаю, почему строка с weakObject
имеет значение.Но, поскольку поведение, которое вы видите, зависит от определенных оптимизаций, все, что может изменить оптимизацию, может изменить результат.