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)
我找到了一个可行的、优雅的解决方案,可以与;_ObjectiveCBridgeable struct一起使用 NSCoder感谢Martin R提供的参考资料。这是我为感兴趣的人编写的库代码。我现在可以做这样的事情:
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}\nRun Code Online (Sandbox Code Playgroud)\n\nSortedArray.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}\nRun Code Online (Sandbox Code Playgroud)\n\nNSSortedArray.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
| 归档时间: |
|
| 查看次数: |
520 次 |
| 最近记录: |