orphan: |
---|
Author: | Dave Abrahams |
---|---|
Date: | 2014-04-10 |
Swift provides three generic array types, all of which have copy-on-write value semantics and amortized O(1) growth. In this document, statements about ArrayType apply to all three of the components.
NativeArray<T>
is the fastest and simplest of the three—use this when you need "C array" performance. The elements of aNativeArray
are always stored contiguously in memory.Array<T>
is likeNativeArray<T>
, but optimized for efficient conversions from Cocoa and back—whenT
is a pure Objective-C class or protocol, it can be backed by the (potentially non-contiguous) storage of an arbitraryNSArray
rather than by a SwiftNativeArray
. WhenT
is known to be a pure Swift type, the performance ofArray<T>
is identical to that ofNativeArray<T>
.Slice<T>
is a subrange of someArray<T>
orNativeArray<T>
; it's the result of using slice notation, e.g.a[7...21]
on any Swift arraya
. A slice always has contiguous storage and "C array" performance. Slicing an ArrayType is O(1) unless the source is anArray<T>
backed by anNSArray
that doesn't supply contiguous storage.Slice
is recommended for transient computations but not for long-term storage. Since it references a sub-range of some shared backing buffer, aSlice
may artificially prolong the lifetime of elements outside theSlice
itself.
- ArrayType
<T>
implicitly converts to ArrayType<U>
ifT
is a trivial subtype ofU
(or ifU
isAnyObject
—see below). [Implementation note: when accessed as ArrayType<U>
, the underlying buffer ofT
s is treated as immutable, to be copied-on-write, even if uniquely-referenced] - ArrayType
<U>
explicitly converts to ArrayType<T>
? viax as ArrayType<T>
. The cast succeeds, yielding a non-nil result, iff the original value was of some ArrayType<V>
whereV
is a trivial subtype ofT
. [Implementation note: ifV
==T
, the underlying buffer need only be treated as immutable if uniquely referenced]
An arbitrary Swift type
T
can conform toBridgedToObjectiveC
, which specifies its conversions to and from ObjectiveC:protocol BridgedToObjectiveC { // FIXME: should be ': class' or ': AnyObject' typealias ObjectiveCType: ObjCClassType func bridgeToObjectiveC() -> ObjectiveCType class func bridgeFromObjectiveC(_: ObjectiveCType) -> Self? }
User-defined value types may conform to
BridgedToObjectiveC
, but user-defined classes may not. [This restriction allows us to maintain the highest efficiency forArray<T>
whereT
is a Swift class].Some generic types (
Array<T>
in particular) can be bridged only if their element type can be bridged. These conform toConditionallyBridgedToObjectiveC
:protocol ConditionallyBridgedToObjectiveC : BridgedToObjectiveC { class func isBridgedToObjectiveC() -> Bool }
A type
T
is formally considered bridged if:- it conforms to
ConditionallyBridgedToObjectiveC
andT.isBridgedToObjectiveC()
istrue
- or,
T
does not conform toConditionallyBridgedToObjectiveC
, and- it is a class type, or
- it conforms to
BridgedToObjectiveC
- it conforms to
A type
T
is considered bridged verbatim if it is a class type that does not conform toBridgedToObjectiveC
A value
x
of type AnyObject bridges toT
ifT
is bridged andT.bridgeFromObjectiveC((x as T.ObjectiveCType)!)
is valid and non-nil.
- ArrayType
<T>
is bridged iffT
is bridged. NSArray
can be constructed from any bridgedArray<T>
orNativeArray<T>
in O(1), without allocation. [Implementation note: we could allow construction fromSlice<T>
also, but it would require an allocation]- Any bridged ArrayType
<T>
is implicitly convertible to ArrayType<AnyObject>
in O(1), without allocation. - In both cases above, if
T
is not bridged, it is considered a fatal error, detected at runtime. - if
T
is not bridged verbatim, the elements of the resultingNSArray
orArray<AnyObject>
are created once, on-demand, by callingbridgeToObjectiveC()
on the originalT
s, and will be kept alive as long as does the array from which they were extracted.
NSArray
can be implicitly converted toArray<AnyObject>
in O(1)
NSArray
andArray<AnyObject>
can be explicitly converted toArray<T>?
usinga as Array<T>
. There are several cases:- If the
NSArray
was originally created as a Swift ArrayType<U>
, conversion is O(1) and succeeds ifU
is a trivial subtype ofT
- Otherwise, if
T
is not bridged, conversion fails in O(1), yielding nil - Otherwise, if
T
is a pure ObjC class or protocol, conversion succeeds unconditionally in O(1). In that case, any individual element that is not actually aT
may be detected later by the usual Objective-C means, most commonly anobjc_msgSend
failure. - Otherwise, conversion is O(N) and succeeds iff every element of
the
NSArray
bridges toT
.
- If the