it-swarm.com.ru

Различия между [NSArray arrayWithArray:] и [NSArray copy]

в последнее время я много работаю с массивами, и мне интересно ... в чем разница между этими двумя строками.

NSArray *array = [NSArray arrayWithArray:someArray];

а также

NSArray *array = [someArray copy];

Что из этого быстрее? Что, если у нас есть NSMutableArray и mutableCopy?

20
Błażej

Что из этого быстрее?

Не беспокойся об этом. Преждевременная оптимизация.

Основное отличие: первый подход приводит к автоматически выпущенной "копии", которой вы не владеете и не должны выпускать, в то время как вы владеете объектом, созданным во второй строке. Кстати, оба массива будут неизменными.

24
user529758

В дополнение к другим ответам также обратите внимание, что когда someArray равно nil, первая строка будет указывать array на пустой массив, а вторая - на nil. Это может быть важным отличием, особенно в изменяемых массивах.

21
Mario

Разница между ними заключается в том, что последний будет сохранен. Первый будет автоматически выпущен.

Обе версии делают поверхностную копию массива.

NSMutableArray *notMutableReally = [NSArray arrayWithArray:aMutableArray];

Должен дать вам предупреждение компилятора, поскольку вы будете пытаться назначить NSArray для NSMutableArray.

Используйте.

NSMutableArray *mutableArrayCopy = [NSMutableArray arrayWithArray:aMutableArray];

Что быстрее? Не волнуйтесь, все они гораздо быстрее, чем остальные вещи, которые вы будете делать. Проверьте с инструментами, если вы действительно заботитесь.

7
Warren Burton

Основное отличие состоит в том, что -copy лучше знает, как копировать себя (может делать это более эффективно и, возможно, использовать более адаптированный подкласс NSArray), в то время как +arrayWithArray: создаст новый экземпляр NSArray (ну, фактически, конкретный класс, используемый Foundation для массивов) ) и передать его тем же списком объектов из исходного объекта. Также это добавит дополнительный авто-релиз.

Так что -copy (очень очень), вероятно, более эффективен.

Фактически для неизменяемого NSArrays, -copy просто выполняет -retain, поэтому он даже не беспокоится о создании нового экземпляра.

4
Julien
NSMutableArray *arr = [NSMutableArray array];
for ( int i = 0; i < 10000; i ++)
{
    [arr addObject:@(i*1000000ULL)];
}
// MARK
// arr = (id)[NSArray arrayWithArray:arr];

NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate];
NSArray *res = nil;
for ( int i = 0; i < 10000; i ++)
{
    res = [arr copy];
}
NSLog(@"time A: %f", [NSDate timeIntervalSinceReferenceDate] - t);
t = [NSDate timeIntervalSinceReferenceDate];
for ( int i = 0; i < 10000; i ++)
{
    res = [NSArray arrayWithArray:arr];
}
NSLog(@"time B: %f", [NSDate timeIntervalSinceReferenceDate] - t);

время A: 1,572795, время B: 1,539150, B [NSArray arrayWithArray:] всегда быстрее, но разница во времени очень мала. Но если мы раскомментируем "MARK" и получим копию из NSArray вместо NSMutableArray, у нас будет другое время выполнения A: 0,000473 время B: 1,548400 результат: в 3200 раз быстрее

3
Roman Solodyashkin

Один из них, вероятно, быстрее. Запустите их миллион раз и посмотрите, кто победит.

В случае NSArray против NSMutableArray копируемый неизменный массив не должен фактически возвращать копию, поскольку он не может измениться. Однако, если у вас есть изменяемый массив, его нужно будет скопировать, поскольку вы можете изменить оригинал. И, конечно, создание изменяемой копии всегда должно возвращать новый объект.

Во всем вашем приложении разница в скорости и памяти, вероятно, не будет иметь значения по сравнению со всем, что происходит.

1
Jesper

В Swift все по-другому. Благодаря новому Open Source Foundation для Swift мы знаем, что, хотя init(array:) создает новый массив с заданными элементами (если есть), copy() просто возвращает self.

    public override func copy() -> AnyObject {
        return copyWithZone(nil)
    }

    public func copyWithZone(zone: NSZone) -> AnyObject {
        return self
    }

https://github.com/Apple/Swift-corelibs-foundation/blob/master/Foundation/NSArray.Swift#L82

    public convenience init(array: [AnyObject]) {
        self.init(array: array, copyItems: false)
    }

    public convenience init(array: [AnyObject], copyItems: Bool) {
        let optionalArray : [AnyObject?] =
            copyItems ?
                array.map { return Optional<AnyObject>(($0 as! NSObject).copy()) } :
                array.map { return Optional<AnyObject>($0) }

        // This would have been Nice, but "initializer delegation cannot be nested in another expression"
//        optionalArray.withUnsafeBufferPointer { ptr in
//            self.init(objects: ptr.baseAddress, count: array.count)
//        }
        let cnt = array.count
        let buffer = UnsafeMutablePointer<AnyObject?>.alloc(cnt)
        buffer.initializeFrom(optionalArray)
        self.init(objects: buffer, count: cnt)
        buffer.destroy(cnt)
        buffer.dealloc(cnt)
    }

https://github.com/Apple/Swift-corelibs-foundation/blob/master/Foundation/NSArray.Swift#L116

Итак, очевидно, что copy() быстрее, и теперь вы знаете, как они оба работают! (Только в Swift)

1
Ben Leggiero