Как написать правильное свойство только для чтения? - PullRequest
3 голосов
/ 08 февраля 2011

У меня есть 2 вопроса о том, как сделать правильное свойство только для чтения в Objective-C 2.0 +.

Вот мой оригинальный подход, назовем его решение 1 :

@interface ClassA{
 @private
  NSMutableArray *a_;
}

// NOTE: no retain
@property (nonatomic, readonly) NSMutableArray *a;

@end


///////////////////////////////////////
@implementation ClassA

@synthesize a = a_;

- (NSMutableArray *)a{
  if(nil == a_){
    a_ = [[NSMutableArray alloc] array];
  }
  // Potential leak warning on the following line.
  return a_;
}

- (void)dealloc{
  // I released the object here, I think this should be safe.
  [a_ release];
  [super dealloc];
@end

Когда я компилирую и анализирую его, система выдает предупреждение типа «потенциальная утечка при возврате _».

Затем я снова читаю документ Objective-C и нахожу другойподход, как показано ниже.Давайте назовем это решение 2 .

@interface ClassB{
 @private
  NSMutableArray *a_;
}

// NOTE: make it retain+readonly
@property (nonatomic, readonly, retain) NSMutableArray *a;

@end


///////////////////////////////////////
// Add a private category
@interface ClassB ()

// reset the property to readwrite
@property (nonatomic, readwrite, retain) NSMutableArray *a;

@end

//////
@implementation ClassB

@synthesize a = a_;

- (id)init{
  if(self = [super init]){
    // NOTE: set the value as we use property normally.
    self.a = [NSMutableArray array];
  }
  return self;
}

- (void)dealloc{
  self.a = nil;
  [super dealloc];
@end

Теперь вот мои вопросы:

  • Можно ли использовать решение 1 и избавиться от «потенциала»?утечка '?
  • Является ли решение 2 общим решением?

Спасибо, ребята!

- Тонни

Ответы [ 3 ]

3 голосов
/ 10 февраля 2011

В ответ на запрос я воспроизводлю свой комментарий в качестве ответа:

[[NSMutableArray alloc] array] должен выдать вам предупреждение компилятора, и оно обязательно вылетит. Вы хотите [[NSMutableArray alloc] init].

2 голосов
/ 10 февраля 2011

Честно говоря, мне проще использовать "приватные" свойства чтения-записи, а не суетиться с иварами вообще:

MyClass.h

@interface MyClass : NSObject

@property (nonatomic, copy, readonly) NSArray * someArray;    // Public

@end

MyClass.m

@interface MyClass ()     // Class extension

@property (nonatomic, copy, readwrite) NSArray * someArray;   // "Private"

@end

@implementation MyClass

@synthesize someArray = someArray_;

- (id)init
{
    self = [super init];

    if (self != nil)
    {
        self.someArray = ...; // Array initialization
    }

    return self;
}

- (void)dealloc
{
    [someArray_ release];

    [super dealloc];
}

@end

Нет необходимости в иваре! Современная среда выполнения автоматически их синтезирует. Ваше свойство доступно только для чтения извне (т. Е. Другим классам), но внутренне вы объявили свойство как доступное для чтения и записи, чтобы вы могли использовать удобство доступа к синтезированным свойствам.

(Конечно, я все еще объявляю явный синтез ivar - в этом примере someArray_ - для использования в -dealloc, поскольку есть веские причины не использовать свойства в -dealloc и, возможно, в -init.)

2 голосов
/ 08 февраля 2011

Как правило, если теперь значение свойства «только для чтения» будет опережать время, его следует установить в методе init.

Я не уверен, что это вызовет предупреждение об утечке, но я бы сделал что-то вроде:

@interface ClassA{
 @private
  NSMutableArray a_;
}

// NOTE: no retain
@property (nonatomic, readonly) NSMutableArray a;

@end

@implementation ClassB

@synthesize a = a_;

- (id)init{
  if(self = [super init]){
    // NOTE: set the value as we use property normally.
    a_ = [[NSMutableArray alloc] init];
  }
  return self;
}

- (NSMutableArray *)a
{
 return a_;
}

- (void)dealloc{
    [a_ release];
    [super dealloc];
   }
@end

РЕДАКТИРОВАНИЕ:

Исправлено назначение_.

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