定义在Swift中被视为类的结构

Noo*_*ath 8 struct bridge class swift

在Swift中,String结构也被视为类对象,就像使用该NSCoder encodeObject(_:forKey:)方法一样.我知道它String直接与objective-c类桥接NSString,但是有没有办法使自定义struct行为类似?也许将它连接到一个自定义类?我希望能够做到这样的事情:

struct SortedArray <Value: Comparable> {}

// Would I need to create a bridge between 
// SortedArray and NSSortedArray? Can I even do that?
class NSSortedArray <Value: Comparable> : NSObject, NSCoding {
    required init?(coder aDecoder: NSCoder) {}
    func encodeWithCoder(aCoder: NSCoder) {}
}

class MyClass : NSObject, NSCoding {
    private var objects: SortedArray<String> = SortedArray<String>()
    required init?(coder aDecoder: NSCoder) {
        guard let objects = aDecoder.decodeObjectForKey("objects") as? SortedArray<String> else { return nil }
        self.objects = objects
    }
    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(objects, forKey: "objects")
    }
}
Run Code Online (Sandbox Code Playgroud)

Noo*_*ath 1

我找到了一个可行的、优雅的解决方案,可以与;_ObjectiveCBridgeable struct一起使用 NSCoder感谢Martin R提供的参考资料。这是我为感兴趣的人编写的库代码。我现在可以做这样的事情:

