Reflection based (Dictionary, CKRecord, NSManagedObject, Realm, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift

Overview

EVReflection

Issues Coverage Documentation Stars Awesome

Version Carthage compatible Language Platform License

Git Twitter LinkedIn Website eMail

General information

At this moment the master branch is tested with Swift 4.2 and 5.0 beta If you want to continue using EVReflection in an older version, then use the corresponding branch. Run the unit tests to see EVReflection in action.

Please update to cocoapods 1.7.0 for now you could do that using

sudo gem install cocoapods --pre

This is required for libraries that want to support other swift versions besides 5.0 For more information see the cocoapods blog

EVReflection is used in EVCloudKitDao and EVWordPressAPI

In most cases EVReflection is very easy to use. Just take a look the section It's easy to use. But if you do want to do non standard specific things, then EVReflection will offer you an extensive range of functionality.

Available extensions

There are extension available for using EVReflection with XMLDictionairy, Realm, CloudKit, Alamofire and Moya with RxSwift or ReactiveSwift

All these extens can be installed by adding something like this in your podfile:

pod 'EVReflection/MoyaRxSwift'

For Carthage there is not (yet) an extension for all above extension. If needed, please let me know. For carthage you can use:

github "evermeer/EVReflection" 

Index

Main features of EVReflection:

  • Parsing objects based on NSObject to and from a dictionary. (also see the XML and .plist samples!)
  • Parsing objects to and from a JSON string.
  • Support NSCoding function encodeWithCoder and decodeObjectWithCoder
  • Supporting Printable, Hashable and Equatable while using all properties.
  • Mapping objects from one type to an other
  • Support for property mapping, converters, validators and key cleanup

It's easy to use:

Defining an object. You only have to set EVObject as it's base class (or extend an NSObject with EVReflectable):

class User: EVObject {
    var id: Int = 0
    var name: String = ""
    var friends: [User]? = []
}

Parsing JSON to an object:

let json:String = "{\"id\": 24, \"name\": \"Bob Jefferson\", \"friends\": [{\"id\": 29, \"name\": \"Jen Jackson\"}]}"
let user = User(json: json)

Parsing JSON to an array of objects:

let json:String = "[{\"id\": 27, \"name\": \"Bob Jefferson\"}, {\"id\": 29, \"name\": \"Jen Jackson\"}]"
let array = [User](json: json)

Parsing from and to a dictionary:

let dict = user.toDictionary()
let newUser = User(dictionary: dict)
XCTAssert(user == newUser, "Pass")

Saving and loading an object to and from a file:

user.saveToTemp("temp.dat")
let result = User(fileNameInTemp: "temp.dat")
XCTAssert(theObject == result, "Pass")

Mapping object to another type:

let administrator: Administrator = user.mapObjectTo()

If you have XML instead of JSON

If you want to do the same but you have XML, then you can achieve that using the XML subspec 'pod EVReflection/XML' It is a simple way to parse XML. With that your code will look like this:

let xml = "<user><id>27</id><name>Bob</name><friends><user><id>20</id><name>Jen</name></user></friends></user>"
let user = User(xmlString: xml)

Using EVReflection in your own App

'EVReflection' is available through the dependency manager CocoaPods. You do have to use cocoapods version 0.36 or later

You can just add EVReflection to your workspace by adding the following 2 lines to your Podfile:

use_frameworks!
pod "EVReflection"

You can also use the Swift2.2 or Swift2.3 version of EVReflection. You can get that version by using the podfile command:

use_frameworks!
pod "EVReflection"', :git => 'https://github.com/evermeer/EVReflection.git', :branch => 'Swift2.2'

Version 0.36 of cocoapods will make a dynamic framework of all the pods that you use. Because of that it's only supported in iOS 8.0 or later. When using a framework, you also have to add an import at the top of your swift file like this:

import EVReflection

If you want support for older versions than iOS 8.0, then you can also just copy the files from the pod folder to your project. You do have to use the Swift2.3 version or older. iOS 7 support is dropped from Swift 3.

Be aware that when you have your object definitions in a framework and not in your main app, then you have to let EVReflection know that it should also look in that framework for your classes. This can easilly be done by using the following one liner (for instance in the appdelegate)

EVReflection.setBundleIdentifier(YourDataObject.self)

More Sample code

Clone EVReflection to your desktop to see these and more unit tests

func testEquatable() {
    var theObjectA = TestObject2()
    theObjectA.objectValue = "value1"
    var theObjectB = TestObject2()
    theObjectB.objectValue = "value1"
    XCTAssert(theObjectA == theObjectB, "Pass")

    theObjectB.objectValue = "value2"
    XCTAssert(theObjectA != theObjectB, "Pass")
}

func testHashable() {
    var theObject = TestObject2()
    theObject.objectValue = "value1"
    var hash1 = theObject.hash
    NSLog("hash = \(hash)")
}

func testPrintable() {
    var theObject = TestObject2()
    theObject.objectValue = "value1"
    NSLog("theObject = \(theObject)")
}

func testArrayFunctions() {
    let dictionaryArray: [NSDictionary] = yourGetDictionaryArrayFunction()
    let userArray = [User](dictionaryArray: dictionaryArray)
    let newDictionaryArray = userArray.toDictionaryArray()
}

func testMapping() {
    let player = GamePlayer()
    player.name = "It's Me"

    let administrator = GameAdministrator(usingValuesFrom: player)
}

Direct conversion from a NSDictionary (or an array of NSDictionaries) to json and back.

let dict1: NSDictionary = [
  "requestId": "request",
  "postcode": "1111AA",
  "houseNumber": "1"
]
let json = dict1.toJsonString()
let dict2 = NSMutableDictionary(json: json)
print("dict:\n\(dict1)\n\njson:\n\(json)\n\ndict2:\n\(dict2)")

// You can do the same with arrays
let array:[NSDictionary] = [dict1, dict2]
let jsonArray = array.toJsonStringArray()
let array2 = [NSDictionary](jsonArray: jsonArray)
print("json array: \n\(jsonArray)\n\narray2:\n\(array2)")

This is how you can parse a .plist into an object model. See EVReflectionIssue124.swift to see it working.

   if let path = Bundle(for: type(of: self)).path(forResource: "EVReflectionIssue124", ofType: "plist") {
       if let data = NSDictionary(contentsOfFile: path) {
          let plistObject = Wrapper(dictionary: data)
          print(plistObject)
       }
   }

If you want to parse XML, then you can use the pod subxpec EVReflection/XML

    let xml: String = "<data><item name=\"attrib\">itemData</item></data>"
    let xmlObject = MyObject(xml: xml)
    print(xmlObject)

Extending existing objects:

It is possible to extend other objects with the EVReflectable protocol instead of changing the base class to EVObject. This will let you add the power of EVReflection to objects that also need another framework. In some cases you still need some aditional code. For a sample see the Realm and NSManagedObject subspecs. The most basic way to extend your objects is like this:

import EVReflection
extension MyObject : EVReflectable { }

Extra information:

Conversion options

With almost any EVReflection function you can specify what kind of conversion options should be used. This is done using an option set. You can use the following conversion options:

  • None - Do not use any conversion function.
  • PropertyConverter : If specified the function propertyConverters on the EVObject will be called
  • PropertyMapping : If specified the function propertyMapping on the EVObject will be called
  • SkipPropertyValue : If specified the function skipPropertyValue on the EVObject will be called
  • KeyCleanup : If specified the automatic pascalCase and snake_case property key mapping will be called.
  • Encoding : For if you want class level functionality for encoding values (like base64, unicode, encription, ...)
  • Decoding : For if you want class level functionality for decoding values (like base64, unicode, encription, ...)

In EVReflection all functions will use a default conversion option specific to it's function. The following 4 default conversion types are used:

  • DefaultNSCoding = [None]
  • DefaultComparing = [PropertyConverter, PropertyMapping, SkipPropertyValue]
  • DefaultDeserialize = [PropertyConverter, PropertyMapping, SkipPropertyValue, KeyCleanup, Decoding]
  • DefaultSerialize = [PropertyConverter, PropertyMapping, SkipPropertyValue, Encoding]

If you want to change one of the default conversion types, then you can do that using something like:

ConversionOptions.DefaultNSCoding = [.PropertyMapping]

Automatic keyword mapping for Swift keywords

If you have JSON fields that are Swift keywords, then prefix the property with an underscore. So the JSON value for self will be stored in the property \_self. At this moment the following keywords are handled:

"self", "description", "class", "deinit", "enum", "extension", "func", "import", "init", "let", "protocol", "static", "struct", "subscript", "typealias", "var", "break", "case", "continue", "default", "do", "else", "fallthrough", "if", "in", "for", "return", "switch", "where", "while", "as", "dynamicType", "is", "new", "super", "Self", "Type", "COLUMN", "FILE", "FUNCTION", "LINE", "associativity", "didSet", "get", "infix", "inout", "left", "mutating", "none", "nonmutating", "operator", "override", "postfix", "precedence", "prefix", "right", "set", "unowned", "unowned", "safe", "unowned", "unsafe", "weak", "willSet", "private", "public"

Automatic keyword mapping PascalCase or camelCase to snake_case

When creating objects from JSON EVReflection will automatically detect if snake_case (keys are all lowercase and words are separated by an underscore) should be converted to PascalCase or camelCase property names. See Conversion options for when this function will be called.

When exporting object to a dictionary or JSON string you will have an option to specify that you want a conversion to snake_case or not. The default is .DefaultDeserialize which will also convert to snake case.

let jsonString = myObject.toJsonString([.DefaultSerialize])
let dict = myObject.toDictionary([PropertyConverter, PropertyMapping, SkipPropertyValue])

Custom keyword mapping

It's also possible to create a custom property mapping. You can define if an import should be ignored, if an export should be ignored or you can map a property name to another key name (for the dictionary and json). For this you only need to implement the propertyMapping function in the object. See Conversion options for when this function will be called.

public class TestObject5: EVObject {
    var Name: String = "" // Using the default mapping
    var propertyInObject: String = "" // will be written to or read from keyInJson
    var ignoredProperty: String = "" // Will not be written or read to/from json 

    override public func propertyMapping() -> [(keyInObject: String?, keyInResource: String?)] {
        return [(keyInObject: "ignoredProperty",keyInResource: nil), (keyInObject: "propertyInObject",keyInResource: "keyInJson")]
    }
}

Custom property converters

You can also use your own property converters. For this you need to implement the propertyConverters function in your object. For each property you can create a custom getter and setter that will then be used by EVReflection. In the sample below the JSON texts 'Sure' and 'Nah' will be converted to true or false for the property isGreat. See Conversion options for when this function will be called.

public class TestObject6: EVObject {
    var isGreat: Bool = false

    override func propertyConverters() -> [(key: String, decodeConverter: ((Any?) -> ()), encodeConverter: (() -> Any?))] {
        return [
            ( // We want a custom converter for the field isGreat
              key: "isGreat"
              // isGreat will be true if the json says 'Sure'
              , decodeConverter: { self.isGreat = ($0 as? String == "Sure") }
              // The json will say 'Sure  if isGreat is true, otherwise it will say 'Nah'
              , encodeConverter: { return self.isGreat ? "Sure": "Nah"})
        ]
    }
}

Encoding and decoding

You can add generic cod to encode or decode multiple or all properties in an object. This can be used for instance for base64, unicode and encription. Here is a base64 sample:

class SimleEncodingDecodingObject : EVObject{
    var firstName: String?
    var lastName: String?
    var street: String?
    var city: String?

    override func decodePropertyValue(value: Any, key: String) -> Any? {
        return (value as? String)?.base64Decoded?.string ?? value
    }

    override func encodePropertyValue(value: Any, key: String) -> Any {
        return (value as? String)?.base64Encoded.string ?? value
    }
}


extension String {
var data:          Data  { return Data(utf8) }
var base64Encoded: Data  { return data.base64EncodedData() }
var base64Decoded: Data? { return Data(base64Encoded: self) }
}

extension Data {
var string: String? { return String(data: self, encoding: .utf8) }
}

Custom object converter

If you want to serialize an object to a dictionary or json but the structure should be different than the object itself, then instead of using propertyConverers, you can also convert the entire object by implementing the customConverter function. In the example below the entire object will be serialized to just a string. You could also return a dictionary that represents the custom structure or an array if the object should have been an array

override func customConverter() -> AnyObject? {
    return "Object not serialized"
}

Custom type converter

If you have a custom type that requires special conversion, then you can extend it with the EVCustomReflectable protocol. A good implementation for this can be found in the Realm subspec for the List type. The converter is implemented like this:

extension List : EVCustomReflectable {
    public func constructWith(value: Any?) -> EVCustomReflectable {
        if let array = value as? [NSDictionary] {
            self.removeAll()
            for dict in array {
                if let element: T = EVReflection.fromDictionary(dict, anyobjectTypeString: _rlmArray.objectClassName) as? T {
                    self.append(element)
                }
            }
        }
        return self
    }
    public func toCodableValue() -> Any {
        return self.enumerated().map { ($0.element as? EVReflectable)?.toDictionary() ?? NSDictionary() }
    }
}

For the usage, please have a look at the Realm unittest

Skip the serialization or deserialization of specific values

When there is a need to not (de)serialize specific values like nil NSNull or empty strings you can implement the skipPropertyValue function and return true if the value needs to be skipped. See Conversion options for when this function will be called.

class TestObjectSkipValues: EVObject {
   var value1: String? 
   var value2: [String]?
   var value3: NSNumber?

   override func skipPropertyValue(value: Any, key: String) -> Bool {
      if let value = value as? String where value.characters.count == 0 || value == "null" {
         print("Ignoring empty string for key \(key)")
         return true
      } else if let value = value as? NSArray where value.count == 0 {
         print("Ignoring empty NSArray for key\(key)")
         return true
      } else if value is NSNull {
         print("Ignoring NSNull for key \(key)")
         return true
      }
      return false
   }
}

Property validators

Before setting a value the value will always be validated using the standard validateValue KVO function. This means that for every property you can also create a validation function for that property. See the sample below where there is a validateName function for the name property.

enum MyValidationError: ErrorType {
   case TypeError,
   LengthError
}

public class GameUser: EVObject {
   var name: String?
   var memberSince: NSDate?
   var objectIsNotAValue: TestObject?

   func validateName(value:AutoreleasingUnsafeMutablePointer<AnyObject?>) throws {
      if let theValue = value.memory as? String {
         if theValue.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) < 3 {
            NSLog("Validating name is not long enough \(theValue)")
            throw MyValidationError.LengthError
         }
         NSLog("Validating name OK \(theValue)")
      } else {
         NSLog("Validating name is not a string: \(value.memory)")
         throw MyValidationError.TypeError
     }
   }
}

