Differences between [NSArray arrayWithArray:] and

2020-06-07 07:00发布

lately I work much with arrays and I'm wonder.. what's diffrences between those two lines.

NSArray *array = [NSArray arrayWithArray:someArray];

and

NSArray *array = [someArray copy];

Which of it is faster? What in case we have NSMutableArray and mutableCopy?

7条回答
Rolldiameter
2楼-- · 2020-06-07 07:07

The difference between the two is that the latter will be retained. The former will be autoreleased.

Both versions make a shallow copy of the array.

NSMutableArray *notMutableReally = [NSArray arrayWithArray:aMutableArray];

Should give you a compiler warning as you will be trying to assign a NSArray to a NSMutableArray.

Use.

NSMutableArray *mutableArrayCopy = [NSMutableArray arrayWithArray:aMutableArray];

Which is faster? Dont worry, they are all far faster than the rest of the stuff you will be doing. Check with Instruments if you really care.

查看更多
虎瘦雄心在
3楼-- · 2020-06-07 07:17

One of them is probably faster. Run them a million times and see if anyone wins.

In case of NSArray vs NSMutableArray, an immutable array being copied does not have to actually return a copy since it can't change. However, if you have a mutable array, it would need to be copied since you could change the original. And of course doing a mutable copy always needs to return a new object.

In your entire app, the speed and memory difference is probably not going to matter compared to everything else that's going on.

查看更多
Anthone
4楼-- · 2020-06-07 07:18

Which of it is faster?

Don't worry about it. Premature optimization.

The main difference: the first approach results in an autoreleased "copy" that you don't own and don't have to release, while you do own the object created on the second line. Both arrays will be immutable, by the way.

查看更多
地球回转人心会变
5楼-- · 2020-06-07 07:19

In Swift, it's very different. Thanks to the new open-source Foundation for Swift, we know that whereas init(array:) creates a new array with the items given (if any), copy() simply returns 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

So, obviously, copy() is faster, and now you know how they both work! (Just only in Swift)

查看更多
Rolldiameter
6楼-- · 2020-06-07 07:22
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);

time A: 1.572795, time B: 1.539150, B [NSArray arrayWithArray:] always faster but time difference very small. But if we uncomment "MARK" and get copy from NSArray instead NSMutableArray we will have other runtime A: 0.000473 time B: 1.548400 result: ~3200x times faster

查看更多
Root(大扎)
7楼-- · 2020-06-07 07:24

The main difference is that -copy knows better how to copy itself (can do it more efficiently and maybe use a more adapted subclass of NSArray) while +arrayWithArray: will create a new instance of NSArray (well, in fact the concrete class used by Foundation for arrays) and feed it with the same list of objects from the initial object. Also it will add an extra autorelease.

So -copy is (very very) likely more efficient.

In fact for immutable NSArrays, -copy is just doing -retain, so it does not even bother creating a new instance.

查看更多
登录 后发表回答