mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Adds an explicit @escaping throughout the standard library, validation test suite, and tests. This will be necessary as soon as noescape is the default for closure parameters.
1553 lines
49 KiB
Swift
1553 lines
49 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@_exported import Foundation // Clang module
|
|
import CoreFoundation
|
|
import CoreGraphics
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// NSObject
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// These conformances should be located in the `ObjectiveC` module, but they can't
|
|
// be placed there because string bridging is not available there.
|
|
extension NSObject : CustomStringConvertible {}
|
|
extension NSObject : CustomDebugStringConvertible {}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Strings
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@available(*, unavailable, message: "Please use String or NSString")
|
|
public class NSSimpleCString {}
|
|
|
|
@available(*, unavailable, message: "Please use String or NSString")
|
|
public class NSConstantString {}
|
|
|
|
@_silgen_name("swift_convertStringToNSString")
|
|
public // COMPILER_INTRINSIC
|
|
func _convertStringToNSString(_ string: String) -> NSString {
|
|
return string._bridgeToObjectiveC()
|
|
}
|
|
|
|
extension NSString : ExpressibleByStringLiteral {
|
|
/// Create an instance initialized to `value`.
|
|
public required convenience init(unicodeScalarLiteral value: StaticString) {
|
|
self.init(stringLiteral: value)
|
|
}
|
|
|
|
public required convenience init(
|
|
extendedGraphemeClusterLiteral value: StaticString
|
|
) {
|
|
self.init(stringLiteral: value)
|
|
}
|
|
|
|
/// Create an instance initialized to `value`.
|
|
public required convenience init(stringLiteral value: StaticString) {
|
|
var immutableResult: NSString
|
|
if value.hasPointerRepresentation {
|
|
immutableResult = NSString(
|
|
bytesNoCopy: UnsafeMutableRawPointer(mutating: value.utf8Start),
|
|
length: Int(value.utf8CodeUnitCount),
|
|
encoding: value.isASCII ? String.Encoding.ascii.rawValue : String.Encoding.utf8.rawValue,
|
|
freeWhenDone: false)!
|
|
} else {
|
|
var uintValue = value.unicodeScalar
|
|
immutableResult = NSString(
|
|
bytes: &uintValue,
|
|
length: 4,
|
|
encoding: String.Encoding.utf32.rawValue)!
|
|
}
|
|
self.init(string: immutableResult as String)
|
|
}
|
|
}
|
|
|
|
extension NSString : _HasCustomAnyHashableRepresentation {
|
|
// Must be @nonobjc to prevent infinite recursion trying to bridge
|
|
// AnyHashable to NSObject.
|
|
@nonobjc
|
|
public func _toCustomAnyHashable() -> AnyHashable? {
|
|
// Consistently use Swift equality and hashing semantics for all strings.
|
|
return AnyHashable(self as String)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// New Strings
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
// Conversion from NSString to Swift's native representation
|
|
//
|
|
|
|
extension String {
|
|
public init(_ cocoaString: NSString) {
|
|
self = String(_cocoaString: cocoaString)
|
|
}
|
|
}
|
|
|
|
extension String : _ObjectiveCBridgeable {
|
|
@_semantics("convertToObjectiveC")
|
|
public func _bridgeToObjectiveC() -> NSString {
|
|
// This method should not do anything extra except calling into the
|
|
// implementation inside core. (These two entry points should be
|
|
// equivalent.)
|
|
return unsafeBitCast(_bridgeToObjectiveCImpl() as AnyObject, to: NSString.self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
_ x: NSString,
|
|
result: inout String?
|
|
) {
|
|
result = String(x)
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ x: NSString,
|
|
result: inout String?
|
|
) -> Bool {
|
|
self._forceBridgeFromObjectiveC(x, result: &result)
|
|
return result != nil
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(
|
|
_ source: NSString?
|
|
) -> String {
|
|
// `nil` has historically been used as a stand-in for an empty
|
|
// string; map it to an empty string.
|
|
if _slowPath(source == nil) { return String() }
|
|
return String(source!)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Numbers
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberWithInt")
|
|
internal func _swift_Foundation_TypePreservingNSNumberWithInt(
|
|
_ value: Int
|
|
) -> NSNumber
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberWithUInt")
|
|
internal func _swift_Foundation_TypePreservingNSNumberWithUInt(
|
|
_ value: UInt
|
|
) -> NSNumber
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberWithFloat")
|
|
internal func _swift_Foundation_TypePreservingNSNumberWithFloat(
|
|
_ value: Float
|
|
) -> NSNumber
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberWithDouble")
|
|
internal func _swift_Foundation_TypePreservingNSNumberWithDouble(
|
|
_ value: Double
|
|
) -> NSNumber
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberWithCGFloat")
|
|
internal func _swift_Foundation_TypePreservingNSNumberWithCGFloat(
|
|
_ value: CGFloat
|
|
) -> NSNumber
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberWithBool")
|
|
internal func _swift_Foundation_TypePreservingNSNumberWithBool(
|
|
_ value: Bool
|
|
) -> NSNumber
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberGetKind")
|
|
internal func _swift_Foundation_TypePreservingNSNumberGetKind(
|
|
_ value: NSNumber
|
|
) -> UInt32
|
|
|
|
// This enum has a matching counterpart in TypePreservingNSNumber.mm, please
|
|
// update both copies when changing it.
|
|
internal enum _SwiftTypePreservingNSNumberTag : Int {
|
|
case SwiftInt = 1
|
|
case SwiftUInt = 2
|
|
case SwiftFloat = 3
|
|
case SwiftDouble = 4
|
|
case CoreGraphicsCGFloat = 5
|
|
case SwiftBool = 6
|
|
}
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberGetAsInt")
|
|
internal func _swift_Foundation_TypePreservingNSNumberGetAsInt(
|
|
_ value: NSNumber
|
|
) -> Int
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberGetAsUInt")
|
|
internal func _swift_Foundation_TypePreservingNSNumberGetAsUInt(
|
|
_ value: NSNumber
|
|
) -> UInt
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberGetAsFloat")
|
|
internal func _swift_Foundation_TypePreservingNSNumberGetAsFloat(
|
|
_ value: NSNumber
|
|
) -> Float
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberGetAsDouble")
|
|
internal func _swift_Foundation_TypePreservingNSNumberGetAsDouble(
|
|
_ value: NSNumber
|
|
) -> Double
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberGetAsCGFloat")
|
|
internal func _swift_Foundation_TypePreservingNSNumberGetAsCGFloat(
|
|
_ value: NSNumber
|
|
) -> CGFloat
|
|
|
|
@_silgen_name("_swift_Foundation_TypePreservingNSNumberGetAsBool")
|
|
internal func _swift_Foundation_TypePreservingNSNumberGetAsBool(
|
|
_ value: NSNumber
|
|
) -> Bool
|
|
|
|
// Conversions between NSNumber and various numeric types. The
|
|
// conversion to NSNumber is automatic (auto-boxing), while conversion
|
|
// back to a specific numeric type requires a cast.
|
|
// FIXME: Incomplete list of types.
|
|
extension Int : _ObjectiveCBridgeable {
|
|
public init(_ number: NSNumber) {
|
|
self = number.intValue
|
|
}
|
|
|
|
@_semantics("convertToObjectiveC")
|
|
public func _bridgeToObjectiveC() -> NSNumber {
|
|
return _swift_Foundation_TypePreservingNSNumberWithInt(self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout Int?
|
|
) {
|
|
result = x.intValue
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout Int?
|
|
) -> Bool {
|
|
self._forceBridgeFromObjectiveC(x, result: &result)
|
|
return true
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(
|
|
_ source: NSNumber?
|
|
) -> Int {
|
|
return source!.intValue
|
|
}
|
|
}
|
|
|
|
extension UInt : _ObjectiveCBridgeable {
|
|
public init(_ number: NSNumber) {
|
|
self = number.uintValue
|
|
}
|
|
|
|
@_semantics("convertToObjectiveC")
|
|
public func _bridgeToObjectiveC() -> NSNumber {
|
|
return _swift_Foundation_TypePreservingNSNumberWithUInt(self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout UInt?
|
|
) {
|
|
result = x.uintValue
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout UInt?
|
|
) -> Bool {
|
|
self._forceBridgeFromObjectiveC(x, result: &result)
|
|
return true
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(
|
|
_ source: NSNumber?
|
|
) -> UInt {
|
|
return source!.uintValue
|
|
}
|
|
}
|
|
|
|
extension Float : _ObjectiveCBridgeable {
|
|
public init(_ number: NSNumber) {
|
|
self = number.floatValue
|
|
}
|
|
|
|
@_semantics("convertToObjectiveC")
|
|
public func _bridgeToObjectiveC() -> NSNumber {
|
|
return _swift_Foundation_TypePreservingNSNumberWithFloat(self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout Float?
|
|
) {
|
|
result = x.floatValue
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout Float?
|
|
) -> Bool {
|
|
self._forceBridgeFromObjectiveC(x, result: &result)
|
|
return true
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(
|
|
_ source: NSNumber?
|
|
) -> Float {
|
|
return source!.floatValue
|
|
}
|
|
}
|
|
|
|
extension Double : _ObjectiveCBridgeable {
|
|
public init(_ number: NSNumber) {
|
|
self = number.doubleValue
|
|
}
|
|
|
|
@_semantics("convertToObjectiveC")
|
|
public func _bridgeToObjectiveC() -> NSNumber {
|
|
return _swift_Foundation_TypePreservingNSNumberWithDouble(self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout Double?
|
|
) {
|
|
result = x.doubleValue
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout Double?
|
|
) -> Bool {
|
|
self._forceBridgeFromObjectiveC(x, result: &result)
|
|
return true
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(
|
|
_ source: NSNumber?
|
|
) -> Double {
|
|
return source!.doubleValue
|
|
}
|
|
}
|
|
|
|
extension Bool: _ObjectiveCBridgeable {
|
|
public init(_ number: NSNumber) {
|
|
self = number.boolValue
|
|
}
|
|
|
|
@_semantics("convertToObjectiveC")
|
|
public func _bridgeToObjectiveC() -> NSNumber {
|
|
return _swift_Foundation_TypePreservingNSNumberWithBool(self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout Bool?
|
|
) {
|
|
result = x.boolValue
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout Bool?
|
|
) -> Bool {
|
|
self._forceBridgeFromObjectiveC(x, result: &result)
|
|
return true
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(
|
|
_ source: NSNumber?
|
|
) -> Bool {
|
|
return source!.boolValue
|
|
}
|
|
}
|
|
|
|
// CGFloat bridging.
|
|
extension CGFloat : _ObjectiveCBridgeable {
|
|
public init(_ number: NSNumber) {
|
|
self.native = CGFloat.NativeType(number)
|
|
}
|
|
|
|
@_semantics("convertToObjectiveC")
|
|
public func _bridgeToObjectiveC() -> NSNumber {
|
|
return _swift_Foundation_TypePreservingNSNumberWithCGFloat(self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout CGFloat?
|
|
) {
|
|
var nativeResult: CGFloat.NativeType? = 0.0
|
|
CGFloat.NativeType._forceBridgeFromObjectiveC(x, result: &nativeResult)
|
|
result = CGFloat(nativeResult!)
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ x: NSNumber,
|
|
result: inout CGFloat?
|
|
) -> Bool {
|
|
self._forceBridgeFromObjectiveC(x, result: &result)
|
|
return true
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(
|
|
_ source: NSNumber?
|
|
) -> CGFloat {
|
|
return CGFloat(
|
|
CGFloat.NativeType._unconditionallyBridgeFromObjectiveC(source))
|
|
}
|
|
}
|
|
|
|
// Literal support for NSNumber
|
|
extension NSNumber
|
|
: ExpressibleByFloatLiteral,
|
|
ExpressibleByIntegerLiteral,
|
|
ExpressibleByBooleanLiteral
|
|
{
|
|
/// Create an instance initialized to `value`.
|
|
public required convenience init(integerLiteral value: Int) {
|
|
self.init(value: value)
|
|
}
|
|
|
|
/// Create an instance initialized to `value`.
|
|
public required convenience init(floatLiteral value: Double) {
|
|
self.init(value: value)
|
|
}
|
|
|
|
/// Create an instance initialized to `value`.
|
|
public required convenience init(booleanLiteral value: Bool) {
|
|
self.init(value: value)
|
|
}
|
|
}
|
|
|
|
extension NSNumber : _HasCustomAnyHashableRepresentation {
|
|
// Must be @nonobjc to prevent infinite recursion trying to bridge
|
|
// AnyHashable to NSObject.
|
|
@nonobjc
|
|
public func _toCustomAnyHashable() -> AnyHashable? {
|
|
guard let kind = _SwiftTypePreservingNSNumberTag(
|
|
rawValue: Int(_swift_Foundation_TypePreservingNSNumberGetKind(self))
|
|
) else {
|
|
if let nsDecimalNumber: NSDecimalNumber = self as? NSDecimalNumber {
|
|
return AnyHashable(nsDecimalNumber as Decimal)
|
|
}
|
|
return nil
|
|
}
|
|
switch kind {
|
|
case .SwiftInt:
|
|
return AnyHashable(_swift_Foundation_TypePreservingNSNumberGetAsInt(self))
|
|
case .SwiftUInt:
|
|
return AnyHashable(_swift_Foundation_TypePreservingNSNumberGetAsUInt(self))
|
|
case .SwiftFloat:
|
|
return AnyHashable(_swift_Foundation_TypePreservingNSNumberGetAsFloat(self))
|
|
case .SwiftDouble:
|
|
return AnyHashable(_swift_Foundation_TypePreservingNSNumberGetAsDouble(self))
|
|
case .CoreGraphicsCGFloat:
|
|
return AnyHashable(_swift_Foundation_TypePreservingNSNumberGetAsCGFloat(self))
|
|
case .SwiftBool:
|
|
return AnyHashable(_swift_Foundation_TypePreservingNSNumberGetAsBool(self))
|
|
}
|
|
}
|
|
}
|
|
|
|
public let NSNotFound: Int = .max
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Arrays
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension NSArray : ExpressibleByArrayLiteral {
|
|
/// Create an instance initialized with `elements`.
|
|
public required convenience init(arrayLiteral elements: Any...) {
|
|
// Let bridging take care of it.
|
|
self.init(array: elements)
|
|
}
|
|
}
|
|
|
|
extension Array : _ObjectiveCBridgeable {
|
|
|
|
/// Private initializer used for bridging.
|
|
///
|
|
/// The provided `NSArray` will be copied to ensure that the copy can
|
|
/// not be mutated by other code.
|
|
internal init(_cocoaArray: NSArray) {
|
|
_sanityCheck(_isBridgedVerbatimToObjectiveC(Element.self),
|
|
"Array can be backed by NSArray only when the element type can be bridged verbatim to Objective-C")
|
|
// FIXME: We would like to call CFArrayCreateCopy() to avoid doing an
|
|
// objc_msgSend() for instances of CoreFoundation types. We can't do that
|
|
// today because CFArrayCreateCopy() copies array contents unconditionally,
|
|
// resulting in O(n) copies even for immutable arrays.
|
|
//
|
|
// <rdar://problem/19773555> CFArrayCreateCopy() is >10x slower than
|
|
// -[NSArray copyWithZone:]
|
|
//
|
|
// The bug is fixed in: OS X 10.11.0, iOS 9.0, all versions of tvOS
|
|
// and watchOS.
|
|
self = Array(
|
|
_immutableCocoaArray:
|
|
unsafeBitCast(_cocoaArray.copy() as AnyObject, to: _NSArrayCore.self))
|
|
}
|
|
|
|
@_semantics("convertToObjectiveC")
|
|
public func _bridgeToObjectiveC() -> NSArray {
|
|
return unsafeBitCast(self._buffer._asCocoaArray() as AnyObject, to: NSArray.self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
_ source: NSArray,
|
|
result: inout Array?
|
|
) {
|
|
_precondition(
|
|
Swift._isBridgedToObjectiveC(Element.self),
|
|
"array element type is not bridged to Objective-C")
|
|
|
|
// If we have the appropriate native storage already, just adopt it.
|
|
if let native =
|
|
Array._bridgeFromObjectiveCAdoptingNativeStorageOf(source) {
|
|
result = native
|
|
return
|
|
}
|
|
|
|
if _fastPath(_isBridgedVerbatimToObjectiveC(Element.self)) {
|
|
// Forced down-cast (possible deferred type-checking)
|
|
result = Array(_cocoaArray: source)
|
|
return
|
|
}
|
|
|
|
result = _arrayForceCast([AnyObject](_cocoaArray: source))
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ source: NSArray,
|
|
result: inout Array?
|
|
) -> Bool {
|
|
// Construct the result array by conditionally bridging each element.
|
|
let anyObjectArr = [AnyObject](_cocoaArray: source)
|
|
|
|
result = _arrayConditionalCast(anyObjectArr)
|
|
return result != nil
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(
|
|
_ source: NSArray?
|
|
) -> Array {
|
|
// `nil` has historically been used as a stand-in for an empty
|
|
// array; map it to an empty array instead of failing.
|
|
if _slowPath(source == nil) { return Array() }
|
|
|
|
// If we have the appropriate native storage already, just adopt it.
|
|
if let native =
|
|
Array._bridgeFromObjectiveCAdoptingNativeStorageOf(source!) {
|
|
return native
|
|
}
|
|
|
|
if _fastPath(_isBridgedVerbatimToObjectiveC(Element.self)) {
|
|
// Forced down-cast (possible deferred type-checking)
|
|
return Array(_cocoaArray: source!)
|
|
}
|
|
|
|
return _arrayForceCast([AnyObject](_cocoaArray: source!))
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Dictionaries
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension NSDictionary : ExpressibleByDictionaryLiteral {
|
|
public required convenience init(
|
|
dictionaryLiteral elements: (NSCopying, AnyObject)...
|
|
) {
|
|
self.init(
|
|
objects: elements.map { $0.1 },
|
|
forKeys: elements.map { $0.0 },
|
|
count: elements.count)
|
|
}
|
|
}
|
|
|
|
extension Dictionary {
|
|
/// Private initializer used for bridging.
|
|
///
|
|
/// The provided `NSDictionary` will be copied to ensure that the copy can
|
|
/// not be mutated by other code.
|
|
public init(_cocoaDictionary: _NSDictionary) {
|
|
_sanityCheck(
|
|
_isBridgedVerbatimToObjectiveC(Key.self) &&
|
|
_isBridgedVerbatimToObjectiveC(Value.self),
|
|
"Dictionary can be backed by NSDictionary storage only when both key and value are bridged verbatim to Objective-C")
|
|
// FIXME: We would like to call CFDictionaryCreateCopy() to avoid doing an
|
|
// objc_msgSend() for instances of CoreFoundation types. We can't do that
|
|
// today because CFDictionaryCreateCopy() copies dictionary contents
|
|
// unconditionally, resulting in O(n) copies even for immutable dictionaries.
|
|
//
|
|
// <rdar://problem/20690755> CFDictionaryCreateCopy() does not call copyWithZone:
|
|
//
|
|
// The bug is fixed in: OS X 10.11.0, iOS 9.0, all versions of tvOS
|
|
// and watchOS.
|
|
self = Dictionary(
|
|
_immutableCocoaDictionary:
|
|
unsafeBitCast(_cocoaDictionary.copy(with: nil) as AnyObject,
|
|
to: _NSDictionary.self))
|
|
}
|
|
}
|
|
|
|
// Dictionary<Key, Value> is conditionally bridged to NSDictionary
|
|
extension Dictionary : _ObjectiveCBridgeable {
|
|
@_semantics("convertToObjectiveC")
|
|
public func _bridgeToObjectiveC() -> NSDictionary {
|
|
return unsafeBitCast(_bridgeToObjectiveCImpl() as AnyObject,
|
|
to: NSDictionary.self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
_ d: NSDictionary,
|
|
result: inout Dictionary?
|
|
) {
|
|
if let native = [Key : Value]._bridgeFromObjectiveCAdoptingNativeStorageOf(
|
|
d as AnyObject) {
|
|
result = native
|
|
return
|
|
}
|
|
|
|
if _isBridgedVerbatimToObjectiveC(Key.self) &&
|
|
_isBridgedVerbatimToObjectiveC(Value.self) {
|
|
result = [Key : Value](
|
|
_cocoaDictionary: unsafeBitCast(d as AnyObject, to: _NSDictionary.self))
|
|
return
|
|
}
|
|
|
|
// `Dictionary<Key, Value>` where either `Key` or `Value` is a value type
|
|
// may not be backed by an NSDictionary.
|
|
var builder = _DictionaryBuilder<Key, Value>(count: d.count)
|
|
d.enumerateKeysAndObjects({
|
|
(anyKey: Any, anyValue: Any,
|
|
stop: UnsafeMutablePointer<ObjCBool>) in
|
|
let anyObjectKey = anyKey as AnyObject
|
|
let anyObjectValue = anyValue as AnyObject
|
|
builder.add(
|
|
key: Swift._forceBridgeFromObjectiveC(anyObjectKey, Key.self),
|
|
value: Swift._forceBridgeFromObjectiveC(anyObjectValue, Value.self))
|
|
})
|
|
result = builder.take()
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ x: NSDictionary,
|
|
result: inout Dictionary?
|
|
) -> Bool {
|
|
let anyDict = x as [NSObject : AnyObject]
|
|
if _isBridgedVerbatimToObjectiveC(Key.self) &&
|
|
_isBridgedVerbatimToObjectiveC(Value.self) {
|
|
result = Swift._dictionaryDownCastConditional(anyDict)
|
|
return result != nil
|
|
}
|
|
|
|
result = Swift._dictionaryBridgeFromObjectiveCConditional(anyDict)
|
|
return result != nil
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(
|
|
_ d: NSDictionary?
|
|
) -> Dictionary {
|
|
// `nil` has historically been used as a stand-in for an empty
|
|
// dictionary; map it to an empty dictionary.
|
|
if _slowPath(d == nil) { return Dictionary() }
|
|
|
|
if let native = [Key : Value]._bridgeFromObjectiveCAdoptingNativeStorageOf(
|
|
d! as AnyObject) {
|
|
return native
|
|
}
|
|
|
|
if _isBridgedVerbatimToObjectiveC(Key.self) &&
|
|
_isBridgedVerbatimToObjectiveC(Value.self) {
|
|
return [Key : Value](
|
|
_cocoaDictionary: unsafeBitCast(d! as AnyObject, to: _NSDictionary.self))
|
|
}
|
|
|
|
// `Dictionary<Key, Value>` where either `Key` or `Value` is a value type
|
|
// may not be backed by an NSDictionary.
|
|
var builder = _DictionaryBuilder<Key, Value>(count: d!.count)
|
|
d!.enumerateKeysAndObjects({
|
|
(anyKey: Any, anyValue: Any,
|
|
stop: UnsafeMutablePointer<ObjCBool>) in
|
|
builder.add(
|
|
key: Swift._forceBridgeFromObjectiveC(anyKey as AnyObject, Key.self),
|
|
value: Swift._forceBridgeFromObjectiveC(anyValue as AnyObject, Value.self))
|
|
})
|
|
return builder.take()
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// TextChecking
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension NSTextCheckingResult.CheckingType {
|
|
public static var allSystemTypes : NSTextCheckingResult.CheckingType {
|
|
return NSTextCheckingResult.CheckingType(rawValue: 0xffffffff)
|
|
}
|
|
|
|
public static var allCustomTypes : NSTextCheckingResult.CheckingType {
|
|
return NSTextCheckingResult.CheckingType(rawValue: 0xffffffff << 32)
|
|
}
|
|
|
|
public static var allTypes : NSTextCheckingResult.CheckingType {
|
|
return NSTextCheckingResult.CheckingType(rawValue: UInt64.max)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Fast enumeration
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// NB: This is a class because fast enumeration passes around interior pointers
|
|
// to the enumeration state, so the state cannot be moved in memory. We will
|
|
// probably need to implement fast enumeration in the compiler as a primitive
|
|
// to implement it both correctly and efficiently.
|
|
final public class NSFastEnumerationIterator : IteratorProtocol {
|
|
var enumerable: NSFastEnumeration
|
|
var state: [NSFastEnumerationState]
|
|
var n: Int
|
|
var count: Int
|
|
|
|
/// Size of ObjectsBuffer, in ids.
|
|
static var STACK_BUF_SIZE: Int { return 4 }
|
|
|
|
var objects: [Unmanaged<AnyObject>?]
|
|
|
|
public func next() -> Any? {
|
|
if n == count {
|
|
// FIXME: Is this check necessary before refresh()?
|
|
if count == 0 { return nil }
|
|
refresh()
|
|
if count == 0 { return nil }
|
|
}
|
|
let next: Any = state[0].itemsPtr![n]!
|
|
n += 1
|
|
return next
|
|
}
|
|
|
|
func refresh() {
|
|
_sanityCheck(objects.count > 0)
|
|
n = 0
|
|
objects.withUnsafeMutableBufferPointer {
|
|
count = enumerable.countByEnumerating(
|
|
with: &state,
|
|
objects: AutoreleasingUnsafeMutablePointer($0.baseAddress!),
|
|
count: $0.count)
|
|
}
|
|
}
|
|
|
|
public init(_ enumerable: NSFastEnumeration) {
|
|
self.enumerable = enumerable
|
|
self.state = [ NSFastEnumerationState(
|
|
state: 0, itemsPtr: nil,
|
|
mutationsPtr: _fastEnumerationStorageMutationsPtr,
|
|
extra: (0, 0, 0, 0, 0)) ]
|
|
self.objects = Array(
|
|
repeating: nil, count: NSFastEnumerationIterator.STACK_BUF_SIZE)
|
|
self.n = -1
|
|
self.count = -1
|
|
}
|
|
}
|
|
|
|
extension NSArray : Sequence {
|
|
/// Return an *iterator* over the elements of this *sequence*.
|
|
///
|
|
/// - Complexity: O(1).
|
|
final public func makeIterator() -> NSFastEnumerationIterator {
|
|
return NSFastEnumerationIterator(self)
|
|
}
|
|
}
|
|
|
|
/* TODO: API review
|
|
extension NSArray : Swift.Collection {
|
|
final public var startIndex: Int {
|
|
return 0
|
|
}
|
|
|
|
final public var endIndex: Int {
|
|
return count
|
|
}
|
|
}
|
|
*/
|
|
|
|
extension Set {
|
|
/// Private initializer used for bridging.
|
|
///
|
|
/// The provided `NSSet` will be copied to ensure that the copy can
|
|
/// not be mutated by other code.
|
|
public init(_cocoaSet: _NSSet) {
|
|
_sanityCheck(_isBridgedVerbatimToObjectiveC(Element.self),
|
|
"Set can be backed by NSSet _variantStorage only when the member type can be bridged verbatim to Objective-C")
|
|
// FIXME: We would like to call CFSetCreateCopy() to avoid doing an
|
|
// objc_msgSend() for instances of CoreFoundation types. We can't do that
|
|
// today because CFSetCreateCopy() copies dictionary contents
|
|
// unconditionally, resulting in O(n) copies even for immutable dictionaries.
|
|
//
|
|
// <rdar://problem/20697680> CFSetCreateCopy() does not call copyWithZone:
|
|
//
|
|
// The bug is fixed in: OS X 10.11.0, iOS 9.0, all versions of tvOS
|
|
// and watchOS.
|
|
self = Set(
|
|
_immutableCocoaSet:
|
|
unsafeBitCast(_cocoaSet.copy(with: nil) as AnyObject, to: _NSSet.self))
|
|
}
|
|
}
|
|
|
|
extension NSSet : Sequence {
|
|
/// Return an *iterator* over the elements of this *sequence*.
|
|
///
|
|
/// - Complexity: O(1).
|
|
public func makeIterator() -> NSFastEnumerationIterator {
|
|
return NSFastEnumerationIterator(self)
|
|
}
|
|
}
|
|
|
|
extension NSOrderedSet : Sequence {
|
|
/// Return an *iterator* over the elements of this *sequence*.
|
|
///
|
|
/// - Complexity: O(1).
|
|
public func makeIterator() -> NSFastEnumerationIterator {
|
|
return NSFastEnumerationIterator(self)
|
|
}
|
|
}
|
|
|
|
// FIXME: move inside NSIndexSet when the compiler supports this.
|
|
public struct NSIndexSetIterator : IteratorProtocol {
|
|
public typealias Element = Int
|
|
|
|
internal let _set: NSIndexSet
|
|
internal var _first: Bool = true
|
|
internal var _current: Int?
|
|
|
|
internal init(set: NSIndexSet) {
|
|
self._set = set
|
|
self._current = nil
|
|
}
|
|
|
|
public mutating func next() -> Int? {
|
|
if _first {
|
|
_current = _set.firstIndex
|
|
_first = false
|
|
} else if let c = _current {
|
|
_current = _set.indexGreaterThanIndex(c)
|
|
} else {
|
|
// current is already nil
|
|
}
|
|
if _current == NSNotFound {
|
|
_current = nil
|
|
}
|
|
return _current
|
|
}
|
|
}
|
|
|
|
extension NSIndexSet : Sequence {
|
|
/// Return an *iterator* over the elements of this *sequence*.
|
|
///
|
|
/// - Complexity: O(1).
|
|
public func makeIterator() -> NSIndexSetIterator {
|
|
return NSIndexSetIterator(set: self)
|
|
}
|
|
}
|
|
|
|
// Set<Element> is conditionally bridged to NSSet
|
|
extension Set : _ObjectiveCBridgeable {
|
|
@_semantics("convertToObjectiveC")
|
|
public func _bridgeToObjectiveC() -> NSSet {
|
|
return unsafeBitCast(_bridgeToObjectiveCImpl() as AnyObject, to: NSSet.self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(_ s: NSSet, result: inout Set?) {
|
|
if let native =
|
|
Set<Element>._bridgeFromObjectiveCAdoptingNativeStorageOf(s as AnyObject) {
|
|
|
|
result = native
|
|
return
|
|
}
|
|
|
|
if _isBridgedVerbatimToObjectiveC(Element.self) {
|
|
result = Set<Element>(_cocoaSet: unsafeBitCast(s, to: _NSSet.self))
|
|
return
|
|
}
|
|
|
|
// `Set<Element>` where `Element` is a value type may not be backed by
|
|
// an NSSet.
|
|
var builder = _SetBuilder<Element>(count: s.count)
|
|
s.enumerateObjects({
|
|
(anyMember: Any, stop: UnsafeMutablePointer<ObjCBool>) in
|
|
builder.add(member: Swift._forceBridgeFromObjectiveC(
|
|
anyMember as AnyObject, Element.self))
|
|
})
|
|
result = builder.take()
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ x: NSSet, result: inout Set?
|
|
) -> Bool {
|
|
let anySet = x as Set<NSObject>
|
|
if _isBridgedVerbatimToObjectiveC(Element.self) {
|
|
result = Swift._setDownCastConditional(anySet)
|
|
return result != nil
|
|
}
|
|
|
|
result = Swift._setBridgeFromObjectiveCConditional(anySet)
|
|
return result != nil
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(_ s: NSSet?) -> Set {
|
|
// `nil` has historically been used as a stand-in for an empty
|
|
// set; map it to an empty set.
|
|
if _slowPath(s == nil) { return Set() }
|
|
|
|
if let native =
|
|
Set<Element>._bridgeFromObjectiveCAdoptingNativeStorageOf(s! as AnyObject) {
|
|
|
|
return native
|
|
}
|
|
|
|
if _isBridgedVerbatimToObjectiveC(Element.self) {
|
|
return Set<Element>(_cocoaSet: unsafeBitCast(s! as AnyObject,
|
|
to: _NSSet.self))
|
|
}
|
|
|
|
// `Set<Element>` where `Element` is a value type may not be backed by
|
|
// an NSSet.
|
|
var builder = _SetBuilder<Element>(count: s!.count)
|
|
s!.enumerateObjects({
|
|
(anyMember: Any, stop: UnsafeMutablePointer<ObjCBool>) in
|
|
builder.add(member: Swift._forceBridgeFromObjectiveC(
|
|
anyMember as AnyObject, Element.self))
|
|
})
|
|
return builder.take()
|
|
}
|
|
}
|
|
|
|
/*
|
|
FIXME(id-as-any): uncomment this when we can cast NSSet to Set<AnyHashable>.
|
|
extension NSSet : _HasCustomAnyHashableRepresentation {
|
|
// Must be @nonobjc to avoid infinite recursion during bridging
|
|
@nonobjc
|
|
public func _toCustomAnyHashable() -> AnyHashable? {
|
|
var builder = _SetBuilder<Element>(count: s!.count)
|
|
// FIXME(id-as-any): how to get the Hashable conformance here?
|
|
s!.enumerateObjects({
|
|
(anyMember: Any, stop: UnsafeMutablePointer<ObjCBool>) in
|
|
builder.add(member: Swift._forceBridgeFromObjectiveC(
|
|
anyMember as AnyObject, Element.self))
|
|
})
|
|
return AnyHashable(self as Set<AnyHashable>)
|
|
}
|
|
}
|
|
*/
|
|
|
|
extension NSDictionary : Sequence {
|
|
// FIXME: A class because we can't pass a struct with class fields through an
|
|
// [objc] interface without prematurely destroying the references.
|
|
final public class Iterator : IteratorProtocol {
|
|
var _fastIterator: NSFastEnumerationIterator
|
|
var _dictionary: NSDictionary {
|
|
return _fastIterator.enumerable as! NSDictionary
|
|
}
|
|
|
|
public func next() -> (key: Any, value: Any)? {
|
|
if let key = _fastIterator.next() {
|
|
// Deliberately avoid the subscript operator in case the dictionary
|
|
// contains non-copyable keys. This is rare since NSMutableDictionary
|
|
// requires them, but we don't want to paint ourselves into a corner.
|
|
return (key: key, value: _dictionary.object(forKey: key)!)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
internal init(_ _dict: NSDictionary) {
|
|
_fastIterator = NSFastEnumerationIterator(_dict)
|
|
}
|
|
}
|
|
|
|
/// Return an *iterator* over the elements of this *sequence*.
|
|
///
|
|
/// - Complexity: O(1).
|
|
public func makeIterator() -> Iterator {
|
|
return Iterator(self)
|
|
}
|
|
}
|
|
|
|
extension NSEnumerator : Sequence {
|
|
/// Return an *iterator* over the *enumerator*.
|
|
///
|
|
/// - Complexity: O(1).
|
|
public func makeIterator() -> NSFastEnumerationIterator {
|
|
return NSFastEnumerationIterator(self)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Ranges
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension NSRange {
|
|
public init(_ x: Range<Int>) {
|
|
location = x.lowerBound
|
|
length = x.count
|
|
}
|
|
|
|
// FIXME(ABI)(compiler limitation): this API should be an extension on Range.
|
|
// Can't express it now because the compiler does not support conditional
|
|
// extensions with type equality constraints.
|
|
public func toRange() -> Range<Int>? {
|
|
if location == NSNotFound { return nil }
|
|
return location..<(location+length)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// NSLocalizedString
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Returns a localized string, using the main bundle if one is not specified.
|
|
public
|
|
func NSLocalizedString(_ key: String,
|
|
tableName: String? = nil,
|
|
bundle: Bundle = Bundle.main,
|
|
value: String = "",
|
|
comment: String) -> String {
|
|
return bundle.localizedString(forKey: key, value:value, table:tableName)
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// NSLog
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
public func NSLog(_ format: String, _ args: CVarArg...) {
|
|
withVaList(args) { NSLogv(format, $0) }
|
|
}
|
|
|
|
#if os(OSX)
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// NSRectEdge
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// In the SDK, the following NS*Edge constants are defined as macros for the
|
|
// corresponding CGRectEdge enumerators. Thus, in the SDK, NS*Edge constants
|
|
// have CGRectEdge type. This is not correct for Swift (as there is no
|
|
// implicit conversion to NSRectEdge).
|
|
|
|
@available(*, unavailable, renamed: "NSRectEdge.MinX")
|
|
public var NSMinXEdge: NSRectEdge {
|
|
fatalError("unavailable property can't be accessed")
|
|
}
|
|
@available(*, unavailable, renamed: "NSRectEdge.MinY")
|
|
public var NSMinYEdge: NSRectEdge {
|
|
fatalError("unavailable property can't be accessed")
|
|
}
|
|
@available(*, unavailable, renamed: "NSRectEdge.MaxX")
|
|
public var NSMaxXEdge: NSRectEdge {
|
|
fatalError("unavailable property can't be accessed")
|
|
}
|
|
@available(*, unavailable, renamed: "NSRectEdge.MaxY")
|
|
public var NSMaxYEdge: NSRectEdge {
|
|
fatalError("unavailable property can't be accessed")
|
|
}
|
|
|
|
extension NSRectEdge {
|
|
public init(rectEdge: CGRectEdge) {
|
|
self = NSRectEdge(rawValue: UInt(rectEdge.rawValue))!
|
|
}
|
|
}
|
|
|
|
extension CGRectEdge {
|
|
public init(rectEdge: NSRectEdge) {
|
|
self = CGRectEdge(rawValue: UInt32(rectEdge.rawValue))!
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// NSError (as an out parameter).
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
public typealias NSErrorPointer = AutoreleasingUnsafeMutablePointer<NSError?>?
|
|
|
|
// Note: NSErrorPointer becomes ErrorPointer in Swift 3.
|
|
public typealias ErrorPointer = NSErrorPointer
|
|
|
|
public // COMPILER_INTRINSIC
|
|
let _nilObjCError: Error = _GenericObjCError.nilError
|
|
|
|
@_silgen_name("swift_convertNSErrorToError")
|
|
public // COMPILER_INTRINSIC
|
|
func _convertNSErrorToError(_ error: NSError?) -> Error {
|
|
if let error = error {
|
|
return error
|
|
}
|
|
return _nilObjCError
|
|
}
|
|
|
|
@_silgen_name("swift_convertErrorToNSError")
|
|
public // COMPILER_INTRINSIC
|
|
func _convertErrorToNSError(_ error: Error) -> NSError {
|
|
return unsafeDowncast(_bridgeErrorToNSError(error), to: NSError.self)
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Variadic initializers and methods
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension NSPredicate {
|
|
// + (NSPredicate *)predicateWithFormat:(NSString *)predicateFormat, ...;
|
|
public
|
|
convenience init(format predicateFormat: String, _ args: CVarArg...) {
|
|
let va_args = getVaList(args)
|
|
self.init(format: predicateFormat, arguments: va_args)
|
|
}
|
|
}
|
|
|
|
extension NSExpression {
|
|
// + (NSExpression *) expressionWithFormat:(NSString *)expressionFormat, ...;
|
|
public
|
|
convenience init(format expressionFormat: String, _ args: CVarArg...) {
|
|
let va_args = getVaList(args)
|
|
self.init(format: expressionFormat, arguments: va_args)
|
|
}
|
|
}
|
|
|
|
extension NSString {
|
|
public convenience init(format: NSString, _ args: CVarArg...) {
|
|
// We can't use withVaList because 'self' cannot be captured by a closure
|
|
// before it has been initialized.
|
|
let va_args = getVaList(args)
|
|
self.init(format: format as String, arguments: va_args)
|
|
}
|
|
|
|
public convenience init(
|
|
format: NSString, locale: Locale?, _ args: CVarArg...
|
|
) {
|
|
// We can't use withVaList because 'self' cannot be captured by a closure
|
|
// before it has been initialized.
|
|
let va_args = getVaList(args)
|
|
self.init(format: format as String, locale: locale, arguments: va_args)
|
|
}
|
|
|
|
public class func localizedStringWithFormat(
|
|
_ format: NSString, _ args: CVarArg...
|
|
) -> Self {
|
|
return withVaList(args) {
|
|
self.init(format: format as String, locale: Locale.current, arguments: $0)
|
|
}
|
|
}
|
|
|
|
public func appendingFormat(_ format: NSString, _ args: CVarArg...)
|
|
-> NSString {
|
|
return withVaList(args) {
|
|
self.appending(NSString(format: format as String, arguments: $0) as String) as NSString
|
|
}
|
|
}
|
|
}
|
|
|
|
extension NSMutableString {
|
|
public func appendFormat(_ format: NSString, _ args: CVarArg...) {
|
|
return withVaList(args) {
|
|
self.append(NSString(format: format as String, arguments: $0) as String)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension NSArray {
|
|
// Overlay: - (instancetype)initWithObjects:(id)firstObj, ...
|
|
public convenience init(objects elements: Any...) {
|
|
self.init(array: elements)
|
|
}
|
|
}
|
|
|
|
extension NSOrderedSet {
|
|
// - (instancetype)initWithObjects:(id)firstObj, ...
|
|
public convenience init(objects elements: Any...) {
|
|
self.init(array: elements)
|
|
}
|
|
}
|
|
|
|
extension NSSet {
|
|
// - (instancetype)initWithObjects:(id)firstObj, ...
|
|
public convenience init(objects elements: Any...) {
|
|
self.init(array: elements)
|
|
}
|
|
}
|
|
|
|
extension NSSet : ExpressibleByArrayLiteral {
|
|
public required convenience init(arrayLiteral elements: Any...) {
|
|
self.init(array: elements)
|
|
}
|
|
}
|
|
|
|
extension NSOrderedSet : ExpressibleByArrayLiteral {
|
|
public required convenience init(arrayLiteral elements: Any...) {
|
|
self.init(array: elements)
|
|
}
|
|
}
|
|
|
|
//===--- "Copy constructors" ----------------------------------------------===//
|
|
// These are needed to make Cocoa feel natural since we eliminated
|
|
// implicit bridging conversions from Objective-C to Swift
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension NSArray {
|
|
/// Initializes a newly allocated array by placing in it the objects
|
|
/// contained in a given array.
|
|
///
|
|
/// - Returns: An array initialized to contain the objects in
|
|
/// `anArray``. The returned object might be different than the
|
|
/// original receiver.
|
|
///
|
|
/// Discussion: After an immutable array has been initialized in
|
|
/// this way, it cannot be modified.
|
|
@nonobjc
|
|
public convenience init(array anArray: NSArray) {
|
|
self.init(array: anArray as Array)
|
|
}
|
|
}
|
|
|
|
extension NSString {
|
|
/// Returns an `NSString` object initialized by copying the characters
|
|
/// from another given string.
|
|
///
|
|
/// - Returns: An `NSString` object initialized by copying the
|
|
/// characters from `aString`. The returned object may be different
|
|
/// from the original receiver.
|
|
@nonobjc
|
|
public convenience init(string aString: NSString) {
|
|
self.init(string: aString as String)
|
|
}
|
|
}
|
|
|
|
extension NSSet {
|
|
/// Initializes a newly allocated set and adds to it objects from
|
|
/// another given set.
|
|
///
|
|
/// - Returns: An initialized objects set containing the objects from
|
|
/// `set`. The returned set might be different than the original
|
|
/// receiver.
|
|
@nonobjc
|
|
public convenience init(set anSet: NSSet) {
|
|
// FIXME: This is a bit weird. Maybe there's a better way?
|
|
self.init(set: anSet as Set<NSObject> as Set<AnyHashable>)
|
|
}
|
|
}
|
|
|
|
extension NSDictionary {
|
|
/// Initializes a newly allocated dictionary and adds to it objects from
|
|
/// another given dictionary.
|
|
///
|
|
/// - Returns: An initialized dictionary—which might be different
|
|
/// than the original receiver—containing the keys and values
|
|
/// found in `otherDictionary`.
|
|
@objc(_swiftInitWithDictionary_NSDictionary:)
|
|
public convenience init(dictionary otherDictionary: NSDictionary) {
|
|
// FIXME: This is a bit weird. Maybe there's a better way?
|
|
self.init(dictionary: otherDictionary as [NSObject: AnyObject]
|
|
as [AnyHashable: Any])
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// NSUndoManager
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@_silgen_name("NS_Swift_NSUndoManager_registerUndoWithTargetHandler")
|
|
internal func NS_Swift_NSUndoManager_registerUndoWithTargetHandler(
|
|
_ self_: AnyObject,
|
|
_ target: AnyObject,
|
|
_ handler: @escaping @convention(block) (AnyObject) -> Void)
|
|
|
|
extension UndoManager {
|
|
@available(*, unavailable, renamed: "registerUndo(withTarget:handler:)")
|
|
public func registerUndoWithTarget<TargetType : AnyObject>(_ target: TargetType, handler: (TargetType) -> Void) {
|
|
fatalError("This API has been renamed")
|
|
}
|
|
|
|
@available(OSX 10.11, iOS 9.0, *)
|
|
public func registerUndo<TargetType : AnyObject>(withTarget target: TargetType, handler: @escaping (TargetType) -> Void) {
|
|
// The generic blocks use a different ABI, so we need to wrap the provided
|
|
// handler in something ObjC compatible.
|
|
let objcCompatibleHandler: (AnyObject) -> Void = { internalTarget in
|
|
handler(internalTarget as! TargetType)
|
|
}
|
|
NS_Swift_NSUndoManager_registerUndoWithTargetHandler(
|
|
self as AnyObject, target as AnyObject, objcCompatibleHandler)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// NSCoder
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@_silgen_name("NS_Swift_NSCoder_decodeObject")
|
|
internal func NS_Swift_NSCoder_decodeObject(
|
|
_ self_: AnyObject,
|
|
_ error: NSErrorPointer) -> AnyObject?
|
|
|
|
@_silgen_name("NS_Swift_NSCoder_decodeObjectForKey")
|
|
internal func NS_Swift_NSCoder_decodeObjectForKey(
|
|
_ self_: AnyObject,
|
|
_ key: AnyObject,
|
|
_ error: NSErrorPointer) -> AnyObject?
|
|
|
|
@_silgen_name("NS_Swift_NSCoder_decodeObjectOfClassForKey")
|
|
internal func NS_Swift_NSCoder_decodeObjectOfClassForKey(
|
|
_ self_: AnyObject,
|
|
_ cls: AnyObject,
|
|
_ key: AnyObject,
|
|
_ error: NSErrorPointer) -> AnyObject?
|
|
|
|
@_silgen_name("NS_Swift_NSCoder_decodeObjectOfClassesForKey")
|
|
internal func NS_Swift_NSCoder_decodeObjectOfClassesForKey(
|
|
_ self_: AnyObject,
|
|
_ classes: NSSet?,
|
|
_ key: AnyObject,
|
|
_ error: NSErrorPointer) -> AnyObject?
|
|
|
|
|
|
@available(OSX 10.11, iOS 9.0, *)
|
|
internal func resolveError(_ error: NSError?) throws {
|
|
if let error = error, error.code != NSCoderValueNotFoundError {
|
|
throw error
|
|
}
|
|
}
|
|
|
|
extension NSCoder {
|
|
@available(*, unavailable, renamed: "decodeObject(of:forKey:)")
|
|
public func decodeObjectOfClass<DecodedObjectType>(
|
|
_ cls: DecodedObjectType.Type, forKey key: String
|
|
) -> DecodedObjectType?
|
|
where DecodedObjectType : NSCoding, DecodedObjectType : NSObject {
|
|
fatalError("This API has been renamed")
|
|
}
|
|
|
|
public func decodeObject<DecodedObjectType>(
|
|
of cls: DecodedObjectType.Type, forKey key: String
|
|
) -> DecodedObjectType?
|
|
where DecodedObjectType : NSCoding, DecodedObjectType : NSObject {
|
|
let result = NS_Swift_NSCoder_decodeObjectOfClassForKey(self as AnyObject, cls as AnyObject, key as AnyObject, nil)
|
|
return result as? DecodedObjectType
|
|
}
|
|
|
|
@available(*, unavailable, renamed: "decodeObject(of:forKey:)")
|
|
@nonobjc
|
|
public func decodeObjectOfClasses(_ classes: NSSet?, forKey key: String) -> AnyObject? {
|
|
fatalError("This API has been renamed")
|
|
}
|
|
|
|
@nonobjc
|
|
public func decodeObject(of classes: [AnyClass]?, forKey key: String) -> Any? {
|
|
var classesAsNSObjects: NSSet? = nil
|
|
if let theClasses = classes {
|
|
classesAsNSObjects = NSSet(array: theClasses.map { $0 as AnyObject })
|
|
}
|
|
return NS_Swift_NSCoder_decodeObjectOfClassesForKey(self as AnyObject, classesAsNSObjects, key as AnyObject, nil).map { $0 as Any }
|
|
}
|
|
|
|
@nonobjc
|
|
@available(OSX 10.11, iOS 9.0, *)
|
|
public func decodeTopLevelObject() throws -> Any? {
|
|
var error: NSError?
|
|
let result = NS_Swift_NSCoder_decodeObject(self as AnyObject, &error)
|
|
try resolveError(error)
|
|
return result.map { $0 as Any }
|
|
}
|
|
|
|
@available(*, unavailable, renamed: "decodeTopLevelObject(forKey:)")
|
|
public func decodeTopLevelObjectForKey(_ key: String) throws -> AnyObject? {
|
|
fatalError("This API has been renamed")
|
|
}
|
|
|
|
@nonobjc
|
|
@available(OSX 10.11, iOS 9.0, *)
|
|
public func decodeTopLevelObject(forKey key: String) throws -> AnyObject? {
|
|
var error: NSError?
|
|
let result = NS_Swift_NSCoder_decodeObjectForKey(self as AnyObject, key as AnyObject, &error)
|
|
try resolveError(error)
|
|
return result
|
|
}
|
|
|
|
@available(*, unavailable, renamed: "decodeTopLevelObject(of:forKey:)")
|
|
public func decodeTopLevelObjectOfClass<DecodedObjectType>(
|
|
_ cls: DecodedObjectType.Type, forKey key: String
|
|
) throws -> DecodedObjectType?
|
|
where DecodedObjectType : NSCoding, DecodedObjectType : NSObject {
|
|
fatalError("This API has been renamed")
|
|
}
|
|
|
|
@available(OSX 10.11, iOS 9.0, *)
|
|
public func decodeTopLevelObject<DecodedObjectType>(
|
|
of cls: DecodedObjectType.Type, forKey key: String
|
|
) throws -> DecodedObjectType?
|
|
where DecodedObjectType : NSCoding, DecodedObjectType : NSObject {
|
|
var error: NSError?
|
|
let result = NS_Swift_NSCoder_decodeObjectOfClassForKey(self as AnyObject, cls as AnyObject, key as AnyObject, &error)
|
|
try resolveError(error)
|
|
return result as? DecodedObjectType
|
|
}
|
|
|
|
@nonobjc
|
|
@available(*, unavailable, renamed: "decodeTopLevelObject(of:forKey:)")
|
|
public func decodeTopLevelObjectOfClasses(_ classes: NSSet?, forKey key: String) throws -> AnyObject? {
|
|
fatalError("This API has been renamed")
|
|
}
|
|
|
|
@nonobjc
|
|
@available(OSX 10.11, iOS 9.0, *)
|
|
public func decodeTopLevelObject(of classes: [AnyClass]?, forKey key: String) throws -> Any? {
|
|
var error: NSError? = nil
|
|
var classesAsNSObjects: NSSet? = nil
|
|
if let theClasses = classes {
|
|
classesAsNSObjects = NSSet(array: theClasses.map { $0 as AnyObject })
|
|
}
|
|
let result = NS_Swift_NSCoder_decodeObjectOfClassesForKey(self as AnyObject, classesAsNSObjects, key as AnyObject, &error)
|
|
try resolveError(error)
|
|
return result.map { $0 as Any }
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// NSKeyedUnarchiver
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@_silgen_name("NS_Swift_NSKeyedUnarchiver_unarchiveObjectWithData")
|
|
internal func NS_Swift_NSKeyedUnarchiver_unarchiveObjectWithData(
|
|
_ self_: AnyObject,
|
|
_ data: AnyObject,
|
|
_ error: NSErrorPointer) -> AnyObject?
|
|
|
|
extension NSKeyedUnarchiver {
|
|
@available(OSX 10.11, iOS 9.0, *)
|
|
@nonobjc
|
|
public class func unarchiveTopLevelObjectWithData(_ data: NSData) throws -> AnyObject? {
|
|
var error: NSError?
|
|
let result = NS_Swift_NSKeyedUnarchiver_unarchiveObjectWithData(self, data as AnyObject, &error)
|
|
try resolveError(error)
|
|
return result
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Mirror/Quick Look Conformance
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension NSURL : CustomPlaygroundQuickLookable {
|
|
public var customPlaygroundQuickLook: PlaygroundQuickLook {
|
|
guard let str = absoluteString else { return .text("Unknown URL") }
|
|
return .url(str)
|
|
}
|
|
}
|
|
|
|
extension NSRange : CustomReflectable {
|
|
public var customMirror: Mirror {
|
|
return Mirror(self, children: ["location": location, "length": length])
|
|
}
|
|
}
|
|
|
|
extension NSRange : CustomPlaygroundQuickLookable {
|
|
public var customPlaygroundQuickLook: PlaygroundQuickLook {
|
|
return .range(Int64(location), Int64(length))
|
|
}
|
|
}
|
|
|
|
extension NSDate : CustomPlaygroundQuickLookable {
|
|
var summary: String {
|
|
let df = DateFormatter()
|
|
df.dateStyle = .medium
|
|
df.timeStyle = .short
|
|
return df.string(from: self as Date)
|
|
}
|
|
|
|
public var customPlaygroundQuickLook: PlaygroundQuickLook {
|
|
return .text(summary)
|
|
}
|
|
}
|
|
|
|
extension NSSet : CustomReflectable {
|
|
public var customMirror: Mirror {
|
|
return Mirror(reflecting: self as Set<NSObject>)
|
|
}
|
|
}
|
|
|
|
extension NSString : CustomPlaygroundQuickLookable {
|
|
public var customPlaygroundQuickLook: PlaygroundQuickLook {
|
|
return .text(self as String)
|
|
}
|
|
}
|
|
|
|
extension NSArray : CustomReflectable {
|
|
public var customMirror: Mirror {
|
|
return Mirror(reflecting: self as [AnyObject])
|
|
}
|
|
}
|
|
|
|
extension NSDictionary : CustomReflectable {
|
|
public var customMirror: Mirror {
|
|
return Mirror(reflecting: self as [NSObject : AnyObject])
|
|
}
|
|
}
|
|
|
|
@available(*, deprecated, renamed:"NSCoding", message: "Please use NSCoding")
|
|
typealias Coding = NSCoding
|
|
|
|
@available(*, deprecated, renamed:"NSCoder", message: "Please use NSCoder")
|
|
typealias Coder = NSCoder
|
|
|
|
@available(*, deprecated, renamed:"NSKeyedUnarchiver", message: "Please use NSKeyedUnarchiver")
|
|
typealias KeyedUnarchiver = NSKeyedUnarchiver
|
|
|
|
@available(*, deprecated, renamed:"NSKeyedArchiver", message: "Please use NSKeyedArchiver")
|
|
typealias KeyedArchiver = NSKeyedArchiver
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// AnyHashable
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension AnyHashable : _ObjectiveCBridgeable {
|
|
public func _bridgeToObjectiveC() -> NSObject {
|
|
// This is unprincipled, but pretty much any object we'll encounter in
|
|
// Swift is NSObject-conforming enough to have -hash and -isEqual:.
|
|
return unsafeBitCast(base as AnyObject, to: NSObject.self)
|
|
}
|
|
|
|
public static func _forceBridgeFromObjectiveC(
|
|
_ x: NSObject,
|
|
result: inout AnyHashable?
|
|
) {
|
|
result = AnyHashable(x)
|
|
}
|
|
|
|
public static func _conditionallyBridgeFromObjectiveC(
|
|
_ x: NSObject,
|
|
result: inout AnyHashable?
|
|
) -> Bool {
|
|
self._forceBridgeFromObjectiveC(x, result: &result)
|
|
return result != nil
|
|
}
|
|
|
|
public static func _unconditionallyBridgeFromObjectiveC(
|
|
_ source: NSObject?
|
|
) -> AnyHashable {
|
|
// `nil` has historically been used as a stand-in for an empty
|
|
// string; map it to an empty string.
|
|
if _slowPath(source == nil) { return AnyHashable(String()) }
|
|
return AnyHashable(source!)
|
|
}
|
|
}
|
|
|