可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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
?
回答1:
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.
回答2:
In addition to the other answers, also note, that when someArray
is nil,
the first line will make array
point to an empty array and the second will make
it point to nil. This might be an important difference, especially in mutable arrays.
回答3:
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.
回答4:
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.
回答5:
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
回答6:
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.
回答7:
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)