\n\n
func init?(coder aDecoder: NSCoder) {\n    guard let numbers = aDecoder.decodeObjectForKey("Numbers") as? SortedArray<Int> else { return nil }\n    print(numbers) // Outputs "[1,3,5]"\n}\n\nfunc encodeWithCoder(aCoder: NSCoder) {\n    aCoder.encodeObject(SortedArray<Int>([1,5,3]), forKey: "Numbers")\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

SortedArray.swift

\n\n
//\n//  SortedArray.swift\n//  NoodleKit\n//\n//  Created by Thom Morgan on 8/15/16.\n//  Copyright \xc2\xa9 2016 CocoaPods. All rights reserved.\n//\n\n// MARK: - ** Import Modules **\n\nimport Foundation\n\n// MARK: - ** SortOrder Enumeration **\n\n/// Ascending or descending sort order enumerations\npublic enum SortOrder : Int {\n    case Ascending, Descending\n}\n\n// MARK: - ** SortedArray Structure **\n\n/// An array data structure that automatically places elements in order as\n/// they added to the collection.\npublic struct SortedArray <Value: Comparable> : CollectionType, _ObjectiveCBridgeable, CustomStringConvertible {\n\n    // MARK: - _ObjectiveCBridgeable\n\n    /// Required typealias from the `_ObjectiveCBridgeable` private protocol\n    public typealias _ObjectiveCType = NSSortedArray<Value>\n\n    // MARK: - CollectionType\n\n    public typealias Index = Int\n    public typealias Generator = IndexingGenerator<SortedArray<Value>>\n\n    public var startIndex: Index { return 0 }\n    public var endIndex: Index { return values.count }\n    public var range: Range<Index> { return 0 ..< values.count }\n    public var count: Int { return values.count }\n\n    // MARK: - CustomStringConvertible\n\n    public var description: String { return "\\(values)" }\n\n    // MARK: - SortedArray\n\n    /// The order in which to sort array elements.\n    public var sortOrder: SortOrder {\n        willSet { if sortOrder != newValue { values = values.reverse() } }\n    }\n\n    /// The elements of this array.\n    public private (set) var values = [Value]()\n\n    /// Whether or not to allow duplicate elements to be added to this array.\n    public var uniqueElements: Bool = true\n\n    // MARK: - ** Constructor Methods **\n\n    // MARK: - SortedArray\n\n    /// Verbose constructor in which the sort order can be established at\n    /// initialization.\n    /// - parameter sortOrder: The order in which to sort array elements.\n    /// - parameter values: The initial elements to populate this array. \n    /// - note: The initial values parameter need not be sorted, as it will\n    /// automatically be sorted upon initialization.\n    /// - returns: An array structure instance with sorted values.\n    public init(sortOrder: SortOrder = .Ascending, values: [Value] = [Value]()) {\n        self.sortOrder = sortOrder\n        self.values = values.sort({ (a: Value, b: Value) -> Bool in\n            return sortOrder == .Ascending ? (a < b) : (b < a)\n        })\n    }\n\n    /// Convenience constructor that sets the inital array elements.\n    /// - parameter values: The initial elements to populate this array.\n    /// - returns: An array structure instance with sorted values in \n    /// ascending order.\n    public init(_ values: [Value]) {\n        sortOrder = .Ascending\n        self.values = values.sort({ (a: Value, b: Value) -> Bool in\n            return a < b\n        })\n    }\n\n    /// Duplicating constructor.\n    /// - parameter sortedArray: Another array to initialize from.\n    /// - returns: An array structure instance with sorted values\n    /// identical to `sortedArray`.\n    public init(_ sortedArray: SortedArray<Value>) {\n        sortOrder = sortedArray.sortOrder\n        values = sortedArray.values\n    }\n\n    /// Bridging constructor from an `NSSortedArray` class instance.\n    /// - parameter sortedArray: Another array to initialize from.\n    /// - returns: An array structure instance with sorted values\n    /// identical to `sortedArray`.\n    public init(_ sortedArray: NSSortedArray<Value>) {\n        sortOrder = sortedArray.sortOrder\n        values = sortedArray.values\n    }\n\n    // MARK: - ** Public Methods **\n\n    // MARK: - _ObjectiveCBridgeable\n\n    /// Required static method from the `_ObjectiveCBridgeable` private \n    /// protocol.\n    /// - returns: `true`, indicating that this structure is bridgeable to\n    /// an Objective-C class, namely `NSSortedArray`.\n    public static func _isBridgedToObjectiveC() -> Bool {\n        return true\n    }\n\n    /// Required static method from the `_ObjectiveCBridgeable` private\n    /// protocol.\n    /// - returns: `NSSortedArray<Value>.self`\n    public static func _getObjectiveCType() -> Any.Type {\n        return _ObjectiveCType.self\n    }\n\n    /// Required static method from the `_ObjectiveCBridgeable` private\n    /// protocol.\n    /// - parameter source: An `NSSortedArray<Value>` instance to force bridge\n    /// to `SortedArray<Value>`.\n    /// - parameter result: The `SortedArray<Value>` instance created from\n    /// the forced bridging.\n    public static func _forceBridgeFromObjectiveC(source: _ObjectiveCType, inout result: SortedArray<Value>?) {\n        result = SortedArray<Value>(source)\n    }\n\n    /// Required static method from the `_ObjectiveCBridgeable` private\n    /// protocol.\n    /// - parameter source: An `NSSortedArray<Value>` instance to conditionally\n    /// bridge to `SortedArray<Value>`.\n    /// - parameter result: The `SortedArray<Value>` instance created from\n    /// the conditional bridging.\n    public static func _conditionallyBridgeFromObjectiveC(source: _ObjectiveCType, inout result: SortedArray<Value>?) -> Bool {\n        _forceBridgeFromObjectiveC(source, result: &result)\n        return true\n    }\n\n    /// Required method from the `_ObjectiveCBridgeable` private protocol\n    /// - returns: An `NSStortedArray<Value>` instance identical to `self`.\n    public func _bridgeToObjectiveC() -> _ObjectiveCType {\n        return NSSortedArray<Value>(self)\n    }\n\n    // MARK: - CollectionType\n\n    public subscript (index: Index) -> Value {\n        get { return values[index] }\n        set { values[index] = newValue }\n    }\n\n    public func generate() -> Generator {\n        return Generator(SortedArray(values: values))\n    }\n\n    /// Insert `newElement` at index `i`.\n    ///\n    /// - requires: `i <= count`.\n    ///\n    /// - complexity: O(`self.count`).\n    public mutating func insert(value: Value, atIndex index: Index) {\n        values.insert(value, atIndex: index)\n    }\n\n    /// Remove and return the element at index `i`.\n    ///\n    /// Invalidates all indices with respect to `self`.\n    ///\n    /// - complexity: O(`self.count`).\n    public mutating func removeAtIndex(index: Index) -> Value {\n        return values.removeAtIndex(index)\n    }\n\n    /// Remove all elements.\n    ///\n    /// - postcondition: `capacity == 0` iff `keepCapacity` is `false`.\n    ///\n    /// - complexity: O(`self.count`).    \n    public mutating func removeAll() {\n        values.removeAll()\n    }\n\n    // MARK: - SortedArray\n\n    /// Returns the first index where `value` appears in `self` or `nil` if\n    /// `value` is not found.\n    ///\n    /// - note: This is a significantly less costly implementation of the\n    /// default system method `indexOf(element: Element)`.\n    ///\n    /// - complexity: O(`log(self.count)`)\n    ///\n    /// - parameter value: The value to search for\n    /// - parameter range: The range to search within. If `nil` the entire\n    /// range of elements are searched.\n    /// - returns: The first index where `value` appears in `self` or `nil` if\n    /// `value` is not found.\n    @warn_unused_result\n    public func indexOf(value: Value, searchRange range: Range<Index>? = nil) -> Index? {\n\n        if values.count == 0 { return nil }\n\n        let range = range ?? 0 ..< values.count\n        let index = (range.startIndex + range.length / 2)\n        let val = values[index]\n\n        if range.length == 1 {\n            return val == value ? index : nil\n        } else if (val > value && sortOrder == .Ascending) || (val < value && sortOrder == .Descending) {\n            return indexOf(value, searchRange: range.startIndex ..< index)\n        }\n\n        return indexOf(value, searchRange: index ..< range.endIndex)\n\n    }\n\n    /// Returns the first index where `value` would be placed in sorted order\n    /// in `self`.\n    ///\n    /// - complexity: O(`log(self.count)`)\n    ///\n    /// - parameter value: The value to search for.\n    /// - parameter range: The range to search within. If `nil` the entire\n    /// range of elements are searched.\n    /// - returns: Returns the first index where `value` would be placed\n    /// in sorted order.\n    @warn_unused_result\n    public func ordinalIndexForValue(value: Value, searchRange range: Range<Index>? = nil) -> Index {\n\n        if values.count == 0 { return 0 }\n\n        let range = range ?? 0 ..< values.count\n        let index = (range.startIndex + range.length / 2)\n        let val = values[index]\n\n        if range.length == 1 {\n            return (val > value && sortOrder == .Ascending) || (val < value && sortOrder == .Descending) ? index : index + 1\n        } else if (val > value && sortOrder == .Ascending) || (val < value && sortOrder == .Descending) {\n            return ordinalIndexForValue(value, searchRange: range.startIndex ..< index)\n        }\n\n        return ordinalIndexForValue(value, searchRange: index ..< range.endIndex)\n\n    }\n\n    /// Adds a value to `self` in sorted order.\n    /// - parameter value: The value to add.\n    /// - returns: The index where `value` was inserted, or `nil` if\n    /// `uniqueElements` is set to `true` and `value` already exists in\n    /// `self.\n    ///\n    /// - complexity: O(`log(self.count)`)\n    public mutating func add(value: Value) -> Index? {\n        var index = 0\n        if values.count == 0 { values.append(value) }\n        else {\n            if uniqueElements && indexOf(value) != nil { return nil }\n            index = ordinalIndexForValue(value)\n            values.insert(value, atIndex: index)\n        }\n        return index\n    }\n\n    /// Removes all instances of `value` from `self`\n    /// - parameter value: The `value` to remove from `self`.\n    ///\n    /// - complexity: O(`log(self.count) * n`) where `n` is the number of\n    /// times `value` occurs in `self`.\n    public mutating func remove(value: Value){\n        var index = indexOf(value)\n        while index != nil {\n            values.removeAtIndex(index!)\n            index = indexOf(value)\n        }\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

NSSortedArray.swift

\n\n
//\n//  NSSortedArray.swift\n//  NoodleKit\n//\n//  Created by Thom Morgan on 6/29/16.\n//  Copyright \xc2\xa9 2016 NoodleOfDeath. All rights reserved.\n//\n\n// MARK: - ** Import Modules **\n\nimport Foundation\n\nprivate struct CodingKeys {\n    static let SortOrder = "SortOrder"\n    static let Values = "Values"\n}\n\n// MARK: - ** NSSortedArray Class **\n\n/// An array class that automatically places elements in order as\n/// they added to the collection.\npublic class NSSortedArray <Value: Comparable> : NSObject, CollectionType, NSCoding {\n\n    // MARK: - CollectionType\n\n    public typealias Index = Int\n    public typealias Generator = IndexingGenerator<NSSortedArray<Value>>\n\n    public var startIndex: Index { return 0 }\n    public var endIndex: Index { return values.count }\n    public var range: Range<Index> { return 0 ..< values.count }\n    public var count: Int { return values.count }\n\n    // MARK: - CustomStringConvertible\n\n    public override var description: String { return "\\(values)" }\n\n    // MARK: - NSSortedArray\n\n    /// The order in which to sort array elements.\n    public var sortOrder: SortOrder {\n        willSet { if sortOrder != newValue { values = values.reverse() } }\n    }\n\n    /// The elements of this array.\n    public private (set) var values = [Value]()\n\n    /// Whether or not to allow duplicate elements to be added to this array.\n    public var uniqueElements: Bool = true\n\n    // MARK: - ** Constructor Methods **\n\n    // MARK: - NSSortedArray\n\n    /// Verbose constructor in which the sort order can be established at\n    /// initialization.\n    /// - parameter sortOrder: The order in which to sort array elements.\n    /// - parameter values: The initial elements to populate this array.\n    /// - note: The initial values parameter need not be sorted, as it will\n    /// automatically be sorted upon initialization.\n    /// - returns: An array structure instance with sorted values.\n    public init(sortOrder: SortOrder = .Ascending, values: [Value] = [Value]()) {\n        self.sortOrder = sortOrder\n        self.values = values.sort({ (a: Value, b: Value) -> Bool in\n            return sortOrder == .Ascending ? (a < b) : (b < a)\n        })\n    }\n\n    /// Convenience constructor that sets the inital array elements.\n    /// - parameter values: The initial elements to populate this array.\n    /// - returns: An array structure instance with sorted values in\n    /// ascending order.\n    public init(_ values: [Value]) {\n        sortOrder = .Ascending\n        self.values = values.sort({ (a: Value, b: Value) -> Bool in\n            return a < b\n        })\n    }\n\n    /// Duplicating constructor.\n    /// - parameter sortedArray: Another array to initialize from.\n    /// - returns: An array structure instance with sorted values\n    /// identical to `sortedArray`.\n    public init(_ sortedArray: NSSortedArray<Value>) {\n        sortOrder = sortedArray.sortOrder\n        values = sortedArray.values\n    }\n\n    /// Bridging constructor from a `SortedArray` structure instance.\n    /// - parameter sortedArray: Another array to initialize from.\n    /// - returns: An array class instance with sorted values\n    /// identical to `sortedArray`.\n    public init(_ sortedArray: SortedArray<Value>) {\n        sortOrder = sortedArray.sortOrder\n        values = sortedArray.values\n    }\n\n    // MARK: - NSCoding\n\n    public convenience required init?(coder aDecoder: NSCoder) {\n        guard let sortOrder = SortOrder(rawValue: aDecoder.decodeIntegerForKey(CodingKeys.SortOrder)) else { return nil }\n        guard let values = aDecoder.decodeObjectForKey(CodingKeys.Values) as? [Value] else { return nil }\n        self.init(sortOrder: sortOrder, values: values)\n    }\n\n    public func encodeWithCoder(aCoder: NSCoder) {\n        aCoder.encodeInteger(sortOrder.rawValue, forKey: CodingKeys.SortOrder)\n        aCoder.encodeObject(values, forKey: CodingKeys.Values)\n    }\n\n    // MARK: - CollectionType\n\n    public subscript (index: Index) -> Value {\n        get { return values[index] }\n        set { values[index] = newValue }\n    }\n\n    public func generate() -> Generator {\n        return Generator(NSSortedArray(values: values))\n    }\n\n    /// Insert `newElement` at index `i`.\n    ///\n    /// - requires: `i <= count`.\n    ///\n    /// - complexity: O(`self.count`).\n    public func insert(value: Value, atIndex index: Index) {\n        values.insert(value, atIndex: index)\n    }\n\n    /// Remove and return the element at index `i`.\n    ///\n    /// Invalidates all indices with respect to `self`.\n    ///\n    /// - complexity: O(`self.count`).\n    public func removeAtIndex(index: Index) -> Value {\n        return values.removeAtIndex(index)\n    }\n\n    /// Remove all elements.\n    ///\n    /// - postcondition: `capacity == 0` iff `keepCapacity` is `false`.\n    ///\n    /// - complexity: O(`self.count`).\n    public func removeAll(keepCapacity keepCapacity: Bool = false) {\n        values.removeAll(keepCapacity: keepCapacity)\n    }\n\n    // MARK: - NSSortedArray\n\n    /// Returns the first index where `value` appears in `self` or `nil` if\n    /// `value` is not found.\n    ///\n    /// - note: This is a significantly less costly implementation of the\n    /// default system method `indexOf(element: Element)`.\n    ///\n    /// - complexity: O(`log(self.count)`)\n    ///\n    /// - parameter value: The value to search for.\n    /// - parameter range: The range to search within. If `nil` the entire\n    /// range of elements are searched.\n    /// - returns: The first index where `value` appears in `self` or `nil` if\n    /// `value` is not found.\n    @warn_unused_result\n    public func indexOf(value: Value, searchRange range: Range<Index>? = nil) -> Index? {\n\n        if values.count == 0 { return nil }\n\n        let range = range ?? 0 ..< values.count\n        let index = (range.startIndex + range.length / 2)\n        let val = values[index]\n\n        if range.length == 1 {\n            return val == value ? index : nil\n        } else if (val > value && sortOrder == .Ascending) || (val < value && sortOrder == .Descending) {\n            return indexOf(value, searchRange: range.startIndex ..< index)\n        }\n\n        return indexOf(value, searchRange: index ..< range.endIndex)\n\n    }\n\n    /// Returns the first index where `value` would be placed in sorted order\n    /// in `self`.\n    ///\n    /// - complexity: O(`log(self.count)`)\n    ///\n    /// - parameter value: The value to search for.\n    /// - parameter range: The range to search within. If `nil` the entire\n    /// range of elements are searched.\n    /// - returns: The first index where `value` would be placed in sorted\n    /// order in `self`.\n    @warn_unused_result\n    public func ordinalIndexForValue(value: Value, searchRange range: Range<Index>? = nil) -> Index {\n\n        if values.count == 0 { return 0 }\n\n        let range = range ?? 0 ..< values.count\n        let index = (range.startIndex + range.length / 2)\n        let val = values[index]\n\n        if range.length == 1 {\n            return (val > value && sortOrder == .Ascending) || (val < value && sortOrder == .Descending) ? index : index + 1\n        } else if (val > value && sortOrder == .Ascending) || (val < value && sortOrder == .Descending) {\n            return ordinalIndexForValue(value, searchRange: range.startIndex ..< index)\n        }\n\n        return ordinalIndexForValue(value, searchRange: index ..< range.endIndex)\n\n    }\n\n    /// Adds a value to `self` in sorted order.\n    /// - parameter value: The value to add.\n    /// - returns: The index where `value` was inserted, or `nil` if\n    /// `uniqueElements` is set to `true` and `value` already exists in\n    /// `self.\n    ///\n    /// - complexity: O(`log(self.count)`)\n    public func add(value: Value) -> Index? {\n        var index = 0\n        if values.count == 0 { values.append(value) }\n        else {\n            if uniqueElements && indexOf(value) != nil { return nil }\n            index = ordinalIndexForValue(value)\n            values.insert(value, atIndex: index)\n        }\n        return index\n    }\n\n    /// Removes all instances of `value` from `self`\n    /// - parameter value: The `value` to rem