iOS 10 NSNumber cra sh с перечислениями - PullRequest
1 голос
/ 01 мая 2020

У меня очень странная проблема, связанная с NSNumber объектами для моих перечисленных значений и доступом к ним на устройстве под управлением iOS os версии 10.

Так же, как отказ от ответственности - это проблема не возникает в других iOS os версиях.

Я объявил перечисление следующим образом:

typedef NS_ENUM(NSInteger, MYENUM) {
   FIRST = 1500,
   SECOND = 1700,
   THIRD = 1900,
   ...
};

При использовании этого перечисления я передаю его в этом fashion:

[[MyObject alloc] initObjectWith:@(FIRST)];

За исключением внутренней логики c, я использую enum в словаре и, следовательно, необходимо преобразовать его в NSNumber.

При этом происходит сбой приложения потому что перечисление как-то не NSNumber, а скорее NSIndexPath.

Screenshot

Почему это происходит?

Когда я удаляю штучный литерал и изменяю сигнатуру метода, чтобы принять NSInteger, этот cra sh исчезает.

Я пытался искать в Интернете этот тип проблемы, но коротко.

Дальнейшее объяснение (за комментарий) * 103 5 *

Никаких специальных логик c не происходит внутри метода init для myObject, просто присваивая свойству, которое определяется как NSNumber, передаваемому параметру.

Что касается журнала cra sh, XCode печально известен предоставлением не очень полезных журналов cra sh, и все, что я вижу, это EXC_BAD_ACCESS, что может означать либо доступ к освобожденному объекту, либо потенциальную утечку памяти.

Класс MyObject определяется следующим образом:

заголовочный файл:

@interface ISNEvent : NSObject

@property(nonatomic, assign) NSNumber* number;

-(instancetype)initObjectWith:(NSNumber*)number;

@end

.m файл:

- (instancetype)initObjectWith:(NSNumber*)number {
   self = [super init];
   if (self) {
     _number = number;
   }

   return self;
}

1 Ответ

1 голос
/ 02 мая 2020

Вы определили свою собственность с assign семантикой памяти:

@property(nonatomic, assign) NSNumber* number;

Это означает, что вы получите ссылку на все, что вы предоставляете, но вы не будете сохранять сильную ссылку, и вы выиграли 't nil ваша ссылка, когда объект освобожден. Это хуже обоих миров, потому что вы держите висячую ссылку на объект, который вы позволяете освободить. Как вы сказали, эта конкретная ошибка «может ... означать доступ к объекту, который был освобожден», и это именно то, что здесь происходит.

Вы можете рассмотреть возможность временного включения зомби ( команда + <</kbd>) или «Продукт» »« Схема »» «Редактировать схему ...» и go в разделе «Диагностика» настроек «Выполнить» и посмотрите, не изменится ли ваше поведение. Вероятно, вы больше не увидите эту ссылку NSIndexPath (или что-то еще), а скорее получите некоторое подтверждение того, что экземпляр NSNumber был освобожден.

В любом случае, вы, несомненно, хотели сделать это свойство NSNumber strong ссылка:

@property(nonatomic, strong) NSNumber *number;

Другим решением было бы сделать его weak, что позволило бы его освободить, но безопасно установить вашу ссылку на nil. Это безопаснее, чем assign, но я также сомневаюсь, что это то, что вы хотели. И третьим вариантом будет copy, который мы иногда используем с изменяемыми типами, который здесь неприменим.

Итог, в настоящее время, я бы посоветовал не использовать семантику памяти assign с любыми типами объектов. Используйте strong, copy или weak. В этом случае strong - это то, что вы хотите. Используйте assign только с примитивными типами данных (например, NSInteger, CGFloat, et c.), Но не с типами объектов.

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

...