Print options

You should be able to solve all problems with parsing your json to an object. If you get warnings and you know they don't matter and you want to stop them from printin you can suppress all print warings by calling the followin line of code:

PrintOptions.Active = .None

If you then want to turn on the print output, then just call:

PrintOptions.Active = .All

It's also possible to enable printing for specific warning types. Here is the line of code that is equal to setting it to .All. Just leave out the type that you want to suppress.

PrintOptions.Active = [.UnknownKeypath, .IncorrectKey, .ShouldExtendNSObject, .IsInvalidJson, .MissingProtocol, .MissingKey, .InvalidType, .InvalidValue, .InvalidClass, .EnumWithoutAssociatedValue]

Deserialization class level validations

There is also support for class level validation when deserializing to an object. There are helper functions for making keys required or not allowed. You can also add custom messages. Here is some sample code about how you can implement such a validation

public class ValidateObject: EVObject {
   var requiredKey1: String?
   var requiredKey2: String?
   var optionalKey1: String?

   override public func initValidation(dict: NSDictionary) {
      self.initMayNotContainKeys(["error"], dict: dict)
      self.initMustContainKeys(["requiredKey1", "requiredKey2"], dict: dict)
      if dict.valueForKey("requiredKey1") as? String == dict.valueForKey("optionalKey1") as? String {
         // this could also be called in your property specific validators
         self.addStatusMessage(.Custom, message: "optionalKey1 should not be the same as requiredKey1")
      }
   }
}

