Skip to content

Commit 1f4d172

Browse files
committed
Parity: NSMeasurement, NSObject class methods
- Implement NSMeasurement - Implement NSObject’s .isKind(of:), .isMember(of:), .isSubclass(of:) and .superclass.
1 parent 049b8d4 commit 1f4d172

File tree

2 files changed

+109
-10
lines changed

2 files changed

+109
-10
lines changed

Foundation/NSMeasurement.swift

+56-10
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,74 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
1413
open class NSMeasurement : NSObject, NSCopying, NSSecureCoding {
1514
open private(set) var unit: Unit
1615
open private(set) var doubleValue: Double
1716

18-
@available(*, unavailable)
19-
public convenience override init() { fatalError("Measurements must be constructed with a value and unit") }
20-
2117
public init(doubleValue: Double, unit: Unit) {
22-
self.doubleValue = doubleValue
2318
self.unit = unit
19+
self.doubleValue = doubleValue
2420
}
2521

26-
open func canBeConverted(to unit: Unit) -> Bool { NSUnimplemented() }
22+
open func canBeConverted(to unit: Unit) -> Bool {
23+
return self.unit is Dimension && unit is Dimension && type(of: unit).isSubclass(of: type(of: self.unit))
24+
}
2725

28-
open func converting(to unit: Unit) -> Measurement<Unit> { NSUnimplemented() }
26+
open func converting(to otherUnit: Unit) -> Measurement<Unit> {
27+
precondition(canBeConverted(to: otherUnit))
28+
29+
if unit.isEqual(otherUnit) {
30+
return Measurement(value: doubleValue, unit: otherUnit)
31+
} else {
32+
let dimensionUnit = unit as! Dimension
33+
34+
let valueInTermsOfBase = dimensionUnit.converter.baseUnitValue(fromValue: doubleValue)
35+
if otherUnit.isEqual(type(of: dimensionUnit).baseUnit()) {
36+
return Measurement(value: valueInTermsOfBase, unit: otherUnit)
37+
} else {
38+
let otherDimensionUnit = otherUnit as! Dimension
39+
40+
let otherValueFromTermsOfBase = otherDimensionUnit.converter.value(fromBaseUnitValue: valueInTermsOfBase)
41+
return Measurement(value: otherValueFromTermsOfBase, unit: otherUnit)
42+
}
43+
}
44+
}
2945

30-
open func adding(_ measurement: Measurement<Unit>) -> Measurement<Unit> { NSUnimplemented() }
46+
open func adding(_ rhs: Measurement<Unit>) -> Measurement<Unit> {
47+
precondition(unit is Dimension)
48+
precondition(rhs.unit is Dimension)
49+
50+
let dimensionUnit = unit as! Dimension
51+
let rhsDimensionUnit = rhs.unit as! Dimension
52+
53+
if unit.isEqual(rhs.unit) {
54+
return Measurement(value: doubleValue + rhs.value, unit: unit)
55+
} else {
56+
let lhsValueInTermsOfBase = dimensionUnit.converter.baseUnitValue(fromValue: doubleValue)
57+
let rhsValueInTermsOfBase = rhsDimensionUnit.converter.baseUnitValue(fromValue: rhs.value)
58+
return Measurement(value: lhsValueInTermsOfBase + rhsValueInTermsOfBase, unit: type(of: dimensionUnit).baseUnit())
59+
}
60+
}
3161

32-
open func subtracting(_ measurement: Measurement<Unit>) -> Measurement<Unit> { NSUnimplemented() }
62+
open func subtracting(_ rhs: Measurement<Unit>) -> Measurement<Unit> {
63+
precondition(unit is Dimension)
64+
precondition(rhs.unit is Dimension)
65+
66+
let dimensionUnit = unit as! Dimension
67+
let rhsDimensionUnit = rhs.unit as! Dimension
68+
69+
if unit.isEqual(rhs.unit) {
70+
return Measurement(value: doubleValue - rhs.value, unit: unit)
71+
} else {
72+
let lhsValueInTermsOfBase = dimensionUnit.converter.baseUnitValue(fromValue: doubleValue)
73+
let rhsValueInTermsOfBase = rhsDimensionUnit.converter.baseUnitValue(fromValue: rhs.value)
74+
return Measurement(value: lhsValueInTermsOfBase - rhsValueInTermsOfBase, unit: type(of: dimensionUnit).baseUnit())
75+
}
76+
}
3377

34-
open func copy(with zone: NSZone? = nil) -> Any { NSUnimplemented() }
78+
open func copy(with zone: NSZone? = nil) -> Any {
79+
return self
80+
}
3581

3682
open class var supportsSecureCoding: Bool { return true }
3783

Foundation/NSObject.swift

+53
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212
// This brings it into line with Darwin usage for compatibility.
1313
@_exported import Dispatch
1414

15+
#if canImport(ObjectiveC)
16+
import ObjectiveC
17+
#else
18+
@_silgen_name("_swift_class_getSuperclass")
19+
internal func _swift_class_getSuperclass(_ t: AnyClass) -> AnyClass?
20+
#endif
21+
1522
import CoreFoundation
1623

1724
/// The `NSObjectProtocol` groups methods that are fundamental to all Foundation objects.
@@ -361,6 +368,52 @@ open class NSObject : NSObjectProtocol, Equatable, Hashable {
361368
public static func ==(lhs: NSObject, rhs: NSObject) -> Bool {
362369
return lhs.isEqual(rhs)
363370
}
371+
372+
// Please note:
373+
// the following methods are not overridable in swift-corelibs-foundation.
374+
375+
private class var nsObjectSuperclass: NSObject.Type? {
376+
// Pretend that {Swift,}Foundation.NSObject is the top of the class hierarchy.
377+
// On Darwin, avoids dipping into the class hierarchy that exists above this class,
378+
// which is ultimately rooted in the ObjC NSObject class.
379+
guard !(self == NSObject.self) else { return nil }
380+
381+
let actualSuperclass: NSObject.Type
382+
383+
#if canImport(ObjectiveC)
384+
actualSuperclass = class_getSuperclass(self) as! NSObject.Type
385+
#else
386+
actualSuperclass = _swift_class_getSuperclass(self) as! NSObject.Type
387+
#endif
388+
389+
return actualSuperclass
390+
}
391+
392+
public class var superclass: AnyClass? {
393+
return nsObjectSuperclass
394+
}
395+
396+
/// Returns a Boolean value that indicates whether the receiving
397+
/// class is a subclass of, or identical to, a given class.
398+
public class func isSubclass(of aClass: AnyClass) -> Bool {
399+
var checkedClass: NSObject.Type? = self
400+
while let thisClass = checkedClass {
401+
if thisClass === aClass {
402+
return true
403+
}
404+
checkedClass = thisClass.nsObjectSuperclass
405+
}
406+
407+
return false
408+
}
409+
410+
public func isMember(of aClass: AnyClass) -> Bool {
411+
return type(of: self) === aClass
412+
}
413+
414+
public func isKind(of aClass: AnyClass) -> Bool {
415+
return type(of: self).isSubclass(of: aClass)
416+
}
364417
}
365418

366419
extension NSObject : CustomDebugStringConvertible {

0 commit comments

Comments
 (0)