From f3b83316b9133dec618d2bf3527543693bbb90e6 Mon Sep 17 00:00:00 2001 From: Artur Mkrtchyan Date: Sat, 28 Mar 2020 00:55:29 +0400 Subject: [PATCH] Added support for array of enums! #13 --- Example/Tests/ExampleModels/User.swift | 4 ++- Example/Tests/Tests.swift | 9 +++++-- Unrealm/Classes/Swift/Realm+Unrealm.swift | 25 ++++++++++++++---- Unrealm/Classes/Swift/Unrealm.swift | 31 ++++++++++++++++++++++- 4 files changed, 60 insertions(+), 9 deletions(-) diff --git a/Example/Tests/ExampleModels/User.swift b/Example/Tests/ExampleModels/User.swift index bdf114c..5e1bd6f 100644 --- a/Example/Tests/ExampleModels/User.swift +++ b/Example/Tests/ExampleModels/User.swift @@ -9,7 +9,7 @@ import Foundation import Unrealm -enum MyEnum: Int, RealmableEnum { +enum MyEnum: Int, RealmableEnumInt { case case1 case case2 case case3 @@ -31,6 +31,8 @@ struct User: Realmable { var doubleOptional: Double? = nil var boolOptional: Bool? = nil var arrayOptional: [Location]? = nil + var arrayOfEnums: [MyEnum] = [] + var arrayOfEnumsOptional: [MyEnum]? = nil static func primaryKey() -> String? { return "id" diff --git a/Example/Tests/Tests.swift b/Example/Tests/Tests.swift index bc29b35..cbdde99 100644 --- a/Example/Tests/Tests.swift +++ b/Example/Tests/Tests.swift @@ -12,7 +12,8 @@ class Tests: XCTestCase { private static func configRealm() -> Realm.Configuration { let realmableTypes: [RealmableBase.Type] = [Dog.self, User.self, Person.self, SubPerson.self, Location.self, Passenger.self, Driver.self, ParentStruct.self, ParentStruct.ChildStruct.self] - Realm.registerRealmables(realmableTypes) + Realm.registerRealmables(realmableTypes, + enums: [MyEnum.self]) var objectTypes = realmableTypes.compactMap({$0.objectType()}) objectTypes.append(RLMTestClass.self) @@ -133,7 +134,9 @@ class Tests: XCTestCase { floatOptional: 3.4, doubleOptional: 1.3, boolOptional: true, - arrayOptional: [loc2, loc3]) + arrayOptional: nil, + arrayOfEnums: [], + arrayOfEnumsOptional: nil) try! self.realm.write { self.realm.add(user) @@ -155,6 +158,8 @@ class Tests: XCTestCase { XCTAssertEqual(NSDictionary(dictionary: user.dicInt), NSDictionary(dictionary: savedUser!.dicInt)) XCTAssertEqual(user.intOptional, savedUser!.intOptional) XCTAssertEqual(user.arrayOptional, savedUser!.arrayOptional) + XCTAssertEqual(user.arrayOfEnums, savedUser!.arrayOfEnums) + XCTAssertEqual(user.arrayOfEnumsOptional, savedUser!.arrayOfEnumsOptional) XCTAssertEqual(user.list.count, savedUser!.list.count) for i in 0.. String { +internal func getGeneric(from type: String) -> String { if let match = type.range(of: "(?<=<)[^>]+", options: .regularExpression) { return String(type[match]) } @@ -368,6 +374,15 @@ fileprivate func getTypeString(from value: Any) -> String { if typeStr.hasPrefix("Dictionary<") { return "NSData" } + + if typeStr.hasPrefix("Array<") { + let generic = getGeneric(from: typeStr) + if let enumType = enumsAndRealmables[generic] { + let rawValueType = enumType.rawValueType + typeStr = "Array<" + String(describing: rawValueType) + ">" + return typeStr + } + } if let typeinfo = try? typeInfo(of: type(of: value)) { if typeinfo.kind == .enum { diff --git a/Unrealm/Classes/Swift/Unrealm.swift b/Unrealm/Classes/Swift/Unrealm.swift index f95e479..47377b8 100644 --- a/Unrealm/Classes/Swift/Unrealm.swift +++ b/Unrealm/Classes/Swift/Unrealm.swift @@ -19,12 +19,17 @@ import UnrealmObjC #endif internal var objectsAndRealmables: [String:RealmableBase.Type] = [:] +internal var enumsAndRealmables: [String:RealmableEnum.Type] = [:] public protocol RealmableEnum { func rlmValue() -> Any init?(rlmValue: Any) + static var rawValueType: Any.Type { get } } +public protocol RealmableEnumInt: RealmableEnum {} +public protocol RealmableEnumString: RealmableEnum {} + public extension RealmableEnum where Self : RawRepresentable { func rlmValue() -> Any { return rawValue @@ -34,6 +39,16 @@ public extension RealmableEnum where Self : RawRepresentable { guard let rawVal = rlmValue as? Self.RawValue else {return nil} self.init(rawValue: rawVal) } + + static var rawValueType: Any.Type { + return Self.RawValue.self + } +} + +extension Array where Element: RealmableEnum { + var elementType: Any.Type { + return Element.rawValueType + } } extension Optional where Wrapped: RealmableEnum { @@ -309,9 +324,16 @@ public extension Realmable { try property.set(value: convertedArray, on: &self) } else { var selfArray = [Any]() + let generic = getGeneric(from: String(describing: type(of: child.value))) + for i in 0..(val: Any, to objectType: T.Type) -> AnyObj if let o = convert(val: value, to: c) { realmArray.add(o) } + } else if let enumValue = value as? RealmableEnum { + let rawValue = enumValue.rlmValue() + if let intValue = rawValue as? Int { + realmArray.add(NSNumber(value: intValue) as AnyObject) + } else { + realmArray.add(rawValue as AnyObject) + } } else { realmArray.add(value as AnyObject) }