You could then test this validation with code like:

func testValidation() {
   // Test missing required key
   let json = "{\"requiredKey1\": \"Value1\"}"
   let test = ValidateObject(json: json)
   XCTAssertNotEqual(test.evReflectionStatus(), .None, "We should have a not .None status")
   XCTAssertEqual(test.evReflectionStatuses.count, 1, "We should have 1 validation result")
   for (status, message) in test.evReflectionStatuses {
      print("Validation result: Status = \(status), Message = \(message)")
   }
}

What to do when you use object inheritance

You can deserialize json to an object that uses inheritance. When the properties are specified as the base class, then the correct specific object type will be returned by the function getSpecificType. See the sample code below or the unit test in EVReflectionInheritanceTests.swift

class Quz: EVObject {
    var fooArray: Array<Foo> = []
    var fooBar: Foo?
    var fooBaz: Foo?
}

class Foo: EVObject {
    var allFoo: String = "all Foo"

    // What you need to do to get the correct type for when you deserialize inherited classes
    override func getSpecificType(_ dict: NSDictionary) -> EVReflectable {
        if dict["justBar"] != nil {
            return Bar()
        } else if dict["justBaz"] != nil {
            return Baz()
        }
        return self
    }
}

class Bar : Foo {
    var justBar: String = "For bar only"
}

