Skip to content

Commit

Permalink
Added support for array of enums! #13
Browse files Browse the repository at this point in the history
  • Loading branch information
arturdev committed Mar 27, 2020
1 parent 413bd0f commit f3b8331
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 9 deletions.
4 changes: 3 additions & 1 deletion Example/Tests/ExampleModels/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import Foundation
import Unrealm

enum MyEnum: Int, RealmableEnum {
enum MyEnum: Int, RealmableEnumInt {
case case1
case case2
case case3
Expand All @@ -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"
Expand Down
9 changes: 7 additions & 2 deletions Example/Tests/Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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..<user.list.count {
Expand Down
25 changes: 20 additions & 5 deletions Unrealm/Classes/Swift/Realm+Unrealm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,15 @@ public extension Realm {
Unrealm requires to register all the types conforming to Realmable protocol
- parameter realmables: Types to be registereds
*/
static func registerRealmables(_ realmables: [RealmableBase.Type]) {
static func registerRealmables(_ realmables: [RealmableBase.Type], enums: [RealmableEnum.Type] = []) {
prepareUnrealm()


for en in enums {
let types = exctractTypeComponents(from: en)
let typeName = types.1
enumsAndRealmables[typeName] = en
}

//Creating all classes
realmables.forEach({
var superClass: AnyClass = Object.self
Expand Down Expand Up @@ -255,8 +261,8 @@ public extension Realm {
}
}

static func registerRealmables(_ realmables:RealmableBase.Type...) {
registerRealmables(realmables)
static func registerRealmables(_ realmables:RealmableBase.Type..., enums: [RealmableEnum.Type] = []) {
registerRealmables(realmables, enums: enums)
}
}

Expand Down Expand Up @@ -325,7 +331,7 @@ fileprivate func addPropertyToClassIfNeeded(className: AnyObject.Type, name: Str
addPropertyToClass(className, name, typeStr)
}

fileprivate func getGeneric(from type: String) -> String {
internal func getGeneric(from type: String) -> String {
if let match = type.range(of: "(?<=<)[^>]+", options: .regularExpression) {
return String(type[match])
}
Expand Down Expand Up @@ -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 {
Expand Down
31 changes: 30 additions & 1 deletion Unrealm/Classes/Swift/Unrealm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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..<realmArray.count {
let o = realmArray[i]
selfArray.append(o)

if let enumType = enumsAndRealmables[generic], let enumVal = enumType.init(rlmValue: o) {
selfArray.append(enumVal)
} else {
selfArray.append(o)
}
}
try property.set(value: selfArray, on: &self)
}
Expand Down Expand Up @@ -415,6 +437,13 @@ fileprivate func convert<T: NSObject>(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)
}
Expand Down

0 comments on commit f3b8331

Please sign in to comment.