Нужно ли переопределять геттер, чтобы свойство возвращало неизменяемую копию?

Предположим, что у меня есть класс, содержащий изменяемый массив. Я хочу убедиться, что если другие классы запросят массив, они получат неизменяемый тип, но в классе-владельце это на самом деле экземпляр NSMutableArray, чтобы я мог добавлять и удалять элементы.

#import "Person.h"

@class Asset;

@interface Employee : Person

{
    NSMutableArray *_assets;
}

@property (nonatomic,copy) NSArray *assets;

-(void)addAssets:(Asset *)a;

Вопрос в том, нужно ли мне изменить методы доступа на что-то подобное, или они будут автоматически вести себя так, как я хочу?

#import "Employee.h"
#import "Asset.h"

@implementation Employee

/* Accessors for assets properties
-(NSArray *)assets
{
    return [_assets copy];
}

-(void)setAssets:(NSArray *)assets
{
    _assets = [assets mutableCopy ];

}
*/

-(void)addAssets:(Asset *)a
{
    //is assets nil?

    if (!_assets) {
        //Create Array
        _assets = [[NSMutableArray alloc]init];
    }
    [_assets addObject:a];

}

person user3213703    schedule 04.08.2014    source источник
comment
Почему ты не попробовал?   -  person Amin Negm-Awad    schedule 04.08.2014


Ответы (2)


ответ ppalancica неверен. Атрибут copy означает только то, что установщик возьмет копию при установке свойства. Синтезированный геттер не возвращает копию. Вы должны реализовать это поведение самостоятельно:

- (NSArray *)assets
{
    return [_assets copy];
}

Возможно, вы захотите создать средство доступа только для внутреннего использования, которое не создает копии. Вы также можете повторно объявить свойство конфиденциально; Затем клиентский код будет обрабатывать массив, который он запрашивает, как неизменяемый.

Этот код демонстрирует, что синтезированный геттер возвращает нескопированный объект:

#import <Foundation/Foundation.h>

@interface ArrayReturner : NSObject

@property (copy, nonatomic) NSArray * array;

@end

@implementation ArrayReturner
{
    NSMutableArray * _array;
}

- (BOOL)myArrayIsIdenticalTo:(NSArray *)otherArray
{
    return _array == otherArray;
}

@end

int main(int argc, const char *argv[])
{
    @autoreleasepool {

        ArrayReturner * a = [ArrayReturner new];
        [a setArray:@[@1, @2]];
        NSArray * returnedArray = [a array];
        // Does not throw
        NSCAssert([a myArrayIsIdenticalTo:returnedArray],
                  @"Returned array is a separate instance.");
    }

    return 0;
}
person jscs    schedule 19.08.2014
comment
что мне сделать, чтобы синтезированный геттер возвращал копию? ну, я попытался изменить код вашего примера, изменив геттер, чтобы он возвращал копию. но все же myArrayIsIdentical приводит к идентичному совпадению. - person user3213703; 06.11.2014
comment
Какой класс вы используете для своего теста? Неизменяемые классы часто не возвращают новый объект при их копировании для экономии памяти. - person jscs; 06.11.2014
comment
Я реплицировал ваш класс ArrayReturner и изменил его на Mutable (изменяемый массив), ну, оказывается, мне нужно реализовать методы установки и получения в изменяемом классе на случай, если я хочу получить новый скопированный объект (массив) из класса MutableArrayReturner. - person user3213703; 07.11.2014

Поскольку вы уже указали атрибут "copy" для свойства массива, нет необходимости переопределять геттер и сеттер. Компилятор сделает всю тяжелую работу за вас.

Если вместо этого вы укажете «сильный», геттер и сеттер будут выглядеть так:

-(NSArray *)assets
{
    return _assets;
}

-(void)setAssets:(NSArray *)assets
{
    _assets = assets;
}

И это может быть проблемой.

На самом деле существует конференция WWDC, которая объясняет все эти детали. Для свойств NSString рекомендуется использовать копирование, и вы можете увидеть это во многом в фреймворках iOS SDK.

person ppalancica    schedule 04.08.2014
comment
Полагаю, вы имеете в виду сессию WWDC — вся конференция охватывает очень много тем. Было бы полезно указать, о каком сеансе вы говорите, может быть, даже дать ссылку на видео. - person Caleb; 04.08.2014
comment
Да, сессия, извините. Полезной ссылкой может быть: developer.apple.com/videos/wwdc/2012. Сеансы 405, 413 или любые другие, связанные с управлением памятью и эффективным использованием Objective-C. - person ppalancica; 04.08.2014
comment
copy не заставит получатель вернуть копию; спецификатор свойства влияет только на установщик. - person jscs; 04.08.2014
comment
Этот ответ неверен; синтезированный геттер не вернет копию: gist.github.com/woolsweater/ 38ad03759e6245bf6733 Вы должны написать свой собственный, если хотите такое поведение. - person jscs; 15.08.2014