class Baz: Foo {
    var justBaz: String = "For baz only"
}

Known issues

EVReflection is trying to handle all types. With some types there are limitations in Swift. So far there is a workaround for any of these limitations. Here is an overview:

It's not possible in Swift to use .setObjectForKey for:

  • nullable type fields like Int?
  • properties based on an enum
  • an Array of nullable objects like [MyObject?]
  • a Set like Set
  • generic properties like var myVal:T = T()
  • structs like CGRect or CGPoint

For all these issues there are workarounds. The easiest workaround is just using a difrent type like:

  • Instead of an Int? you could use NSNumber?
  • Instead of [MyObject?] use [MyObject]
  • Instead of Set use [MyObject]
  • Instead of 'var status: StatysType' use 'var status:Int' and save the rawValue
  • Instead of a generic property use a specific property that can hold the data (a dictionary?)
  • Instead of using a struct, create your own object model for that struct

If you want to keep on using the same type, You can override the setValue forUndefinedKey in the object itself. See WorkaroundsTests.swift and WorkaroundSwiftGenericsTests.swift to see the workaround for all these types in action.

Generic properties

For generic properties the protocol EVGenericsKVC is required. see WorkaroundSwiftGenericsTests.swift

Arrays with nullable objects or Set's

For arrays with nullable objects or Set's like [MyObj?] or Set the protocol EVArrayConvertable is required. see WorkaroundsTests.swift

Swift Dictionaries

For Swift Dictionaries (and not NSDictionary) the protocol EVDictionaryConvertable is required. See WorkaroundsTests.swift

License

EVReflection is available under the MIT 3 license. See the LICENSE file for more info.

My other libraries:

