Nano Hash - криптовалюты, майнинг, программирование

почему слабая для свойства и __weak переменная экземпляра ведут себя по-разному

Я знаю, что сильные и слабые - это модификаторы, используемые в объявлениях свойств, в то время как __strong и __weak используются в объявлениях переменных экземпляра... сильный говорит, что сохраняет объект в памяти до тех пор, пока я им владею, а слабый говорит, что сохраняет объект в памяти как пока кто-то еще имеет сильную ссылку на это ... верно? но я не понимаю, почему слабая для свойства и переменная __weak, например, ведет себя по-разному ?? Вот я и задумался...

 @interface DemoViewController (){

    __weak NSArray *weakArray;
    __strong NSArray *strongArray;
    __weak NSString *weakString;
    __strong NSString *strongString;  
 }

@property (weak) NSString *weakStringProperty;
@property (strong) NSString *strongStringProperty;

@property (weak) NSArray *weakArrayProperty;
@property (strong) NSArray *strongArrayProperty;

@end

@implementation DemoViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    strongArray = [[NSArray alloc] initWithObjects:@"one",@"two", nil];
    weakArray = strongArray;

    NSLog(@"Round:1 strongArray is %@.", strongArray);
    NSLog(@"Round:1 weakArray is %@.", weakArray);

    strongArray = nil;

    NSLog(@"Round:2 strongArray is %@.", strongArray);
    NSLog(@"Round:2 weakArray is %@.", weakArray);

    self.strongArrayProperty = [[NSArray alloc] initWithObjects:@"one",@"two", nil];
    self.weakArrayProperty = self.strongArrayProperty;

    NSLog(@"Round:1 strongArrayProperty is %@.", self.strongArrayProperty);
    NSLog(@"Round:1 weakArrayProperty is %@.", self.weakArrayProperty);

    self.strongArrayProperty = nil;

    NSLog(@"Round:2 strongArrayProperty is %@.", self.strongArrayProperty);
    NSLog(@"Round:2 weakArrayProperty is %@.", self.weakArrayProperty);


    strongString = [[NSString alloc]initWithFormat:@"instanceVariable"];
    weakString = strongString;

    NSLog(@"Round:1 strongString is %@.", strongString);
    NSLog(@"Round:1 weakString is %@.", weakString);

    strongString = nil;

    NSLog(@"Round:2 strongString is %@.", strongString);
    NSLog(@"Round:2 weakString is %@.", weakString);

    self.strongStringProperty = [[NSString alloc]initWithFormat:@"Property"];
    self.weakStringProperty = self.strongStringProperty;

    NSLog(@"Round:1 strongStringProperty is %@.", self.strongStringProperty);
    NSLog(@"Round:1 weakStringProperty is %@.", self.weakStringProperty);

    self.strongStringProperty = nil;

    NSLog(@"Round:2 strongStringProperty is %@.", self.strongStringProperty);
    NSLog(@"Round:2 weakStringProperty is %@.", self.weakStringProperty);

}
@end

И вот полученные логи

Round:1 strongArray is (
    one,
    two
).
 Round:1 weakArray is (
    one,
    two
).
 Round:2 strongArray is (null).
 Round:2 weakArray is (null).


 Round:1 strongArrayProperty is (
    one,
    two
).
Round:1 weakArrayProperty is (
    one,
    two
).
Round:2 strongArrayProperty is (null).
Round:2 weakArrayProperty is (
    one,
    two
).           —???

Round:1 strongString is instanceVariable.
Round:1 weakString is instanceVariable.
Round:2 strongString is (null).
Round:2 weakString is (null).


Round:1 strongStringProperty is Property.
Round:1 weakStringProperty is Property.
Round:2 strongStringProperty is (null).
Round:2 weakStringProperty is Property.   ——??

Обе слабые переменные экземпляра печатают (null) после того, как объекты, на которые они слабо ссылались, устанавливаются равными nil, и это, как и ожидалось, но мне интересно, почему оба слабых свойства weakStringProperty и weakArrayProperty все еще печатают свои предыдущие значения и ведут себя так, как будто они строго указывали на strongStringProperty и strongArrayProperty соответственно??

Спасибо :)


  • Я могу получить strongArrayProperty и weakArrayProperty как (null) в раунде 2. Хотя weakStringProperty в раунде 2 по-прежнему является свойством. Это очень странно, поскольку технически ARC должен с этим справиться. PS- Я запускал это на своем компьютере. 22.12.2016
  • Я думаю, причина в том, что слабое свойство сохраняется, поскольку основной метод имеет пул автоматического выпуска, который включает в себя запуск приложения. Из-за пула авторелиза слабое свойство не сразу устанавливается равным нулю. Хотя я пытался получить к нему доступ в viewDidAppear и didReceiveMemoryWarning (путем имитации предупреждения о памяти), он все равно не стал нулевым. 22.12.2016
  • странный!! когда я запускаю этот код на реальном устройстве, он дает ожидаемые результаты как для слабых переменных экземпляра, так и для слабых свойств... это означает, что проблема связана только с симуляторами. В любом случае спасибо @Kunal Shrivastava 23.12.2016

Ответы:


1

weakStringProperty не является nil, потому что Фонд все еще сохраняет его.

Когда вы вызвали [[NSString alloc]initWithFormat:@"Property"], Foundation решила интернировать строку как NSTaggedPointerString, которую затем сохранила для использования в будущем. Вы можете проверить это, зарегистрировав класс:

NSLog(@"kindof: %@", [self.weakStringProperty class]);

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

// Longer string
self.strongStringProperty = [[NSString alloc]initWithFormat:@"Property la la la"];

// Mutable string
self.strongStringProperty = [[NSMutableString alloc]initWithFormat:@"Property"];
22.12.2016

2

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

Изменить, например, на

@property (weak, nonatomic, readwrite) NSString *weakStringProperty; 

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

Однако iOS довольно часто создает объекты, которые никогда не будут выпущены. Например, существует один пустой объект NSArray, который никогда не будет выпущен. То же самое для многих объектов NSNumber, коротких строк, @YES и @NO и других. Нет никакой гарантии, что объект будет освобожден, когда вы думаете, что это произойдет, и, следовательно, нет гарантии, что слабый объект станет нулевым.

22.12.2016
  • на симуляторе ... Я попытался с изменениями, которые вы сказали сделать, и в результате ... свойства все еще не были установлены на ноль в viewDidLoad и viewWillAppear, но были установлены на ноль в viewDid Appear. Но странно то, что когда я запускаю это на устройстве, все слабые свойства обнуляются после того, как объекты, на которые они указывали, обнуляются и регистрируют ожидаемые результаты. В любом случае спасибо :) 23.12.2016
  • Новые материалы

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

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

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