123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- import Foundation
- import Realm
- import Realm.Private
- @objc(RealmSwiftObject)
- open class Object: RLMObjectBase, ThreadConfined, RealmCollectionValue {
-
- public static func _rlmArray() -> RLMArray<AnyObject> {
- return RLMArray(objectClassName: className())
- }
-
-
- public override required init() {
- super.init()
- }
-
- public init(value: Any) {
- super.init(value: value, schema: .partialPrivateShared())
- }
-
-
- public var realm: Realm? {
- if let rlmReam = RLMObjectBaseRealm(self) {
- return Realm(rlmReam)
- }
- return nil
- }
-
- public var objectSchema: ObjectSchema {
- return ObjectSchema(RLMObjectBaseObjectSchema(self)!)
- }
-
-
-
-
- public override final var isInvalidated: Bool { return super.isInvalidated }
-
- open override var description: String { return super.description }
-
- public override final class func objectUtilClass(_ isSwift: Bool) -> AnyClass {
- return ObjectUtil.self
- }
-
-
- @objc open class func primaryKey() -> String? { return nil }
-
- @objc open class func ignoredProperties() -> [String] { return [] }
-
- @objc open class func indexedProperties() -> [String] { return [] }
-
-
- @objc open subscript(key: String) -> Any? {
- get {
- if realm == nil {
- return value(forKey: key)
- }
- return RLMDynamicGetByName(self, key, true)
- }
- set(value) {
- if realm == nil {
- setValue(value, forKey: key)
- } else {
- RLMDynamicValidatedSet(self, key, value)
- }
- }
- }
-
-
- public func observe(_ block: @escaping (ObjectChange) -> Void) -> NotificationToken {
- return RLMObjectAddNotificationBlock(self, { names, oldValues, newValues, error in
- if let error = error {
- block(.error(error as NSError))
- return
- }
- guard let names = names, let newValues = newValues else {
- block(.deleted)
- return
- }
- block(.change((0..<newValues.count).map { i in
- PropertyChange(name: names[i], oldValue: oldValues?[i], newValue: newValues[i])
- }))
- })
- }
-
-
- public func dynamicList(_ propertyName: String) -> List<DynamicObject> {
- return noWarnUnsafeBitCast(RLMDynamicGetByName(self, propertyName, true) as! RLMListBase,
- to: List<DynamicObject>.self)
- }
-
-
- public func isSameObject(as object: Object?) -> Bool {
- return RLMObjectBaseAreEqual(self, object)
- }
-
-
-
- public override required init(realm: RLMRealm, schema: RLMObjectSchema) {
- super.init(realm: realm, schema: schema)
- }
-
- public override required init(value: Any, schema: RLMSchema) {
- super.init(value: value, schema: schema)
- }
- }
- public struct PropertyChange {
-
- public let name: String
-
- public let oldValue: Any?
-
- public let newValue: Any?
- }
- public enum ObjectChange {
-
- case error(_: NSError)
-
- case change(_: [PropertyChange])
-
- case deleted
- }
- public final class DynamicObject: Object {
- public override subscript(key: String) -> Any? {
- get {
- let value = RLMDynamicGetByName(self, key, false)
- if let array = value as? RLMArray<AnyObject> {
- return List<DynamicObject>(rlmArray: array)
- }
- return value
- }
- set(value) {
- RLMDynamicValidatedSet(self, key, value)
- }
- }
-
- public override func dynamicList(_ propertyName: String) -> List<DynamicObject> {
- return self[propertyName] as! List<DynamicObject>
- }
-
- public override func value(forUndefinedKey key: String) -> Any? {
- return self[key]
- }
-
- public override func setValue(_ value: Any?, forUndefinedKey key: String) {
- self[key] = value
- }
-
- public override class func shouldIncludeInDefaultSchema() -> Bool {
- return false
- }
- }
- @objc(RealmSwiftObjectUtil)
- public class ObjectUtil: NSObject {
- @objc private class func swiftVersion() -> NSString {
- #if SWIFT_PACKAGE
- return "5.1"
- #else
- return swiftLanguageVersion as NSString
- #endif
- }
- @objc private class func ignoredPropertiesForClass(_ type: AnyClass) -> NSArray? {
- if let type = type as? Object.Type {
- return type.ignoredProperties() as NSArray?
- }
- if let type = type as? RLMObject.Type {
- return type.ignoredProperties() as NSArray?
- }
- return nil
- }
- @objc private class func indexedPropertiesForClass(_ type: AnyClass) -> NSArray? {
- if let type = type as? Object.Type {
- return type.indexedProperties() as NSArray?
- }
- if let type = type as? RLMObject.Type {
- return type.indexedProperties() as NSArray?
- }
- return nil
- }
- @objc private class func linkingObjectsPropertiesForClass(_ type: AnyClass) -> NSDictionary? {
- if let type = type as? RLMObject.Type {
- return type.linkingObjectsProperties() as NSDictionary?
- }
-
- return nil
- }
-
-
- private static func baseName(forLazySwiftProperty name: String) -> String? {
-
-
-
- if let storageRange = name.range(of: ".storage", options: [.anchored, .backwards]) {
- #if swift(>=4.0)
- return String(name[..<storageRange.lowerBound])
- #else
- return name.substring(to: storageRange.lowerBound)
- #endif
- }
-
- #if swift(>=4.0)
- if let storageRange = name.range(of: "$__lazy_storage_$_", options: [.anchored]) {
- return String(name[storageRange.upperBound...])
- }
- #endif
- return nil
- }
-
- private static func getNonIgnoredMirrorChildren(for object: Any) -> [Mirror.Child] {
- let ignoredPropNames: Set<String>
- if let realmObject = object as? Object {
- ignoredPropNames = Set(type(of: realmObject).ignoredProperties())
- } else {
- ignoredPropNames = Set()
- }
-
- return Mirror(reflecting: object).children.filter { (prop: Mirror.Child) -> Bool in
- guard let label = prop.label else {
- return false
- }
- if ignoredPropNames.contains(label) {
-
- return false
- }
- if let lazyBaseName = baseName(forLazySwiftProperty: label) {
- if ignoredPropNames.contains(lazyBaseName) {
-
- return false
- }
- if object is RLMObject {
-
-
- return false
- }
-
-
- throwRealmException("Lazy managed property '\(lazyBaseName)' is not allowed on a Realm Swift object"
- + " class. Either add the property to the ignored properties list or make it non-lazy.")
- }
- return true
- }
- }
-
-
- private static func getOptionalPropertyMetadata(for child: Mirror.Child, at index: Int) -> RLMSwiftPropertyMetadata? {
- guard let name = child.label else {
- return nil
- }
- let mirror = Mirror(reflecting: child.value)
- let type = mirror.subjectType
- let code: PropertyType
- if type is Optional<String>.Type || type is Optional<NSString>.Type {
- code = .string
- } else if type is Optional<Date>.Type {
- code = .date
- } else if type is Optional<Data>.Type {
- code = .data
- } else if type is Optional<Object>.Type {
- code = .object
- } else if type is RealmOptional<Int>.Type ||
- type is RealmOptional<Int8>.Type ||
- type is RealmOptional<Int16>.Type ||
- type is RealmOptional<Int32>.Type ||
- type is RealmOptional<Int64>.Type {
- code = .int
- } else if type is RealmOptional<Float>.Type {
- code = .float
- } else if type is RealmOptional<Double>.Type {
- code = .double
- } else if type is RealmOptional<Bool>.Type {
- code = .bool
- } else if child.value is RLMOptionalBase {
- throwRealmException("'\(type)' is not a valid RealmOptional type.")
- code = .int
- } else if mirror.displayStyle == .optional || type is ExpressibleByNilLiteral.Type {
- return RLMSwiftPropertyMetadata(forNilLiteralOptionalProperty: name)
- } else {
- return nil
- }
- return RLMSwiftPropertyMetadata(forOptionalProperty: name, type: code)
- }
- @objc private class func getSwiftProperties(_ object: Any) -> [RLMSwiftPropertyMetadata] {
- return getNonIgnoredMirrorChildren(for: object).enumerated().map { idx, prop in
- if let value = prop.value as? LinkingObjectsBase {
- return RLMSwiftPropertyMetadata(forLinkingObjectsProperty: prop.label!,
- className: value.objectClassName,
- linkedPropertyName: value.propertyName)
- } else if prop.value is RLMListBase {
- return RLMSwiftPropertyMetadata(forListProperty: prop.label!)
- } else if let optional = getOptionalPropertyMetadata(for: prop, at: idx) {
- return optional
- } else {
- return RLMSwiftPropertyMetadata(forOtherProperty: prop.label!)
- }
- }
- }
- @objc private class func requiredPropertiesForClass(_: Any) -> [String] {
- return []
- }
- }
- private func forceCastToInferred<T, V>(_ x: T) -> V {
- return x as! V
- }
- extension Object: AssistedObjectiveCBridgeable {
- static func bridging(from objectiveCValue: Any, with metadata: Any?) -> Self {
- return forceCastToInferred(objectiveCValue)
- }
- var bridged: (objectiveCValue: Any, metadata: Any?) {
- return (objectiveCValue: unsafeCastToRLMObject(), metadata: nil)
- }
- }
- extension Object {
-
- @available(*, unavailable, renamed: "observe()")
- public func addNotificationBlock(_ block: @escaping (ObjectChange) -> Void) -> NotificationToken {
- fatalError()
- }
- #if os(OSX)
- #else
-
- @available(*, unavailable, renamed: "isSameObject(as:)") public func isEqual(to object: Any?) -> Bool {
- fatalError()
- }
- #endif
- }
|