Also see my other public source iOS libraries:

  • EVReflection - Reflection based (Dictionary, CKRecord, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift
  • EVCloudKitDao - Simplified access to Apple's CloudKit
  • EVFaceTracker - Calculate the distance and angle of your device with regards to your face in order to simulate a 3D effect
  • EVURLCache - a NSURLCache subclass for handling all web requests that use NSURLReques
  • AlamofireOauth2 - A swift implementation of OAuth2 using Alamofire
  • EVWordPressAPI - Swift Implementation of the WordPress (Jetpack) API using AlamofireOauth2, AlomofireJsonToObjects and EVReflection (work in progress)
  • PassportScanner - Scan the MRZ code of a passport and extract the firstname, lastname, passport number, nationality, date of birth, expiration date and personal numer.
  • AttributedTextView - Easiest way to create an attributed UITextView with support for multiple links (url, hashtags, mentions).

Evolution of EVReflection (Gource Visualization)

Evolution of EVReflection (Gource Visualization)

Comments
  • EVReflection parse to array issue Swift 2.0?

    EVReflection parse to array issue Swift 2.0?

    In my podfile:use_frameworks! pod 'EVReflection', '~> 2.6'

    Added a class:

    public class SubscriptionsItem: EVObject {
        var subscriptionId: String = ""
        var title: String = ""
        var count: Int = 0
    }
    

    Now i'm trying to parse json data to my array of SubscriptionsItems: subscriptionEntries = [SubscriptionsItem](json: responseObject)

    I'm getting 'Cannot invoke initiallizer for type '[SubscriptionsItem]' with an argument list of type '(json: String)'.

    Can't figure out what i'm doing wrong here?

    help wanted fixed? 
    opened by tobiasolofssonevry 26
  • Very Slow Performance Parsing Json

    Very Slow Performance Parsing Json

    Hello, I'm testing speed of json libraries and have big problems with EVReflection.

    The EVReflection parse is taking 42 SECONDS to parse this model and this json with recursive objects in lists. Running in the simulator. In the device it crash, out of memory!

    Do you think we can change this or it is a real problem of evereflection and we need to migrate to faster libs? I can help to fix if you have some tips about where can be the problem.

    Thank you

    Model: `import UIKit import EVReflection

    class SpeedReflection: EVObject { var name: String? = nil var list: [SpeedReflection]? = nil }`

    JSON: { "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }] }, { "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }] }, { "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }] }, { "name": "String Long Name", "list": [] }] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }] }] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [{ "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }, { "name": "String Long Name", "list": [] }] }] }

    bug enhancement help wanted 
    opened by pedrovalentini 21
  • NSDate issue

    NSDate issue

    Hi, I'm sending to rest server a NSDate object.

    if I print print(NSDate())

    i get: 2016-01-18 15:35:43 +0000

    after conversion with EVReflection i get:

    "18/01/16, 16:35:49 CET",

    this output is not compliant with standard because back end response is:

    Can not construct instance of java.util.Date from String value '18/01/16, 16:35:49 CET': not a valid representation (error: Failed to parse Date value '18/01/16, 16:35:49 CET': Can not parse date "18/01/16, 16:35:49 CET": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))\n at

    opened by cafuni 20
  • Ignore nil properties in toJsonString()

    Ignore nil properties in toJsonString()

    Is there any way to set up EVReflection to ignore properties that are nil when generating JSON?

    eg. I have a model

    class Test : EVObject {
      var prop1 : String? = nil
      var prop2 : String? = nil
    }
    
    

    if prop1 is nil, I would like toJsonString() to return a string ignoring prop1 completely. (This is consistent with the way JAYL-Entity works, and I'm in the process of replacing it with EVReflection).

    Thanks!,

    Raf.

    enhancement 
    opened by rafcabezas 17
  • framework not found EVReflection

    framework not found EVReflection

    Mac OSX 10.11.1 Xcode 7.1

    I installed the library following this steps:

    Open Terminal and execute: $ sudo gem install cocoapods Navigate to my Project folder (example /Users/myName/Documents/APP/APP.xcodeproj). Setup Cocoapod: pod setup Create the Podfile: touch Podfile Open the Podfile: open -e Podfile Insert code for Podfile: use_frameworks! pod "EVReflection", '~> 2.6' Finally install the Podfile pod install

    when I run the app I receive this error: ld: framework not found EVReflection clang: error: linker command failed with exit code 1 (use -v to see invocation)

    opened by cafuni 17
  • Cant Parse Dynamic object like array string and dictonary

    Cant Parse Dynamic object like array string and dictonary

    Language : Swift version : 5.0

    Response from server

    {
        "status": "success",
        "code": 200,
        "message": "Data received successfully",
        "data": [
            {
                "PId": 1,
                "PharmacyName": "Xyz",
                "ContactPerson": "test",
                "EmailId": "[email protected]",
                "PhoneNumer": "1234567890",
                "Address1": "test",
                "Address2": "test",
                "City": "test",
                "EntryDate": "2020-06-06T11:05:59.42",
                "ModifyDate": "2020-06-06T11:05:59.42",
                "UserId": 1,
                "IsDelete": false
            },
            {
                "PId": 2,
                "PharmacyName": "ZZZ",
                "ContactPerson": "ZZZ",
                "EmailId": "[email protected]",
                "PhoneNumer": "1234567890",
                "Address1": "test",
                "Address2": "test",
                "City": "test",
                "EntryDate": "2020-06-06T11:05:32.967",
                "ModifyDate": "2020-06-06T11:05:32.967",
                "UserId": 1,
                "IsDelete": false
            }
        ]
    }
    
    I have a the below model class
    
    

    I have below model

    **Code **

    protocol arrayorDictonary { }
    
    extension Array: arrayorDictonary { }
    extension Dictionary: arrayorDictonary { }
    
    
    //empty model
    class EmptyModelWithData : EVObject {
        var message = ""
        var status  = ""
        var code = 0
        var data : arrayorDictonary?
    }
    
    Alamofire.request(baseURL + urlMethod , method: method ,parameters: nil, encoding: JSONEncoding.default, headers:headerDic as? HTTPHeaders).responseObject {(response : DataResponse<EmptyModelWithData>) in
                SVProgressHUD.dismiss()
                let statusCode = response.response?.statusCode
                if response.result.value != nil {
                 }
      }
    
    

    and i get the following warning: while doing this

    WARNING: The class 'EmptyModelWithData' is not key value coding-compliant for the key 'data' There is no support for optional type, array of optionals or enum properties. As a workaround you can implement the function 'setValue forUndefinedKey' for this. See the unit tests for more information

    Note: Data is not specific type. some time data is array. some time data is dictionary. and sometime it would be string. so i create protocol but not working

    I hope I get solution from here..

    Thank you so much..

    opened by maulikshah09 16
  • XML - Crash on missing key

    XML - Crash on missing key

    Current using the following:

        pod 'EVReflection/Realm', :git => 'https://github.com/evermeer/EVReflection.git', :tag => '5.4.3'
        pod 'EVReflection/XML', :git => 'https://github.com/evermeer/EVReflection.git', :tag => '5.4.3'
    

    Example XML:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <xmldata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    
    <filename>MyFileName.pdf</filename>
    
    </xmldata>
    

    Example object: class Result: Object, EVReflectable {

        @objc dynamic var filename: String?
    }
    

    When EVR attempts to turn the XML into a Dictionary, the <xmldata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> line is interpreted as a field. Its key is "__name" and value is "xmldata". This occurs on line 20 of EVReflectable+XMLDictionary.

    I figured this wouldn't be a big deal. I'm not including the "__name" key as a property so I assume that key-value pair will simply be discarded. But, to my surprise, EVR attempts to set the data to the appropriate (non-existant) property. This occurs in the setPropertiesfromDictionary function because "__name" shows up in the keyMapping list.

    I dived into getKeyMapping to figure out why this would be. It would seem that you include the unknown mappings. Specifically the following:

    if !isAdded {
        keyMapping.append((item.key as? String, item.key as? String))
    }
    

    We are including a key that does not have a corresponding property on a Realm object. This appears to cause a crash in RLMObjectBase.

    In summary: I am combining the Realm and XML extensions. A crash occurs when a key exists in the XML that does not have a complimentary property in the object.

    fixed? 
    opened by Alarson93 16
  • Nested evobject fails to deserialize - App name contains a dot

    Nested evobject fails to deserialize - App name contains a dot

    I have two class like this:

    import EVReflection
    
    class DocumentDetails : EVObject{
        var reference = ""
        var documentContent = ""
        var documentAttachmentLinks : [DocumentAttachmentLink]? = []
    }
    
    class DocumentAttachmentLink : EVObject {
        var attachmentId = ""
        var fileName = ""
        var dateCreated = ""
    }
    

    Whenever I try to create an instance of DocumentDetails it fails to deserialize the documentAttachmentLinks with the following error:

    ERROR: Could not create an instance for type DocumentAttachmentLink
    dict:{
        AttachmentId = 340cfe14bfa14531ad7e781566be9d8f;
        DateCreated = "2017-02-10T14:29:22.4831934+13:00";
        DateDownloaded = "2017-02-13T00:54:35.9319384+00:00";
        DocumentId = 1067783;
        FileName = "1_UblPreview.pdf";
        Id = 5;
    }
    

    I've tried stepping through the EVReflection code but can't figure out what I'm doing wrong.

    bug 
    opened by icbmike 16
  • EVReflection with NSManagedObject CRASHES!

    EVReflection with NSManagedObject CRASHES!

    hI: I've been using EVReflection to make our Network Layer Fully Restful and I Must say: AWESOME WORK! Thanks for this Library.

    Now, to the Issue:

    The Next Step is to get Those Object Straight into CORE DATA. Here is one of the Classes in Question

    // Here is the Object With the EVReflectable Extension as the Documentation Claims:

    import Foundation
    import CoreData
    import EVReflection
    
    public class NGTripSummary: NSManagedObject { }
    
    extension NGTripSummary: EVReflectable { }
    

    // and HERE is the Object Properties:

    // NGTripSummary+CoreDataProperties.swift

    import Foundation
    import CoreData
    
    extension NGTripSummary {
    
        @nonobjc public class func fetchRequest() -> NSFetchRequest<NGTripSummary> {
            return NSFetchRequest<NGTripSummary>(entityName: "NGTripSummary")
        }
    
        @NSManaged public var carId: Int64
        @NSManaged public var citiesVisited: NSObject?
        @NSManaged public var cost: Double
        @NSManaged public var distance: Double
        @NSManaged public var globalStartDate: NSDate?
        @NSManaged public var globalEndDate: NSDate?
        @NSManaged public var kpl: Double
        @NSManaged public var litres: Double
        @NSManaged public var routeLocations: NSObject?
        @NSManaged public var sessionId: Int64
        @NSManaged public var localStartDate: NSDate?
        @NSManaged public var localEndDate: NSDate?
        @NSManaged public var duration: Int64
        @NSManaged public var speed: Double
        @NSManaged public var _id: Int64
        @NSManaged public var sessionUuid: String?
        @NSManaged public var tripUuid: String?
    
    }
    

    // . here is the JSON String that Represents a Demo Object:

    let tripData = "{\"id\":26105240,\"userId\":25796277,\"carId\":25817551,\"vehicleId\":57812351,\"sessionUuid\":\"53324259-aa69-41c8-8f9e-c62bdb70f165\",\"tripUuid\":\"afdd8f55-6d14-4cf9-bd9f-5b6da47aaf93\",\"localStartDate\":1487170622490,\"localEndDate\":1487178323654,\"globalStartDate\":1487163422490,\"globalEndDate\":1487171123654,\"routeLocations\":null,\"litres\":24.7699,\"kpl\":0.0772,\"cost\":153.3258,\"distance\":1.9132,\"duration\":491.958,\"speed\":14.0}"
    

    // and HERE is the Method I'm Trying to use to Create this Mock Object:

        func makeMockData() {
            let singleTrip = NGTripSummary(json: tripData)
            print("Single Trip: \(singleTrip)")
        } 
    

    // NOW: When Creating the Object, the Crash Happens HERE @ class EVReflection:

                // Call your own object validators that comply to the format: validate<Key>:Error:
                do {
                    var setValue: AnyObject? = value as AnyObject?
    /* LINE 923: CRASH HAPPENS HERE -> */  try anyObject.validateValue(&setValue, forKey: key)
                    anyObject.setValue(setValue, forKey: key)
                } catch _ {
                    (anyObject as? EVReflectable)?.addStatusMessage(.InvalidValue, message: "Not a valid value for object `\(NSStringFromClass(type(of: (anyObject as AnyObject))))`, type `\(type)`, key  `\(key)`, value `\(value)`")
                    print("INFO: Not a valid value for object `\(NSStringFromClass(type(of: (anyObject as AnyObject))))`, type `\(type)`, key  `\(key)`, value `\(value)`")
                }
    

    ////////////////////////////////////////// REASON FOR CRASH /////////////////////////////////////

    2017-04-24 17:51:47.195791+0300 engieApp[6570:2198102] [error] error: CoreData: error: Failed to call designated initializer on NSManagedObject class 'engieApp.NGTripSummary' CoreData: error: CoreData: error: Failed to call designated initializer on NSManagedObject class 'engieApp.NGTripSummary'

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////

    @evermeer: Please help us! you are the last hope of our Galaxy (dev-team), may the Force be with you :-) 👍

    enhancement fixed? 
    opened by hernanarber 15
  • Initializing nested arrays?

    Initializing nested arrays?

    I am trying to find a way to initialize an array with nested arrays without having to initialize a class to do so.

    I tried let myArrays = [[[MyObject]]](json: myDataString)

    But of course I got an error saying that [[MyObject]] was not a subclass of NSObject. (Subquestion...using this method it doesn't have to be a EVObject?)

    I also get the same error doing it through classes.

    class DataClass: EVObject {
        var myArrays = [[[[MyObject]]]()
    }
    

    also did

    class DataClass: EVObject {
        var myArrays: Array<Array<Array<MyObject>>> = []
    }
    

    I get the same error every time. Not sure what to do to get this to work without making a property converter. Even if I went that route Im not sure what I would convert this into. Maybe a

    Array<Array<Array< NSDictionary >>>

    and try to loop through each array till I have my array of dictionaries and then convert that?

    bug 
    opened by noobs2ninjas 15
  • Wrap enum in generic as workaround

    Wrap enum in generic as workaround

    Hey,

    I have lots enums used in lots of different objects, so in order to save myself a lot of coding I figured I'd try to come up with a workaround that doesn't require me to alter every object where enums are used.

    So I defined a generic class as a wrapper for my enums. EVReflection merrily serializes my enums but now they have an ugly class around them in the JSON output. I haven't gotten to parsing yet.

    Now I'm wondering how I can override the JSON serialization for the generic class to only output the enum's raw value (accessible via a protocol method implemented by the generic class) instead of the whole generic object with the enum inside. And back again when deserializing.

    Any ideas?

    enhancement fixed? 
    opened by Minthos 15
  • Errors on install pod: Generic type 'DataResponse' specialized with too few type parameters (got 1, but expected 2)

    Errors on install pod: Generic type 'DataResponse' specialized with too few type parameters (got 1, but expected 2)

    Hi, I have installed latest version of  EVReflection/Alamofire pod pod 'EVReflection/Alamofire'

    Screenshot 2021-05-27 at 12 00 09 PM

    I have faced this error initially. ERROR: Compiling for iOS 8.0, but module 'Alamofire' has a minimum deployment target of iOS 10.0 Screenshot 2021-05-27 at 11 55 49 AM

    To resolve this issue I have changed EVReflection minimum deployment target to 10.0.

    Then I faced below 2 errors at total places.

    1. Cannot specialize non-generic type 'DataResponseSerializer' -> Remove '
    2. 'Generic type 'DataResponse' specialized with too few type parameters (got 1, but expected 2) Screenshot 2021-05-27 at 11 57 49 AM

    Can you please fix that ?

    opened by krunalgoswami 0
  • XML parsing doesn't work

    XML parsing doesn't work

    XML parsing doesn't work even with an example provided in READ.ME itself.

    I've started new project with Podfile using: pod 'EVReflection' pod 'EVReflection/XML'

    Parsing collapses when nesting array of objects which is very silly. You can try using your own example for XML and it won't work.

    opened by MockinMan 0
  • Crash in NSArray

    Crash in NSArray

    Hello,

    I'm getting this crash sometimes. I am not able to reproduce this everytime.

    if theValue is Array { return (theValue as AnyObject, valueType, false) }

    Precondition failed: NSArray element failed to match the Swift Array Element type Expected CountryRatesDetailModel but found __NSDictionaryI: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1100.2.280/swift/stdlib/public/core/ArrayBuffer.swift, line 354 2021-01-04 11:33:13.527870+0530[8041:61326] Precondition failed: NSArray element failed to match the Swift Array Element type Expected CountryRatesDetailModel but found __NSDictionaryI: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1100.2.280/swift/stdlib/public/core/ArrayBuffer.swift, line 354 2021-01-04 11:35:39.520740+0530[8041:62506] XPC connection interrupted Screenshot 2021-01-04 at 11 45 35 am Screenshot 2021-01-04 at 11 44 43 am

    opened by khushbuInexture 7
  • Base object validator not called

    Base object validator not called

    I'm deserializing a JSON document that has multiple properties that aren't found in the target object and since the server-side object structure is subject to change we use the validateValue() callback to filter out properties that aren't on the local object so that we don't get NSUnknownKeyExceptions while deserializing.

    It looks like there's a logic error in EVReflection.swift that's keeping this check from being done. validateValue() exists on the target object and is set to throw an exception on invalid keys but setValue() gets called leading to an NSUnknownKeyException. The problem seems to be the check on line 989

    public static func setObjectValue<T>(_ anyObject: T, key: String, theValue: Any?, typeInObject: String? = nil, valid: Bool, conversionOptions: ConversionOptions = .DefaultDeserialize, parents: [NSObject] = []) where T: NSObject {
    ...
    (line 987) var setValue: AnyObject? = value as AnyObject?
    let validateFunction = "validate" + key.prefix(1).uppercased() + key.dropFirst() + ":error:"
    if (anyObject as AnyObject).responds(to: Selector(validateFunction)) {
        try anyObject.validateValue(&setValue, forKey: key)
    }
    anyObject.setValue(setValue, forKey: key)
    

    Which as I understand is checking if a custom key validator exists and if not call the base validator validateValue(). I think the check needs to be changed to

    if !(anyObject as AnyObject).responds(to: Selector(validateFunction)) {
        try anyObject.validateValue(&setValue, forKey: key)
    }
    

    I've been doing this in my local copy the last few times I updated the library and it seems to fix the problem without causing other side effects.

    opened by rpankhurst 0
  • Unusable With Default Settings in XCode 11.4.1

    Unusable With Default Settings in XCode 11.4.1

    XCode version: 11.4.1 OSX version: 10.15.4

    Using a default cocoapods install of the library with version 5.10.1 causes the following error as the library has an iOS 8.0 target:

    Screen Shot 2020-04-17 at 6 26 25 PM

    Compiling for iOS 8.0, but module 'Alamofire' has a minimum deployment target of iOS 10.0
    

    Screen Shot 2020-04-17 at 7 53 17 PM

    Manually setting the value to iOS 10.0 as the minimum leads to compilation errors.

    Screen Shot 2020-04-17 at 6 03 18 PM

    opened by z9fyak74amnjbvcyn4t2g 10
Releases(5.10.1)
Owner
Edwin Vermeer
Edwin Vermeer
Reflection, Dict2Model, Model2Dict, Archive

感谢小饭的翻译 中文文档 ###Selfless pay, just to make you faster to conquer swift! .Reflection .convert dictionary to model .convert model to dictionary .convert

时点软件冯成林 307 Nov 22, 2022
A Swift Runtime library for viewing type info, and the dynamic getting and setting of properties.

Runtime is a Swift library to give you more runtime abilities, including getting type metadata, setting properties via reflection, and type constructi

Wes Wickwire 970 Jan 3, 2023
Key-Value Coding (KVC) for native Swift classes and structs

SwiftKVC SwiftKVC brings key-value coding to native Swift classes and structures. You can easily set and access properties just using a subscript: var

Brad Hilton 136 Jun 14, 2022
A small package that provides a Swift API for instantiating Swift and Objective-C classes by their non-namespaced class name.

Reflection A small package that provides a Swift API for instantiating Swift and Objective-C classes by their non-namespaced class name. Installation

Kelly Dun 0 Apr 10, 2022
Reflection based (Dictionary, CKRecord, NSManagedObject, Realm, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift

EVReflection General information At this moment the master branch is tested with Swift 4.2 and 5.0 beta If you want to continue using EVReflection in

Edwin Vermeer 964 Dec 14, 2022
Realm RxSwift - This application was written in order to use Realm, RxSwift frameworks in real example

Realm_RxSwift This simple app was written to introduce basic operations of some

Elbek Khasanov 3 Apr 7, 2022
JSONNeverDie - Auto reflection tool from JSON to Model, user friendly JSON encoder / decoder, aims to never die

JSONNeverDie is an auto reflection tool from JSON to Model, a user friendly JSON encoder / decoder, aims to never die. Also JSONNeverDie is a very important part of Pitaya.

John Lui 454 Oct 30, 2022
Auto reflection tool from JSON to Model, user friendly JSON encoder / decoder, aims to never die

JSONNeverDie is an auto reflection tool from JSON to Model, a user friendly JSON encoder / decoder, aims to never die. Also JSONNeverDie is a very imp

John Lui 454 Oct 30, 2022
Simple JSON Object mapping written in Swift

ObjectMapper ObjectMapper is a framework written in Swift that makes it easy for you to convert your model objects (classes and structs) to and from J

Tristan Himmelman 9k Jan 2, 2023
Spin aims to provide a versatile Feedback Loop implementation working with the three main reactive frameworks available in the Swift community (RxSwift, ReactiveSwift and Combine)

With the introduction of Combine and SwiftUI, we will face some transition periods in our code base. Our applications will use both Combine and a thir

Spinners 119 Dec 29, 2022
A library to turn dictionary into object and vice versa for iOS. Designed for speed!

WAMapping Developed and Maintained by ipodishima Founder & CTO at Wasappli Inc. Sponsored by Wisembly A fast mapper from JSON to NSObject Fast Simple

null 8 Nov 20, 2022
🧚 RxSwift + Moya + HandyJSON + Plugins.

RxNetworks ?? . RxSwift + Moya + HandyJSON + Plugins. ?? ?? ?? English | 简体中文 This is a set of infrastructure based on RxSwift + Moya MoyaNetwork This

77。 140 Jan 3, 2023
GitTime is GitHub Tracking App. Using ReactorKit, RxSwift, Moya.

GitTime Feature Activity: GitHub Contributions graph & Event lists Trending: Trending Repositories & Developers Buddys: Show your buddy's contribution

Kanz 58 Dec 7, 2022
Reactive extensions to Cocoa frameworks, built on top of ReactiveSwift.

ReactiveSwift offers composable, declarative and flexible primitives that are built around the grand concept of streams of values over time. These primitives can be used to uniformly represent common Cocoa and generic programming patterns that are fundamentally an act of observation.

null 20k Jan 3, 2023
Set of useful extensions for ReactiveSwift & ReactiveCocoa

ACKReactiveExtensions ACKReactiveExtensions is set of useful extensions for ReactiveCocoa you could use in your apps. Currently we have extensions for

Ackee 17 Aug 12, 2022
Elegantly connect to a JSON api. (Alamofire + Promises + JSON Parsing)

⚠ Important Notice: Farewell ws... hello Networking ! Networking is the next generation of the ws project. Think of it as ws 2.0 built for iOS13. It u

Fresh 351 Oct 2, 2022
Decodable Simple and strict, yet powerful object mapping made possible by Swift 2's error handling.

Decodable Simple and strict, yet powerful object mapping made possible by Swift 2's error handling. Greatly inspired by Argo, but without a bizillion

Johannes Lund 1k Jul 15, 2022
CRUD is an object-relational mapping (ORM) system for Swift 4+.

CRUD is an object-relational mapping (ORM) system for Swift 4+. CRUD takes Swift 4 Codable types and maps them to SQL database tables. CRUD can create tables based on Codable types and perform inserts and updates of objects in those tables. CRUD can also perform selects and joins of tables, all in a type-safe manner.

PerfectlySoft Inc. 61 Nov 18, 2022
Simple REST Client based on RxSwift and Alamofire.

RxRestClient Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements iOS 10.0+ tvOS 10.

STDev 16 Nov 19, 2022
Simple REST Client based on RxSwift and Alamofire.

RxRestClient Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements iOS 10.0+ tvOS 10.

STDev 16 Nov 19, 2022