Сохранение ссылки на свойства в Objective- C - PullRequest
0 голосов
/ 07 марта 2020

У меня есть свойство объекта в моем классе. Я выделяю этот объект в функции. Как только функция завершена, выполнение свойства освобождается. Я не хочу, чтобы это произошло. Я хочу, чтобы объект оставался до тех пор, пока не будет активна ссылка на MyClass. Это с AR C.

Это код

@interface MyClass : NSObject
@property (nonatomic, strong) MyCustomClass *obj;
@end

@implementation MyClass

- (id)init {
// initialize 
_obj = nil;
}

- (void)func {
 _obj = [[MyCustomClass alloc] initWithParams...];
// do more things 
}

// the object deallocates once the function exits. 

1 Ответ

0 голосов
/ 08 марта 2020

В другом месте вашего кода происходит что-то еще, поскольку приведенный выше код не освобождает этот экземпляр MyCustomClass. Вот несколько возможных причин, по которым экземпляр, на который ссылается _obj, может быть освобожден:

  • _obj получает значение nil где-то еще;
  • _obj снова устанавливается (например, вы снова позвонили func), и старый экземпляр будет освобожден; или
  • MyClass, родительский объект сам по себе освобождается.

Я бы предложил две вещи для диагностики происходящего:

  1. Во-первых, я бы посоветовал добавить dealloc методы к MyClass и MyCustomClass, чтобы вы могли видеть, когда они освобождены:

    - (void)dealloc {
        NSLog(@"%s", __FUNCTION__);
    }
    
  2. Если Вы все еще не можете определить, что происходит, я бы предложил использовать инструменты для отслеживания каждой ссылки на рассматриваемый объект.

    Так, например, запустите профилировщик ( команда + i или «Продукт» («Профиль») и выберите инструмент «Утечки». Перед началом записи сеанса убедитесь, что для параметра «Параметры записи ...» для инструмента «Распределения» не установлено на «Отменить события для освобожденной памяти», но установлено в «Запись счетчиков ссылок»:

    enter image description here

    Теперь вы можете записывать свой сеанс профилирования. Лично я добавил инструмент «Точки интереса» и добавил указатель, где я создал этот MyClass экземпляр,

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        os_log_t log = os_log_create("ViewController", OS_LOG_CATEGORY_POINTS_OF_INTEREST);
        os_signpost_id_t identifier = os_signpost_id_generate(log);
    
        os_signpost_event_emit(log, identifier, "MyClass");
    
        MyClass *myClass = [[MyClass alloc] init];  // the problem here is that I’m using a local variable for the parent class, but the situation in your case may vary
        [myClass func];
    }
    

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

    В любом случае, упражняйте свое приложение, чтобы вы могли проявить проблему. Затем остановите запись. Затем выберите инструмент «Распределение» и найдите свой объект:

    enter image description here

    Вы можете (нажав на стрелку рядом с вашим адресом для этого объекта) увидеть каждая ссылка добавлена ​​и удалена:

    enter image description here

Я не только вижу, что она была освобождена, но я вижу полный стек проследите, где это произошло. Обратите внимание, что метод func находится не в этой трассировке стека, а, скорее, я был в viewDidLoad, внутри dealloc из MyClass, который вызвал dealloc из MyCustomClass. Я даже могу дважды щелкнуть viewDidMethod в моем стеке справа и быть взятым прямо там, где это произошло:

enter image description here

Теперь я вижу проблема в том, что я «случайно» сделал MyClass локальной переменной. Поэтому я бы изменил его, чтобы использовать это свойство (которое в настоящее время закомментировано), и проблема исчезнет go.

Теперь точный источник проблемы в вашем случае, несомненно, будет меняться, но в зависимости от разумности dealloc регистрация и возможность инструментов показывать нам все ссылки, которые были добавлены и удалены, вы сможете диагностировать проблему. И не забудьте go выполнить полную трассировку стека (сосредоточившись на вашем коде белым цветом) и посмотреть, все ли там имеет смысл. Часто мы будем останавливаться на рассматриваемом свойстве (obj в вашем примере) и забывать смотреть на то, что происходит раньше в трассировке стека.

...