├── dao.png ├── .DS_Store ├── Example └── NioExample-iOS │ ├── podfile │ ├── NioExample-iOS.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── project.pbxproj │ ├── NioExample-iOS.xcworkspace │ └── contents.xcworkspacedata │ ├── NioExample-iOS │ ├── NioExample_iOS.xcdatamodeld │ │ ├── .xccurrentversion │ │ └── NioExample_iOS.xcdatamodel │ │ │ └── contents │ ├── ViewController.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ └── AppDelegate.swift │ └── Models │ ├── Model │ ├── CategoryModelObject.swift │ ├── AdditiveModelObject.swift │ └── PositionModelObject.swift │ ├── Plain │ ├── CategoryPlainObject.swift │ ├── AdditivePlainObject.swift │ └── PositionPlainObject.swift │ └── CoreDataModel │ └── NioModel.xcdatamodeld │ └── NioModel.xcdatamodel │ └── contents ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── SDAO.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── SDAO iOS-Tests.xcscheme │ ├── SDAO macOS-Tests.xcscheme │ ├── SDAO tvOS-Tests.xcscheme │ ├── SDAO watchOS.xcscheme │ ├── SDAO iOS.xcscheme │ ├── SDAO tvOS.xcscheme │ ├── SDAO macOS.xcscheme │ └── SDAO.xcscheme ├── SDAO.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── Sources └── SDAO │ ├── Core │ ├── Protocols │ │ ├── Model.swift │ │ └── Plain │ │ │ ├── Plain.swift │ │ │ ├── Numeric.swift │ │ │ └── UniqueID.swift │ └── Translator │ │ └── Protocols │ │ └── Translator.swift │ ├── Supporting │ ├── DAO.h │ └── Info.plist │ ├── CoreData │ └── ManagedModel │ │ └── ManagedModel.swift │ ├── Realm │ └── RealmModel │ │ └── RealmModel.swift │ └── DAO │ └── DAO.swift ├── Tests └── DAOTests │ ├── Realm │ ├── Models │ │ ├── UserModelObject.swift │ │ ├── DialogModelObject.swift │ │ └── MessageModelObject.swift │ ├── Plains │ │ ├── UserPlainObject.swift │ │ ├── DialogPlainObject.swift │ │ └── MessagePlainObject.swift │ ├── Translators │ │ ├── DialogsTranslator.swift │ │ ├── UsersTranslator.swift │ │ └── MessagesTranslator.swift │ ├── Factories │ │ └── Factories.swift │ └── RealmTests.swift │ └── Info.plist ├── SDAO.podspec ├── Package.resolved ├── LICENSE ├── Package.swift ├── .gitignore ├── .travis.yml ├── podfile └── README.md /dao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incetro/DAO/HEAD/dao.png -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incetro/DAO/HEAD/.DS_Store -------------------------------------------------------------------------------- /Example/NioExample-iOS/podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target "NioExample-iOS" do 4 | 5 | pod "NIO" 6 | 7 | end -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SDAO.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SDAO.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SDAO.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SDAO.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Sources/SDAO/Core/Protocols/Model.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Model.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 14/07/2017. 6 | // 7 | // 8 | 9 | import Monreau 10 | import CoreData 11 | 12 | // MARK: - Model 13 | 14 | /// Base protocol for all database models (CoreData, Realm...) 15 | public protocol Model: Storable { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS/NioExample_iOS.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | NioExample_iOS.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS/NioExample_iOS.xcdatamodeld/NioExample_iOS.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // NioExample-iOS 4 | // 5 | // Created by incetro on 17/07/2017. 6 | // Copyright © 2017 Incetro. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | 15 | super.viewDidLoad() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/Models/Model/CategoryModelObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CategoryModelObject.swift 3 | // Nio 4 | // 5 | // Created by incetro on 15/07/2017. 6 | // 7 | // 8 | 9 | import NIO 10 | import CoreData 11 | 12 | // MARK: - CategoryModelObject 13 | 14 | class CategoryModelObject: ManagedModel { 15 | 16 | @NSManaged var name: String 17 | @NSManaged var id: Int64 18 | @NSManaged var positions: NSSet 19 | } 20 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/Models/Model/AdditiveModelObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AdditiveModelObject.swift 3 | // Nio 4 | // 5 | // Created by incetro on 16/07/2017. 6 | // 7 | // 8 | 9 | import NIO 10 | import CoreData 11 | 12 | // MARK: - AdditiveModelObject 13 | 14 | class AdditiveModelObject: ManagedModel { 15 | 16 | @NSManaged var name: String 17 | @NSManaged var id: Int64 18 | @NSManaged var price: Double 19 | @NSManaged var position: PositionModelObject? 20 | } 21 | -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/Models/UserModelObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserModelObject.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 26/08/2018. 6 | // 7 | 8 | import SDAO 9 | import RealmSwift 10 | 11 | // MARK: - UserModelObject 12 | 13 | final class UserModelObject: RealmModel { 14 | 15 | /// User's name 16 | @objc dynamic var name: String = "" 17 | 18 | /// User's age 19 | @objc dynamic var age: Int = 0 20 | 21 | /// User's dialogs 22 | let dialogs = List() 23 | } 24 | -------------------------------------------------------------------------------- /Sources/SDAO/Supporting/DAO.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDAO.h 3 | // SDAO 4 | // 5 | // Created by incetro on 13/07/2017. 6 | // 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SDAO. 12 | FOUNDATION_EXPORT double SDAOVersionNumber; 13 | 14 | //! Project version string for SDAO. 15 | FOUNDATION_EXPORT const unsigned char SDAOVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/Models/Model/PositionModelObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PositionModelObject.swift 3 | // Nio 4 | // 5 | // Created by incetro on 15/07/2017. 6 | // 7 | // 8 | 9 | import NIO 10 | import CoreData 11 | 12 | // MARK: - PositionModelObject 13 | 14 | class PositionModelObject: ManagedModel { 15 | 16 | @NSManaged var name: String 17 | @NSManaged var id: Int64 18 | @NSManaged var price: Double 19 | @NSManaged var category: CategoryModelObject? 20 | @NSManaged var additives: NSSet 21 | } 22 | -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/Models/DialogModelObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DialogModelObject.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 07/10/2019. 6 | // 7 | 8 | import SDAO 9 | import RealmSwift 10 | 11 | // MARK: - DialogModelObject 12 | 13 | final class DialogModelObject: RealmModel { 14 | 15 | // MARK: - Properties 16 | 17 | /// True if the dialog has been pinned 18 | @objc dynamic var isPinned = false 19 | 20 | /// All available (stored) the dialog's messages 21 | let messages = List() 22 | } 23 | -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/Plains/UserPlainObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserPlainObject.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 26/08/2018. 6 | // 7 | 8 | import SDAO 9 | 10 | // MARK: - UserPlainObject 11 | 12 | struct UserPlainObject: Plain { 13 | 14 | // MARK: - Properties 15 | 16 | var uniqueId: UniqueID { 17 | return UniqueID(value: id) 18 | } 19 | 20 | /// Unique identifier 21 | let id: Int 22 | 23 | /// User's name 24 | let name: String 25 | 26 | /// User's age 27 | let age: Int 28 | 29 | /// User's dialogs 30 | let dialogs: [DialogPlainObject] 31 | } 32 | -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/Plains/DialogPlainObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DialogPlainObject.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 07/10/2019. 6 | // 7 | 8 | import SDAO 9 | 10 | // MARK: - DialogPlainObject 11 | 12 | struct DialogPlainObject: Plain { 13 | 14 | // MARK: - Properties 15 | 16 | var uniqueId: UniqueID { 17 | return UniqueID(value: id) 18 | } 19 | 20 | /// Unique id 21 | let id: Int 22 | 23 | /// True if the dialog has been pinned 24 | let isPinned: Bool 25 | 26 | /// All available (stored) the dialog's messages 27 | let messages: [MessagePlainObject] 28 | } 29 | -------------------------------------------------------------------------------- /Sources/SDAO/Core/Protocols/Plain/Plain.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Plain.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 17/07/2017. 6 | // 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - Plain 12 | 13 | /// Parent for all plain objects 14 | public protocol Plain { 15 | 16 | /// Unique identifier 17 | var uniqueId: UniqueID { get } 18 | } 19 | 20 | public extension Plain { 21 | 22 | /// Comparison function 23 | /// 24 | /// - Parameter other: entity compare with. 25 | /// - Returns: result of comparison. 26 | func equals(_ other: T) -> Bool where T: Plain { 27 | return self.uniqueId == other.uniqueId 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/SDAO/CoreData/ManagedModel/ManagedModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ManagedModel.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 15/07/2017. 6 | // 7 | // 8 | 9 | import CoreData 10 | 11 | // MARK: - ManagedModel 12 | 13 | /// If you use CoreData you must inherit your models from this class 14 | open class ManagedModel: NSManagedObject, Model { 15 | 16 | /// Primary key 17 | @NSManaged var uniqueId: String 18 | 19 | /// Primary key type = String for all models 20 | public typealias PrimaryType = String 21 | 22 | /// Primary key name 23 | public static var primaryKey: String { 24 | return "uniqueId" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Tests/DAOTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/Models/MessageModelObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessageModelObject.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 07/10/2019. 6 | // 7 | 8 | import SDAO 9 | import Foundation 10 | 11 | // MARK: - MessageModelObject 12 | 13 | final class MessageModelObject: RealmModel { 14 | 15 | /// Sending date 16 | @objc dynamic var date = Date() 17 | 18 | /// Message text 19 | @objc dynamic var text = "" 20 | 21 | /// Receiver's id 22 | @objc dynamic var receiverId = 0 23 | 24 | /// Sender's id 25 | @objc dynamic var senderId = 0 26 | 27 | /// Message type 28 | @objc dynamic var type = 0 29 | 30 | /// True if the message is incoming 31 | @objc dynamic var isIncoming = false 32 | 33 | /// True if the message has been read 34 | @objc dynamic var isRead = false 35 | } 36 | -------------------------------------------------------------------------------- /Sources/SDAO/Realm/RealmModel/RealmModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RealmModel.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 06/01/2018. 6 | // 7 | 8 | import RealmSwift 9 | import Foundation 10 | 11 | // MARK: - RealmModelWrapper 12 | 13 | open class RealmModelWrapper: Object { 14 | 15 | /// Primary key 16 | @objc dynamic public var uniqueId = "" 17 | 18 | // MARK: - Object 19 | 20 | public override class func primaryKey() -> String? { 21 | return "uniqueId" 22 | } 23 | } 24 | 25 | // MARK: - RealmModel 26 | 27 | open class RealmModel: RealmModelWrapper, Model { 28 | 29 | /// Primary key type = String for all models 30 | public typealias PrimaryType = String 31 | 32 | /// Primary key name 33 | public static var primaryKey: String { 34 | return "uniqueId" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sources/SDAO/Supporting/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/Plains/MessagePlainObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessagePlainObject.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 07/10/2019. 6 | // 7 | 8 | import SDAO 9 | import Foundation 10 | 11 | // MARK: - MessagePlainObject 12 | 13 | struct MessagePlainObject: Plain { 14 | 15 | // MARK: - Properties 16 | 17 | var uniqueId: UniqueID { 18 | return UniqueID(value: id) 19 | } 20 | 21 | /// Unique identifier 22 | let id: Int 23 | 24 | /// Sending date 25 | let date: Date 26 | 27 | /// Message text 28 | let text: String 29 | 30 | /// Sender's id 31 | let senderId: Int 32 | 33 | /// Receiver's id 34 | let receiverId: Int 35 | 36 | /// Message type 37 | let type: Int 38 | 39 | /// True if the message is incoming 40 | let isIncoming: Bool 41 | 42 | /// True if the message has been read 43 | let isRead: Bool 44 | } 45 | -------------------------------------------------------------------------------- /SDAO.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = "SDAO" 3 | spec.version = "2.6.0" 4 | spec.summary = "Elegant DAO implementation written in Swift" 5 | 6 | spec.homepage = "https://github.com/incetro/DAO.git" 7 | spec.license = "MIT" 8 | spec.authors = { "incetro" => "incetro@ya.ru" } 9 | spec.requires_arc = true 10 | spec.swift_version = "5.2" 11 | 12 | spec.ios.deployment_target = "13.0" 13 | spec.osx.deployment_target = "10.15" 14 | spec.watchos.deployment_target = "6.0" 15 | spec.tvos.deployment_target = "12.4" 16 | 17 | spec.source = { git: "https://github.com/incetro/DAO.git", tag: "#{spec.version}"} 18 | spec.source_files = "Sources/SDAO/**/*.{h,swift}" 19 | 20 | spec.dependency "Monreau" 21 | spec.dependency "Realm" 22 | spec.dependency "RealmSwift" 23 | end 24 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/Models/Plain/CategoryPlainObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CategoryPlainObject.swift 3 | // Nio 4 | // 5 | // Created by incetro on 15/07/2017. 6 | // 7 | // 8 | 9 | import NIO 10 | import Transformer 11 | 12 | // MARK: - CategoryPlainObject 13 | 14 | class CategoryPlainObject: TransformablePlain { 15 | 16 | var nioID: NioID { 17 | 18 | return NioID(value: id) 19 | } 20 | 21 | let id: Int64 22 | let name: String 23 | 24 | var positions: [PositionPlainObject] = [] 25 | 26 | init(with name: String, id: Int64) { 27 | 28 | self.name = name 29 | self.id = id 30 | } 31 | 32 | required init(with resolver: Resolver) throws { 33 | 34 | self.id = try resolver.value("id") 35 | self.name = try resolver.value("name") 36 | 37 | self.positions = (try? resolver.value("positions")) ?? [] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Sources/SDAO/Core/Protocols/Plain/Numeric.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Numeric.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 17/07/2017. 6 | // 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - Numeric 12 | 13 | public protocol Numeric { 14 | } 15 | 16 | // MARK: - Int 17 | 18 | extension Int: Numeric { 19 | } 20 | 21 | // MARK: - Int8 22 | 23 | extension Int8: Numeric { 24 | } 25 | 26 | // MARK: - Int16 27 | 28 | extension Int16: Numeric { 29 | } 30 | 31 | // MARK: - Int32 32 | 33 | extension Int32: Numeric { 34 | } 35 | 36 | // MARK: - Int64 37 | 38 | extension Int64: Numeric { 39 | } 40 | 41 | // MARK: - UInt 42 | 43 | extension UInt: Numeric { 44 | } 45 | 46 | // MARK: - UInt8 47 | 48 | extension UInt8: Numeric { 49 | } 50 | 51 | // MARK: - UInt16 52 | 53 | extension UInt16: Numeric { 54 | } 55 | 56 | // MARK: - UInt32 57 | 58 | extension UInt32: Numeric { 59 | } 60 | 61 | // MARK: - UInt64 62 | 63 | extension UInt64: Numeric { 64 | } 65 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "Monreau", 6 | "repositoryURL": "https://github.com/Incetro/Monreau.git", 7 | "state": { 8 | "branch": "master", 9 | "revision": "0e0eb77d1cfaf808659b4be9df0e90577916e14e", 10 | "version": null 11 | } 12 | }, 13 | { 14 | "package": "RealmDatabase", 15 | "repositoryURL": "https://github.com/realm/realm-core.git", 16 | "state": { 17 | "branch": null, 18 | "revision": "f1e962cd447f8b69f8f7cf46a188b1c6246923c5", 19 | "version": "13.17.0" 20 | } 21 | }, 22 | { 23 | "package": "Realm", 24 | "repositoryURL": "https://github.com/realm/realm-swift.git", 25 | "state": { 26 | "branch": null, 27 | "revision": "0155caac1a0830a9fbaaffe5866b909fad3a6fc4", 28 | "version": "10.41.1" 29 | } 30 | } 31 | ] 32 | }, 33 | "version": 1 34 | } 35 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/Models/Plain/AdditivePlainObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AdditivePlainObject.swift 3 | // Nio 4 | // 5 | // Created by incetro on 16/07/2017. 6 | // 7 | // 8 | 9 | import NIO 10 | import Transformer 11 | 12 | // MARK: - AdditivePlainObject 13 | 14 | class AdditivePlainObject: TransformablePlain { 15 | 16 | var nioID: NioID { 17 | 18 | return NioID(value: id) 19 | } 20 | 21 | let id: Int64 22 | let name: String 23 | let price: Double 24 | 25 | init(with name: String, price: Double, id: Int64) { 26 | 27 | self.name = name 28 | self.id = id 29 | self.price = price 30 | } 31 | 32 | var position: PositionPlainObject? = nil 33 | 34 | required init(with resolver: Resolver) throws { 35 | 36 | self.id = try resolver.value("id") 37 | self.name = try resolver.value("name") 38 | self.price = try resolver.value("price") 39 | self.position = try? resolver.value("position") 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/SDAO/Core/Protocols/Plain/UniqueID.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UniqueID.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 17/07/2017. 6 | // 7 | // 8 | 9 | import Foundation 10 | 11 | // MARK: - UniqueID 12 | 13 | /// Primary key for all Plain objects 14 | 15 | public struct UniqueID: RawRepresentable, Hashable { 16 | 17 | // MARK: - RawRepresentable 18 | 19 | /// String value 20 | public let rawValue: String 21 | 22 | // MARK: - Initializers 23 | 24 | /// Default initializer 25 | /// 26 | /// - Parameter rawValue: string value 27 | public init(rawValue: String) { 28 | self.rawValue = rawValue 29 | } 30 | 31 | /// Generic initializer (when id is not string) 32 | /// 33 | /// - Parameter value: some numeric value 34 | public init(value: Numeric) { 35 | self.rawValue = String(describing: value) 36 | } 37 | } 38 | 39 | // MARK: - RawRepresentable 40 | 41 | public extension RawRepresentable where RawValue: Hashable { 42 | var hashValue: Int { 43 | return rawValue.hashValue 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Andrew 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/Models/Plain/PositionPlainObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PositionPlainObject.swift 3 | // Nio 4 | // 5 | // Created by incetro on 15/07/2017. 6 | // 7 | // 8 | 9 | import NIO 10 | import Transformer 11 | 12 | // MARK: - PositionPlainObject 13 | 14 | class PositionPlainObject: TransformablePlain { 15 | 16 | var nioID: NioID { 17 | 18 | return NioID(value: id) 19 | } 20 | 21 | let id: Int64 22 | let name: String 23 | let price: Double 24 | 25 | init(with name: String, price: Double, id: Int64) { 26 | 27 | self.name = name 28 | self.id = id 29 | self.price = price 30 | } 31 | 32 | var category: CategoryPlainObject? = nil 33 | var additives: [AdditivePlainObject] = [] 34 | 35 | required init(with resolver: Resolver) throws { 36 | 37 | self.id = try resolver.value("id") 38 | self.name = try resolver.value("name") 39 | self.price = try resolver.value("price") 40 | self.category = try? resolver.value("category") 41 | 42 | self.additives = (try? resolver.value("additives")) ?? [] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.2 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "SDAO", 8 | platforms: [ 9 | .iOS(.v13), 10 | .macOS(.v10_15), 11 | .watchOS(.v6), 12 | .tvOS(.v12) 13 | ], 14 | products: [ 15 | .library( 16 | name: "SDAO", 17 | targets: ["SDAO"] 18 | ), 19 | ], 20 | dependencies: [ 21 | .package(url: "https://github.com/realm/realm-swift.git", from: "10.31.0"), 22 | .package(url: "https://github.com/Incetro/Monreau.git", .branch("master")) 23 | ], 24 | targets: [ 25 | .target( 26 | name: "SDAO", 27 | dependencies: [ 28 | "Monreau", 29 | .product(name: "RealmSwift", package: "realm-swift") 30 | ] 31 | ), 32 | .testTarget( 33 | name: "DAOTests", 34 | dependencies: [ 35 | "SDAO", 36 | "Monreau", 37 | .product(name: "RealmSwift", package: "realm-swift") 38 | ] 39 | ), 40 | ] 41 | ) 42 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | .build/ 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 47 | # 48 | Pods/ 49 | Podfile.lock 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/Translators/DialogsTranslator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DialogsTranslator.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 07/10/2019. 6 | // 7 | 8 | import SDAO 9 | import Monreau 10 | 11 | // MARK: - DialogsTranslator 12 | 13 | final class DialogsTranslator { 14 | 15 | // MARK: - Aliases 16 | 17 | typealias PlainModel = DialogPlainObject 18 | typealias DatabaseModel = DialogModelObject 19 | 20 | private lazy var dialogStorage = RealmStorage( 21 | configuration: RealmConfiguration(inMemoryIdentifier: "DAO") 22 | ) 23 | } 24 | 25 | // MARK: - Translator 26 | 27 | extension DialogsTranslator: Translator { 28 | 29 | func translate(model: DatabaseModel) throws -> PlainModel { 30 | DialogPlainObject( 31 | id: Int(model.uniqueId) ?? 0, 32 | isPinned: model.isPinned, 33 | messages: try MessagesTranslator().translate( 34 | models: Array(model.messages) 35 | ) 36 | ) 37 | } 38 | 39 | func translate(plain: PlainModel) throws -> DatabaseModel { 40 | let model = try dialogStorage.read(byPrimaryKey: plain.uniqueId.rawValue) ?? DialogModelObject() 41 | try translate(from: plain, to: model) 42 | return model 43 | } 44 | 45 | func translate(from plain: PlainModel, to databaseModel: DatabaseModel) throws { 46 | if databaseModel.uniqueId.isEmpty { 47 | databaseModel.uniqueId = plain.uniqueId.rawValue 48 | } 49 | databaseModel.isPinned = plain.isPinned 50 | databaseModel.messages.removeAll() 51 | databaseModel.messages.append( 52 | objectsIn: try MessagesTranslator().translate( 53 | plains: plain.messages 54 | ) 55 | ) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/Translators/UsersTranslator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UsersTranslator.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 26/08/2018. 6 | // 7 | 8 | import SDAO 9 | import Monreau 10 | 11 | // MARK: - UsersTranslator 12 | 13 | final class UsersTranslator { 14 | 15 | // MARK: - Aliases 16 | 17 | typealias PlainModel = UserPlainObject 18 | typealias DatabaseModel = UserModelObject 19 | 20 | private lazy var userStorage = RealmStorage( 21 | configuration: RealmConfiguration(inMemoryIdentifier: "DAO") 22 | ) 23 | } 24 | 25 | // MARK: - Translator 26 | 27 | extension UsersTranslator: Translator { 28 | 29 | func translate(model: DatabaseModel) throws -> PlainModel { 30 | UserPlainObject( 31 | id: Int(model.uniqueId) ?? 0, 32 | name: model.name, 33 | age: model.age, 34 | dialogs: try DialogsTranslator().translate( 35 | models: Array(model.dialogs) 36 | ) 37 | ) 38 | } 39 | 40 | func translate(plain: PlainModel) throws -> DatabaseModel { 41 | let model = try userStorage.read(byPrimaryKey: plain.uniqueId.rawValue) ?? UserModelObject() 42 | try translate(from: plain, to: model) 43 | return model 44 | } 45 | 46 | func translate(from plain: PlainModel, to databaseModel: DatabaseModel) throws { 47 | if databaseModel.uniqueId.isEmpty { 48 | databaseModel.uniqueId = plain.uniqueId.rawValue 49 | } 50 | databaseModel.age = plain.age 51 | databaseModel.name = plain.name 52 | databaseModel.dialogs.removeAll() 53 | databaseModel.dialogs.append( 54 | objectsIn: try DialogsTranslator().translate( 55 | plains: Array(plain.dialogs) 56 | ) 57 | ) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | osx_image: xcode11.4 2 | xcode_workspace: SDAO.xcworkspace 3 | matrix: 4 | include: 5 | 6 | - xcode_scheme: SDAO macOS 7 | language: swift 8 | env: 9 | - XCODE_SDK=macosx10.13 10 | - XCODE_ACTION="test" 11 | - XCODE_DESTINATION="arch=x86_64" 12 | 13 | - xcode_scheme: SDAO iOS 14 | language: swift 15 | env: 16 | - XCODE_SDK=iphonesimulator11.0 17 | - XCODE_ACTION="test" 18 | - XCODE_DESTINATION="platform=iOS Simulator,OS=9.3,name=iPhone SE" 19 | 20 | - xcode_scheme: SDAO tvOS 21 | language: swift 22 | env: 23 | - XCODE_SDK=appletvsimulator11.0 24 | - XCODE_ACTION="test" 25 | - XCODE_DESTINATION="platform=tvOS Simulator,OS=10.2,name=Apple TV 1080p" 26 | 27 | - xcode_scheme: SDAO watchOS 28 | language: swift 29 | env: 30 | - XCODE_SDK=watchsimulator4.0 31 | - XCODE_ACTION="build" 32 | - XCODE_DESTINATION="platform=watchOS Simulator,name=Apple Watch - 38mm" 33 | install: 34 | - if [[ `uname` == "Linux" ]] ; then 35 | eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)"; 36 | fi 37 | script: 38 | - if [[ `uname` == "Linux" ]] ; then 39 | swift test; 40 | fi 41 | 42 | - if [[ `uname` == "Darwin" ]] ; then 43 | pod install 44 | set -o pipefail; 45 | xcodebuild -version; 46 | xcodebuild -showsdks; 47 | instruments -s devices; 48 | travis_retry xcodebuild -workspace "$TRAVIS_XCODE_WORKSPACE" -scheme "$TRAVIS_XCODE_SCHEME" -sdk "$XCODE_SDK" -destination "$XCODE_DESTINATION" -configuration Debug ENABLE_TESTABILITY=YES $XCODE_ACTION | xcpretty; 49 | fi 50 | after_success: 51 | - sleep 5 # workaround https://github.com/travis-ci/travis-ci/issues/4725 52 | -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/Translators/MessagesTranslator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MessagesTranslator.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 07/10/2019. 6 | // 7 | 8 | import SDAO 9 | import Monreau 10 | 11 | // MARK: - MessagesTranslator 12 | 13 | final class MessagesTranslator { 14 | 15 | // MARK: - Aliases 16 | 17 | typealias PlainModel = MessagePlainObject 18 | typealias DatabaseModel = MessageModelObject 19 | 20 | private lazy var messageStorage = RealmStorage( 21 | configuration: RealmConfiguration(inMemoryIdentifier: "DAO") 22 | ) 23 | } 24 | 25 | // MARK: - Translator 26 | 27 | extension MessagesTranslator: Translator { 28 | 29 | func translate(model: DatabaseModel) throws -> PlainModel { 30 | MessagePlainObject( 31 | id: Int(model.uniqueId) ?? 0, 32 | date: model.date, 33 | text: model.text, 34 | senderId: model.senderId, 35 | receiverId: model.receiverId, 36 | type: model.type, 37 | isIncoming: model.isIncoming, 38 | isRead: model.isRead 39 | ) 40 | } 41 | 42 | func translate(plain: PlainModel) throws -> DatabaseModel { 43 | let model = try messageStorage.read(byPrimaryKey: plain.uniqueId.rawValue) ?? MessageModelObject() 44 | try translate(from: plain, to: model) 45 | return model 46 | } 47 | 48 | func translate(from plain: PlainModel, to databaseModel: DatabaseModel) throws { 49 | if databaseModel.uniqueId.isEmpty { 50 | databaseModel.uniqueId = plain.uniqueId.rawValue 51 | } 52 | databaseModel.date = plain.date 53 | databaseModel.isIncoming = plain.isIncoming 54 | databaseModel.isRead = plain.isRead 55 | databaseModel.senderId = plain.senderId 56 | databaseModel.text = plain.text 57 | databaseModel.type = plain.type 58 | databaseModel.receiverId = plain.receiverId 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /SDAO.xcodeproj/xcshareddata/xcschemes/SDAO iOS-Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 44 | 45 | 47 | 48 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /SDAO.xcodeproj/xcshareddata/xcschemes/SDAO macOS-Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 44 | 45 | 47 | 48 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /SDAO.xcodeproj/xcshareddata/xcschemes/SDAO tvOS-Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 14 | 15 | 17 | 23 | 24 | 25 | 26 | 27 | 37 | 38 | 44 | 45 | 47 | 48 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/Factories/Factories.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Factories.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 07/10/2019. 6 | // 7 | 8 | import Foundation 9 | 10 | // MARK: - UsersFactory 11 | 12 | final class UsersFactory { 13 | 14 | func users(count: Int = 100) -> [UserPlainObject] { 15 | let users = (0.. [DialogPlainObject] { 32 | let dialogs = (0.. [MessagePlainObject] { 48 | var messages: [MessagePlainObject] = [] 49 | for index in 0.. 'https://github.com/Incetro/Monreau', :branch => "master" 5 | end 6 | 7 | target "SDAO iOS" do 8 | platform :ios, "13.0" 9 | standard_pods 10 | end 11 | 12 | target "SDAO iOS-Tests" do 13 | platform :ios, "13.0" 14 | standard_pods 15 | end 16 | 17 | target "SDAO watchOS" do 18 | platform :watchos, "6.0" 19 | standard_pods 20 | end 21 | 22 | target "SDAO tvOS" do 23 | platform :tvos, "12.4" 24 | standard_pods 25 | end 26 | 27 | target "SDAO tvOS-Tests" do 28 | platform :tvos, "12.4" 29 | standard_pods 30 | end 31 | 32 | target "SDAO macOS" do 33 | platform :osx, "10.15" 34 | standard_pods 35 | end 36 | 37 | target "SDAO macOS-Tests" do 38 | platform :osx, "10.15" 39 | standard_pods 40 | end 41 | 42 | post_install do |installer| 43 | installer.pods_project.targets.each do |target| 44 | installer.aggregate_targets.each do |target| 45 | target.xcconfigs.each do |variant, xcconfig| 46 | xcconfig_path = target.client_root + target.xcconfig_relative_path(variant) 47 | IO.write(xcconfig_path, IO.read(xcconfig_path).gsub("DT_TOOLCHAIN_DIR", "TOOLCHAIN_DIR")) 48 | end 49 | end 50 | installer.pods_project.targets.each do |target| 51 | target.build_configurations.each do |config| 52 | if config.base_configuration_reference.is_a? Xcodeproj::Project::Object::PBXFileReference 53 | xcconfig_path = config.base_configuration_reference.real_path 54 | IO.write(xcconfig_path, IO.read(xcconfig_path).gsub("DT_TOOLCHAIN_DIR", "TOOLCHAIN_DIR")) 55 | end 56 | end 57 | end 58 | target.build_configurations.each do |config| 59 | # This works around a unit test issue introduced in Xcode 10. 60 | # We only apply it to the Debug configuration to avoid bloating the app size 61 | if config.name == "Debug" && defined?(target.product_type) && target.product_type == "com.apple.product-type.framework" 62 | config.build_settings['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = "YES" 63 | end 64 | end 65 | end 66 | installer.pods_project.build_configurations.each do |config| 67 | config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64" 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/Models/CoreDataModel/NioModel.xcdatamodeld/NioModel.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /SDAO.xcodeproj/xcshareddata/xcschemes/SDAO watchOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Sources/SDAO/Core/Translator/Protocols/Translator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Translator.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 14/07/2017. 6 | // 7 | // 8 | 9 | import Monreau 10 | import Foundation 11 | 12 | // MARK: - Translator 13 | 14 | /// Base protocol for Trnalsators that translate database models to plain objects 15 | public protocol Translator { 16 | 17 | associatedtype DatabaseModel: Model 18 | associatedtype PlainModel: Plain 19 | 20 | /// Convert database model to plain object 21 | /// 22 | /// - Parameter model: database model 23 | /// - Returns: plain object 24 | /// - Throws: translation error 25 | func translate(model: DatabaseModel) throws -> PlainModel 26 | 27 | /// Convert database models to plain objects 28 | /// 29 | /// - Parameter models: database models 30 | /// - Returns: plain objects 31 | /// - Throws: translation error 32 | func translate(models: [DatabaseModel]) throws -> [PlainModel] 33 | 34 | /// Convert plain object to database model 35 | /// 36 | /// - Parameter model: plain object 37 | /// - Returns: database model 38 | /// - Throws: translation error 39 | func translate(plain: PlainModel) throws -> DatabaseModel 40 | 41 | /// Convert plain objects to database models 42 | /// 43 | /// - Parameter plains: plain objects 44 | /// - Returns: database models 45 | /// - Throws: translation error 46 | func translate(plains: [PlainModel]) throws -> [DatabaseModel] 47 | 48 | /// Translates data from the given plain object to the given database model 49 | /// - Parameter plain: some plain object 50 | /// - Parameter databaseModel: some database model 51 | func translate(from plain: PlainModel, to databaseModel: DatabaseModel) throws 52 | 53 | /// Translates data from the given plain object to the given database model 54 | /// - Parameter plain: some plain object 55 | /// - Parameter databaseModel: some database model 56 | func translate(from plains: [PlainModel], to databaseModels: [DatabaseModel]) throws 57 | } 58 | 59 | public extension Translator { 60 | 61 | /// Convert database models to plain objects 62 | /// 63 | /// - Parameter models: database models 64 | /// - Returns: plain objects 65 | /// - Throws: translation error 66 | func translate(models: [DatabaseModel]) throws -> [PlainModel] { 67 | return try models.map(translate) 68 | } 69 | 70 | /// Convert plain objects to database models 71 | /// 72 | /// - Parameter plains: plain objects 73 | /// - Returns: database models 74 | /// - Throws: translation error 75 | func translate(plains: [PlainModel]) throws -> [DatabaseModel] { 76 | return try plains.map(translate) 77 | } 78 | 79 | /// Translates data from the given plain object to the given database model 80 | /// - Parameter plain: some plain object 81 | /// - Parameter databaseModel: some database model 82 | func translate(from plains: [PlainModel], to databaseModels: [DatabaseModel]) throws { 83 | guard plains.count == databaseModels.count else { 84 | let error = NSError( 85 | domain: "com.dao.translator", 86 | code: 1000, 87 | userInfo: [ 88 | NSLocalizedDescriptionKey : "Plain objects count must be equal to database objects count" 89 | ] 90 | ) 91 | throw error 92 | } 93 | for (plain, model) in zip(plains, databaseModels) { 94 | try translate(from: plain, to: model) 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /SDAO.xcodeproj/xcshareddata/xcschemes/SDAO iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /SDAO.xcodeproj/xcshareddata/xcschemes/SDAO tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /SDAO.xcodeproj/xcshareddata/xcschemes/SDAO macOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Tests/DAOTests/Realm/RealmTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RealmTests.swift 3 | // SDAO 4 | // 5 | // Created by incetro on 26/08/2018. 6 | // 7 | 8 | import RealmSwift 9 | import Monreau 10 | import XCTest 11 | import SDAO 12 | 13 | // MARK: - RealmTests 14 | 15 | class RealmTests: XCTestCase { 16 | 17 | // MARK: - Properties 18 | 19 | private let configuration = RealmConfiguration(inMemoryIdentifier: "DAO") 20 | private lazy var dao = DAO( 21 | storage: RealmStorage( 22 | configuration: configuration 23 | ), 24 | translator: UsersTranslator() 25 | ) 26 | 27 | // MARK: - Helpers 28 | 29 | func printTimeElapsedWhenRunningCode(title: String, operation: () throws -> ()) { 30 | let startTime = CFAbsoluteTimeGetCurrent() 31 | do { 32 | try operation() 33 | } catch { 34 | XCTFail(error.localizedDescription) 35 | } 36 | let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime 37 | print("Time elapsed for \(title): \(timeElapsed) s.") 38 | } 39 | 40 | // MARK: - Tests 41 | 42 | /// Tests `create` and `read by primary key` methods 43 | func testDAO1() { 44 | 45 | /// given 46 | 47 | let usersCount = 10 48 | let users = UsersFactory().users(count: usersCount) 49 | 50 | let objectsCount = users.reduce(0) { (result, user) in 51 | result + user.dialogs.reduce(0) { (result, dialog) in 52 | result + dialog.messages.count 53 | } 54 | } 55 | 56 | print("Test objects count: \(objectsCount)") 57 | 58 | /// when 59 | 60 | printTimeElapsedWhenRunningCode(title: "create") { 61 | XCTAssertNoThrow(try dao.create(users)) 62 | } 63 | 64 | /// then 65 | 66 | do { 67 | XCTAssertEqual(usersCount, try dao.read().count) 68 | for user in users { 69 | guard let object = try dao.read(byPrimaryKey: user.uniqueId) else { 70 | XCTFail("Object must exist here") 71 | return 72 | } 73 | XCTAssertEqual(user.id, object.id) 74 | XCTAssertEqual(user.age, object.age) 75 | XCTAssertEqual(user.name, object.name) 76 | } 77 | } catch { 78 | XCTFail(error.localizedDescription) 79 | } 80 | } 81 | 82 | /// Tests `persist` and `read by primary key` methods 83 | func testDAO2() { 84 | 85 | /// given 86 | 87 | let usersCount = 10 88 | let users = UsersFactory().users(count: usersCount) 89 | 90 | let objectsCount = users.reduce(0) { (result, user) in 91 | result + user.dialogs.reduce(0) { (result, dialog) in 92 | result + dialog.messages.count 93 | } 94 | } 95 | 96 | print("Test objects count: \(objectsCount)") 97 | 98 | /// when 99 | 100 | printTimeElapsedWhenRunningCode(title: "create") { 101 | XCTAssertNoThrow(try dao.create(users)) 102 | } 103 | 104 | let newAge = 13 105 | let newUsers = users.map { 106 | UserPlainObject( 107 | id: $0.id, 108 | name: $0.name, 109 | age: newAge, 110 | dialogs: $0.dialogs 111 | ) 112 | } 113 | 114 | printTimeElapsedWhenRunningCode(title: "persist") { 115 | XCTAssertNoThrow(try dao.persist(newUsers)) 116 | } 117 | 118 | /// then 119 | 120 | do { 121 | XCTAssertEqual(usersCount, try dao.read().count) 122 | for user in newUsers { 123 | guard let object = try dao.read(byPrimaryKey: user.uniqueId) else { 124 | XCTFail("Object must exist here") 125 | return 126 | } 127 | XCTAssertEqual(user.id, object.id) 128 | XCTAssertEqual(user.age, object.age) 129 | XCTAssertEqual(user.name, object.name) 130 | } 131 | } catch { 132 | XCTFail(error.localizedDescription) 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /SDAO.xcodeproj/xcshareddata/xcschemes/SDAO.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 57 | 63 | 64 | 65 | 66 | 67 | 72 | 73 | 79 | 80 | 81 | 82 | 83 | 84 | 94 | 95 | 101 | 102 | 103 | 104 | 110 | 111 | 117 | 118 | 119 | 120 | 122 | 123 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // NioExample-iOS 4 | // 5 | // Created by incetro on 17/07/2017. 6 | // Copyright © 2017 Incetro. All rights reserved. 7 | // 8 | 9 | import NIO 10 | import UIKit 11 | import CoreData 12 | 13 | @UIApplicationMain 14 | class AppDelegate: UIResponder, UIApplicationDelegate { 15 | 16 | var window: UIWindow? 17 | 18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 19 | 20 | let dao = Nio.coredata(named: "NioModel", model: CategoryModelObject.self, plain: CategoryPlainObject.self) 21 | 22 | do { 23 | 24 | let category = CategoryPlainObject(with: "Category #1", id: 1) 25 | let position = PositionPlainObject(with: "Position #1", price: 225.0, id: 1) 26 | 27 | position.additives = [ 28 | 29 | AdditivePlainObject(with: "Additive #1", price: 20.0, id: 1), 30 | AdditivePlainObject(with: "Additive #2", price: 30.0, id: 2) 31 | ] 32 | 33 | category.positions = [position] 34 | 35 | try dao.persist(category) 36 | 37 | if let savedCategory = try dao.read(byPrimaryKey: category.nioID) { 38 | 39 | try dao.erase(byPrimaryKey: savedCategory.nioID) 40 | } 41 | 42 | try dao.erase() 43 | 44 | } catch { 45 | 46 | fatalError(error.localizedDescription) 47 | } 48 | 49 | return true 50 | } 51 | 52 | func applicationWillResignActive(_ application: UIApplication) { 53 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 54 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 55 | } 56 | 57 | func applicationDidEnterBackground(_ application: UIApplication) { 58 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 59 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 60 | } 61 | 62 | func applicationWillEnterForeground(_ application: UIApplication) { 63 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 64 | } 65 | 66 | func applicationDidBecomeActive(_ application: UIApplication) { 67 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 68 | } 69 | 70 | func applicationWillTerminate(_ application: UIApplication) { 71 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 72 | // Saves changes in the application's managed object context before the application terminates. 73 | self.saveContext() 74 | } 75 | 76 | // MARK: - Core Data stack 77 | 78 | lazy var persistentContainer: NSPersistentContainer = { 79 | /* 80 | The persistent container for the application. This implementation 81 | creates and returns a container, having loaded the store for the 82 | application to it. This property is optional since there are legitimate 83 | error conditions that could cause the creation of the store to fail. 84 | */ 85 | let container = NSPersistentContainer(name: "NioExample_iOS") 86 | container.loadPersistentStores(completionHandler: { (storeDescription, error) in 87 | if let error = error as NSError? { 88 | // Replace this implementation with code to handle the error appropriately. 89 | // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 90 | 91 | /* 92 | Typical reasons for an error here include: 93 | * The parent directory does not exist, cannot be created, or disallows writing. 94 | * The persistent store is not accessible, due to permissions or data protection when the device is locked. 95 | * The device is out of space. 96 | * The store could not be migrated to the current model version. 97 | Check the error message to determine what the actual problem was. 98 | */ 99 | fatalError("Unresolved error \(error), \(error.userInfo)") 100 | } 101 | }) 102 | return container 103 | }() 104 | 105 | // MARK: - Core Data Saving support 106 | 107 | func saveContext () { 108 | let context = persistentContainer.viewContext 109 | if context.hasChanges { 110 | do { 111 | try context.save() 112 | } catch { 113 | // Replace this implementation with code to handle the error appropriately. 114 | // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 115 | let nserror = error as NSError 116 | fatalError("Unresolved error \(nserror), \(nserror.userInfo)") 117 | } 118 | } 119 | } 120 | 121 | } 122 | 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](dao.png) 2 | 3 |

DAO

4 | 5 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 | 31 | An implementation of [DAO pattern](http://www.oracle.com/technetwork/java/dataaccessobject-138824.html) for CoreData and Realm. 32 | Now you can think less about database in your applications. 33 | 34 | - [Features](#features) 35 | - [Supported frameworks](#supported-frameworks) 36 | - [Usage](#usage) 37 | - [How it works](#how-it-works) 38 | - [Requirements](#requirements) 39 | - [Communication](#communication) 40 | - [Installation](#installation) 41 | - [Author](#author) 42 | - [License](#license) 43 | 44 | ## Features 45 | - [x] CRUD operations for your database based on [Monreau](https://github.com/incetro/Monreau) 46 | - [x] Abstraction of database objects (models) from application objects (plains) 47 | 48 | ## Supported frameworks 49 | - [x] CoreData 50 | - [x] Realm 51 | 52 | ## Usage 53 | 54 | ```swift 55 | import Monreau 56 | import DAO 57 | 58 | /// Create DAO instance 59 | let dao = DAO( 60 | storage: RealmStorage, 61 | translator: UsersTranslator() 62 | ) 63 | 64 | // Obtain messages (from backend for example) 65 | let messages = messagesService.obtainMessages() 66 | 67 | /// Save messages 68 | try dao.persist(messages) 69 | 70 | /// Obtain some info from database 71 | let count = try dao.read().count 72 | 73 | /// Erase all messages from database 74 | try dao.erase() 75 | ``` 76 | 77 | ## How it works 78 | 79 | 1. Create some database model class 80 | 81 | ```swift 82 | // MARK: - DialogModelObject 83 | 84 | final class DialogModelObject: RealmModel { 85 | 86 | // MARK: - Properties 87 | 88 | /// True if the dialog has been pinned 89 | @objc dynamic var isPinned = false 90 | 91 | /// All available (stored) the dialog's messages 92 | let messages = List() 93 | } 94 | 95 | // MARK: - MessageModelObject 96 | 97 | final class MessageModelObject: RealmModel { 98 | 99 | /// Sending date 100 | @objc dynamic var date = Date() 101 | 102 | /// Message text 103 | @objc dynamic var text = "" 104 | 105 | /// Receiver's id 106 | @objc dynamic var receiverId = 0 107 | 108 | /// Sender's id 109 | @objc dynamic var senderId = 0 110 | 111 | /// Message type 112 | @objc dynamic var type = 0 113 | 114 | /// True if the message is incoming 115 | @objc dynamic var isIncoming = false 116 | 117 | /// True if the message has been read 118 | @objc dynamic var isRead = false 119 | } 120 | ``` 121 | 122 | 2. Create plain object class/struct 123 | 124 | 125 | ```swift 126 | import DAO 127 | import Foundation 128 | 129 | // MARK: - MessagePlainObject 130 | 131 | struct MessagePlainObject: Plain { 132 | 133 | // MARK: - Plain 134 | 135 | var uniqueId: UniqueID { 136 | return UniqueID(value: id) 137 | } 138 | 139 | // MARK: - Properties 140 | 141 | /// Unique identifier 142 | let id: Int 143 | 144 | /// Sending date 145 | let date: Date 146 | 147 | /// Message text 148 | let text: String 149 | 150 | /// Sender's id 151 | let senderId: Int 152 | 153 | /// Receiver's id 154 | let receiverId: Int 155 | 156 | /// Message type 157 | let type: Int 158 | 159 | /// True if the message is incoming 160 | let isIncoming: Bool 161 | 162 | /// True if the message has been read 163 | let isRead: Bool 164 | } 165 | 166 | // MARK: - DialogPlainObject 167 | 168 | struct DialogPlainObject: Plain { 169 | 170 | // MARK: - Plain 171 | 172 | var uniqueId: UniqueID { 173 | return UniqueID(value: id) 174 | } 175 | 176 | // MARK: - Properties 177 | 178 | /// Unique id 179 | let id: Int 180 | 181 | /// True if the dialog has been pinned 182 | let isPinned: Bool 183 | 184 | /// All available (stored) the dialog's messages 185 | let messages: [MessagePlainObject] 186 | } 187 | 188 | ``` 189 | 190 | 3. Create Translator class 191 | 192 | 193 | ```swift 194 | // MARK: - MessageTranslator 195 | 196 | final class MessageTranslator { 197 | 198 | // MARK: - Aliases 199 | 200 | typealias PlainModel = MessagePlainObject 201 | typealias DatabaseModel = MessageModelObject 202 | } 203 | 204 | // MARK: - Translator 205 | 206 | extension MessageTranslator: Translator { 207 | 208 | func translate(model: DatabaseModel) throws -> PlainModel { 209 | MessagePlainObject( 210 | id: Int(model.uniqueId) ?? 0, 211 | date: model.date, 212 | text: model.text, 213 | senderId: model.senderId, 214 | receiverId: model.receiverId, 215 | type: model.type, 216 | isIncoming: model.isIncoming, 217 | isRead: model.isRead 218 | ) 219 | } 220 | 221 | func translate(plain: PlainModel) throws -> DatabaseModel { 222 | let model = MessageModelObject() 223 | try translate(from: plain, to: model) 224 | return model 225 | } 226 | 227 | func translate(from plain: PlainModel, to databaseModel: DatabaseModel) throws { 228 | if databaseModel.uniqueId.isEmpty { 229 | databaseModel.uniqueId = plain.uniqueId.rawValue 230 | } 231 | databaseModel.date = plain.date 232 | databaseModel.isIncoming = plain.isIncoming 233 | databaseModel.isRead = plain.isRead 234 | databaseModel.senderId = plain.senderId 235 | databaseModel.text = plain.text 236 | databaseModel.type = plain.type 237 | databaseModel.receiverId = plain.receiverId 238 | } 239 | } 240 | 241 | // MARK: - DialogTranslator 242 | 243 | final class DialogTranslator { 244 | 245 | // MARK: - Aliases 246 | 247 | typealias PlainModel = DialogPlainObject 248 | typealias DatabaseModel = DialogModelObject 249 | } 250 | 251 | // MARK: - Translator 252 | 253 | extension DialogTranslator: Translator { 254 | 255 | func translate(model: DatabaseModel) throws -> PlainModel { 256 | DialogPlainObject( 257 | id: Int(model.uniqueId) ?? 0, 258 | isPinned: model.isPinned, 259 | messages: try MessagesTranslator().translate( 260 | models: Array(model.messages) 261 | ) 262 | ) 263 | } 264 | 265 | func translate(plain: PlainModel) throws -> DatabaseModel { 266 | let model = DialogModelObject() 267 | try translate(from: plain, to: model) 268 | return model 269 | } 270 | 271 | func translate(from plain: PlainModel, to databaseModel: DatabaseModel) throws { 272 | if databaseModel.uniqueId.isEmpty { 273 | databaseModel.uniqueId = plain.uniqueId.rawValue 274 | } 275 | databaseModel.isPinned = plain.isPinned 276 | databaseModel.messages.removeAll() 277 | databaseModel.messages.append( 278 | objectsIn: try MessagesTranslator().translate( 279 | plains: plain.messages 280 | ) 281 | ) 282 | } 283 | } 284 | ``` 285 | 4. Use it 286 | 287 | ```swift 288 | let dao = DAO( 289 | storage: RealmStorage, 290 | translator: DialogTranslator() 291 | ) 292 | 293 | // Obtain messages (from backend for example) 294 | let dialogs = dialogsService.obtainDialogs() 295 | 296 | ... 297 | 298 | /// Obtain messages from your database 299 | let dialogs = try dao.read() 300 | ``` 301 | 302 | ## Requirements 303 | - iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+ 304 | - Xcode 9.0 305 | - Swift 5 306 | 307 | ## Communication 308 | 309 | - If you **found a bug**, open an issue. 310 | - If you **have a feature request**, open an issue. 311 | - If you **want to contribute**, submit a pull request. 312 | 313 | ## Installation 314 | 315 | ### CocoaPods 316 | 317 | [CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command: 318 | 319 | ```bash 320 | $ gem install cocoapods 321 | ``` 322 | 323 | To integrate DAO into your Xcode project using CocoaPods, specify it in your `Podfile`: 324 | 325 | ```ruby 326 | use_frameworks! 327 | 328 | target "" do 329 | pod "SwiftyDAO" 330 | end 331 | ``` 332 | 333 | Then, run the following command: 334 | 335 | ```bash 336 | $ pod install 337 | ``` 338 | 339 | ### Manually 340 | 341 | If you prefer not to use any dependency managers, you can integrate DAO into your project manually. 342 | 343 | #### Embedded Framework 344 | 345 | - Open up Terminal, `cd` into your top-level project directory, and run the following command "if" your project is not initialized as a git repository: 346 | 347 | ```bash 348 | $ git init 349 | ``` 350 | 351 | - Add DAO as a git [submodule](http://git-scm.com/docs/git-submodule) by running the following command: 352 | 353 | ```bash 354 | $ git submodule add https://github.com/incetro/DAO.git 355 | ``` 356 | 357 | - Open the new `DAO` folder, and drag the `DAO.xcodeproj` into the Project Navigator of your application's Xcode project. 358 | 359 | > It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter. 360 | 361 | - Select the `DAO.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target. 362 | - Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar. 363 | - In the tab bar at the top of that window, open the "General" panel. 364 | - Click on the `+` button under the "Embedded Binaries" section. 365 | - You will see two different `DAO.xcodeproj` folders each with two different versions of the `DAO.framework` nested inside a `Products` folder. 366 | 367 | > It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `DAO.framework`. 368 | 369 | - Select the top `DAO.framework` for iOS and the bottom one for OS X. 370 | 371 | > You can verify which one you selected by inspecting the build log for your project. The build target for `Nio` will be listed as either `DAO iOS`, `DAO macOS`, `DAO tvOS` or `DAO watchOS`. 372 | 373 | - And that's it! 374 | 375 | > The `DAO.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device. 376 | 377 | ## Author 378 | 379 | incetro, incetro@ya.ru 380 | 381 | ## License 382 | 383 | DAO is available under the MIT license. See the LICENSE file for more info. 384 | -------------------------------------------------------------------------------- /Sources/SDAO/DAO/DAO.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DAO.swift 3 | // DAO 4 | // 5 | // Created by incetro on 14/07/2017. 6 | // 7 | // 8 | 9 | import Monreau 10 | import Foundation 11 | 12 | // MARK: - DAO 13 | 14 | public class DAO where S.Model == T.DatabaseModel, S.Key == String { 15 | 16 | // MARK: - Types 17 | 18 | /// Database model type 19 | public typealias Model = T.DatabaseModel 20 | 21 | /// Plain object type 22 | public typealias Plain = T.PlainModel 23 | 24 | /// Primary key type 25 | public typealias PKType = S.Key 26 | 27 | // MARK: - Properties 28 | 29 | /// Database storage 30 | private let storage: S 31 | 32 | /// Objects translator 33 | private let translator: T 34 | 35 | // MARK: - Initializers 36 | 37 | /// Standard initializer 38 | /// 39 | /// - Parameters: 40 | /// - storage: database storage 41 | /// - translator: translator for current `Model` and `Plain` types 42 | public init(storage: S, translator: T) { 43 | self.storage = storage 44 | self.translator = translator 45 | } 46 | 47 | // MARK: - Create 48 | 49 | /// Create entity in database 50 | /// 51 | /// - Parameter plain: plain object with all data for creating 52 | /// - Throws: error if entity cannot be created 53 | public func create(_ plain: Plain) throws { 54 | try storage.create { model in 55 | try translator.translate(from: plain, to: model) 56 | } 57 | } 58 | 59 | /// Create entities in database 60 | /// 61 | /// - Parameter plains: plain objects with all necessary data for creating 62 | /// - Throws: error if any entity cannot be created 63 | public func create(_ plains: [Plain]) throws { 64 | try plains.forEach(create) 65 | } 66 | 67 | // MARK: - Read 68 | 69 | /// Returns the number of objects which fits the predicate 70 | /// - Parameter predicate: some predicate 71 | public func count(predicatedBy predicate: MPredicate? = nil) throws -> Int { 72 | try storage.count(predicatedBy: predicate) 73 | } 74 | 75 | /// Returns the number of objects which fits the predicate 76 | /// - Parameter predicate: some predicate 77 | public func count(predicatedBy predicate: NSPredicate) throws -> Int { 78 | try storage.count(predicatedBy: predicate) 79 | } 80 | 81 | /// Read all entities from database of `Plain` type 82 | /// 83 | /// - Returns: array of entities 84 | /// - Throws: error if any entity cannot be read 85 | public func read() throws -> [Plain] { 86 | let models = try storage.read() 87 | let plains = try translator.translate(models: models) 88 | return plains 89 | } 90 | 91 | /// Read an entity from database of `Plain` type 92 | /// 93 | /// - Parameter primaryKey: entity identifier 94 | /// - Returns: instance of existing entity or nil 95 | /// - Throws: error if entity cannot be read 96 | public func read(byPrimaryKey primaryKey: UniqueID) throws -> Plain? { 97 | guard let model = try storage.read(byPrimaryKey: primaryKey.rawValue) else { 98 | return nil 99 | } 100 | let plain = try translator.translate(model: model) 101 | return plain 102 | } 103 | 104 | /// Read entities from database of `Plain` type 105 | /// 106 | /// - Parameter primaryKeys: entities identifiers 107 | /// - Returns: instances of existing entities 108 | /// - Throws: error if entities cannot be read 109 | public func read(byPrimaryKeys primaryKeys: [UniqueID]) throws -> [Plain] { 110 | let predicate = NSPredicate(format: "uniqueId IN %@", primaryKeys.map(\.rawValue)) 111 | let models = try storage.read(predicatedBy: predicate) 112 | let plains = try translator.translate(models: models) 113 | return plains 114 | } 115 | 116 | /// Read an entity from database of `Plain` type 117 | /// 118 | /// - Parameter primaryKey: entity identifier 119 | /// - Returns: instance of existing entity or nil 120 | /// - Throws: error if entity cannot be read 121 | public func read(byPrimaryKey primaryKey: String) throws -> Plain? { 122 | try read(byPrimaryKey: UniqueID(rawValue: primaryKey)) 123 | } 124 | 125 | /// Read entities from database of `Plain` type 126 | /// 127 | /// - Parameter primaryKeys: entities identifiers 128 | /// - Returns: instances of existing entities 129 | /// - Throws: error if entities cannot be read 130 | public func read(byPrimaryKeys primaryKeys: [String]) throws -> [Plain] { 131 | try read(byPrimaryKeys: primaryKeys.map(UniqueID.init)) 132 | } 133 | 134 | /// Read an entity from database of `Plain` type 135 | /// 136 | /// - Parameter primaryKey: entity identifier 137 | /// - Returns: instance of existing entity or nil 138 | /// - Throws: error if entity cannot be read 139 | public func read(byPrimaryKey primaryKey: Numeric) throws -> Plain? { 140 | try read(byPrimaryKey: UniqueID(value: primaryKey)) 141 | } 142 | 143 | /// Read entities from database of `Plain` type 144 | /// 145 | /// - Parameter primaryKeys: entities identifiers 146 | /// - Returns: instances of existing entities 147 | /// - Throws: error if entities cannot be read 148 | public func read(byPrimaryKeys primaryKeys: [Numeric]) throws -> [Plain] { 149 | try read(byPrimaryKeys: primaryKeys.map(UniqueID.init)) 150 | } 151 | 152 | /// Read entities from database of `Plain` filtered by predicate 153 | /// 154 | /// - Parameters: 155 | /// - predicate: some filter 156 | /// - Returns: ordered array of entities 157 | /// - Throws: error if any entity cannot be read 158 | public func read(predicatedBy predicate: MPredicate) throws -> [Plain] { 159 | let predicate = NSPredicate(format: predicate.filter) 160 | return try read(predicatedBy: predicate) 161 | } 162 | 163 | /// Read entities from database of `Plain` filtered by predicate 164 | /// 165 | /// - Parameters: 166 | /// - predicate: some filter 167 | /// - Returns: ordered array of entities 168 | /// - Throws: error if any entity cannot be read 169 | public func read(predicatedBy predicate: NSPredicate) throws -> [Plain] { 170 | let models = try storage.read(predicatedBy: predicate) 171 | let plains = try translator.translate(models: models) 172 | return plains 173 | } 174 | 175 | // Read all entities in storage ordered by the given key 176 | /// 177 | /// - Parameters: 178 | /// - key: key for sorting 179 | /// - ascending: ascending flag 180 | /// - Returns: all found objects ordered by the given key 181 | public func read(orderedBy field: String, asceding: Bool = true) throws -> [Plain] { 182 | let models = try storage.read(orderedBy: field, ascending: asceding) 183 | let plains = try translator.translate(models: models) 184 | return plains 185 | } 186 | 187 | /// Read entity from database of `Plain` type ordered by field 188 | /// 189 | /// - Parameters: 190 | /// - predicate: filter 191 | /// - name: ordering field 192 | /// - ascending: ascending flag (descending otherwise) 193 | /// - Returns: ordered array of entities 194 | /// - Throws: error if any entity cannot be read 195 | public func read(predicatedBy predicate: MPredicate, orderedBy name: String, ascending: Bool) throws -> [Plain] { 196 | let predicate = NSPredicate(format: predicate.filter) 197 | return try read(predicatedBy: predicate, orderedBy: name, ascending: ascending) 198 | } 199 | 200 | /// Read entity from database of `Plain` type ordered by field 201 | /// 202 | /// - Parameters: 203 | /// - predicate: filter 204 | /// - name: ordering field 205 | /// - ascending: ascending flag (descending otherwise) 206 | /// - Returns: ordered array of entities 207 | /// - Throws: error if any entity cannot be read 208 | public func read(predicatedBy predicate: NSPredicate, orderedBy name: String, ascending: Bool) throws -> [Plain] { 209 | let sorter = SortDescriptor(key: name, ascending: ascending) 210 | let models = try storage.read(predicatedBy: predicate, includeSubentities: true, sortDescriptors: [sorter]) 211 | let plains = try translator.translate(models: models) 212 | return plains 213 | } 214 | 215 | // MARK: - Update 216 | 217 | /// Save new entity or update existing 218 | /// 219 | /// - Parameter plain: plain object with all data for saving 220 | /// - Throws: error if entity can not be saved 221 | public func persist(_ plain: Plain) throws { 222 | let primaryKey = plain.uniqueId.rawValue 223 | if let _ = try storage.read(byPrimaryKey: primaryKey) { 224 | try storage.persist(withPrimaryKey: primaryKey) { model in 225 | guard let model = model else { 226 | fatalError("There is some unknown error with Monreau framework (model must exists here)") 227 | } 228 | try translator.translate(from: plain, to: model) 229 | } 230 | } else { 231 | try create(plain) 232 | } 233 | } 234 | 235 | /// Saving new entities or update existing 236 | /// 237 | /// - Parameters: 238 | /// - plains: plain objects with all data for saving 239 | /// - Throws: error if any entity can not be saved 240 | public func persist(_ plains: [Plain]) throws { 241 | try plains.forEach(persist) 242 | } 243 | 244 | // MARK: - Delete 245 | 246 | /// Delete all entities of `Plain` type 247 | /// 248 | /// - Throws: error if any entity can not be deleted 249 | public func erase() throws { 250 | try storage.erase() 251 | } 252 | 253 | /// Delete an entity of `Plain` type by given identifier 254 | /// 255 | /// - Parameter primaryKey: identifier 256 | /// - Throws: error if entity cannot be deleted 257 | public func erase(byPrimaryKey primaryKey: UniqueID) throws { 258 | try storage.erase(byPrimaryKey: primaryKey.rawValue) 259 | } 260 | 261 | /// Delete an entity of `Plain` type by given identifier 262 | /// 263 | /// - Parameter primaryKey: identifier 264 | /// - Throws: error if entity cannot be deleted 265 | public func erase(byPrimaryKey primaryKey: K) throws { 266 | try erase(byPrimaryKey: UniqueID(value: primaryKey)) 267 | } 268 | 269 | /// Delete an entity of `Plain` type by given identifier 270 | /// 271 | /// - Parameter primaryKeys: identifiers 272 | /// - Throws: error if entity cannot be deleted 273 | public func erase(byPrimaryKeys primaryKeys: [K]) throws { 274 | try erase(byPrimaryKeys: primaryKeys.map(UniqueID.init)) 275 | } 276 | 277 | /// Delete an entity of `Plain` type by given identifier 278 | /// 279 | /// - Parameter primaryKey: identifier 280 | /// - Throws: error if entity cannot be deleted 281 | public func erase(byPrimaryKey primaryKey: String) throws { 282 | try erase(byPrimaryKey: UniqueID(rawValue: primaryKey)) 283 | } 284 | 285 | /// Delete an entity of `Plain` type by given identifier 286 | /// 287 | /// - Parameter primaryKeys: identifiers 288 | /// - Throws: error if entity cannot be deleted 289 | public func erase(byPrimaryKeys primaryKeys: [String]) throws { 290 | try erase(byPrimaryKeys: primaryKeys.map(UniqueID.init)) 291 | } 292 | 293 | /// Delete the given entity 294 | /// 295 | /// - Parameter plain: some plain object for deletion 296 | /// - Throws: error if an entity cannot be deleted 297 | public func erase(_ plain: Plain) throws { 298 | try erase(byPrimaryKey: plain.uniqueId) 299 | } 300 | 301 | /// Delete the given entities 302 | /// 303 | /// - Parameter plains: some plain objects for deletion 304 | /// - Throws: error if any entity cannot be deleted 305 | public func erase(_ plains: [Plain]) throws { 306 | try erase(byPrimaryKeys: plains.map(\.uniqueId)) 307 | } 308 | 309 | /// Delete entity of `Plain` type by given identifiers 310 | /// 311 | /// - Parameter primaryKeys: the given identifiers 312 | /// - Throws: error if any entity cannot be deleted 313 | public func erase(byPrimaryKeys primaryKeys: [UniqueID]) throws { 314 | let predicate = NSPredicate(format: "uniqueId IN %@", primaryKeys.map(\.rawValue)) 315 | try erase(predicatedBy: predicate) 316 | } 317 | 318 | /// Delete entities of `Plain` type by given predicate 319 | /// 320 | /// - Parameter predicate: the given filter 321 | /// - Throws: error if any entity cannot be deleted 322 | public func erase(predicatedBy predicate: MPredicate) throws { 323 | try storage.erase(predicatedBy: predicate) 324 | } 325 | 326 | /// Delete entities of `Plain` type by given predicate 327 | /// 328 | /// - Parameter predicate: the given filter 329 | /// - Throws: error if any entity cannot be deleted 330 | public func erase(predicatedBy predicate: NSPredicate) throws { 331 | try storage.erase(predicatedBy: predicate) 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /Example/NioExample-iOS/NioExample-iOS.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 33C5F3961F1CD76600FAD900 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C5F3951F1CD76600FAD900 /* AppDelegate.swift */; }; 11 | 33C5F3981F1CD76600FAD900 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C5F3971F1CD76600FAD900 /* ViewController.swift */; }; 12 | 33C5F39B1F1CD76600FAD900 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 33C5F3991F1CD76600FAD900 /* Main.storyboard */; }; 13 | 33C5F3A01F1CD76600FAD900 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33C5F39F1F1CD76600FAD900 /* Assets.xcassets */; }; 14 | 33C5F3A31F1CD76600FAD900 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 33C5F3A11F1CD76600FAD900 /* LaunchScreen.storyboard */; }; 15 | 33C5F3B61F1CD99D00FAD900 /* NioModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 33C5F3AC1F1CD99D00FAD900 /* NioModel.xcdatamodeld */; }; 16 | 33C5F3B71F1CD99D00FAD900 /* AdditiveModelObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C5F3AF1F1CD99D00FAD900 /* AdditiveModelObject.swift */; }; 17 | 33C5F3B81F1CD99D00FAD900 /* CategoryModelObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C5F3B01F1CD99D00FAD900 /* CategoryModelObject.swift */; }; 18 | 33C5F3B91F1CD99D00FAD900 /* PositionModelObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C5F3B11F1CD99D00FAD900 /* PositionModelObject.swift */; }; 19 | 33C5F3BA1F1CD99D00FAD900 /* AdditivePlainObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C5F3B31F1CD99D00FAD900 /* AdditivePlainObject.swift */; }; 20 | 33C5F3BB1F1CD99D00FAD900 /* CategoryPlainObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C5F3B41F1CD99D00FAD900 /* CategoryPlainObject.swift */; }; 21 | 33C5F3BC1F1CD99D00FAD900 /* PositionPlainObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C5F3B51F1CD99D00FAD900 /* PositionPlainObject.swift */; }; 22 | 8AA86B1E044CB9A13E1546A0 /* Pods_NioExample_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E69E91EBC43F8E72C9DA8677 /* Pods_NioExample_iOS.framework */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 33C5F3921F1CD76600FAD900 /* NioExample-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "NioExample-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 33C5F3951F1CD76600FAD900 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 28 | 33C5F3971F1CD76600FAD900 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 29 | 33C5F39A1F1CD76600FAD900 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | 33C5F39F1F1CD76600FAD900 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | 33C5F3A21F1CD76600FAD900 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | 33C5F3A41F1CD76600FAD900 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 33C5F3AD1F1CD99D00FAD900 /* NioModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = NioModel.xcdatamodel; sourceTree = ""; }; 34 | 33C5F3AF1F1CD99D00FAD900 /* AdditiveModelObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdditiveModelObject.swift; sourceTree = ""; }; 35 | 33C5F3B01F1CD99D00FAD900 /* CategoryModelObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CategoryModelObject.swift; sourceTree = ""; }; 36 | 33C5F3B11F1CD99D00FAD900 /* PositionModelObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PositionModelObject.swift; sourceTree = ""; }; 37 | 33C5F3B31F1CD99D00FAD900 /* AdditivePlainObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdditivePlainObject.swift; sourceTree = ""; }; 38 | 33C5F3B41F1CD99D00FAD900 /* CategoryPlainObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CategoryPlainObject.swift; sourceTree = ""; }; 39 | 33C5F3B51F1CD99D00FAD900 /* PositionPlainObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PositionPlainObject.swift; sourceTree = ""; }; 40 | 80AFFC4AA4C0C537358E8BB6 /* Pods-NioExample-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NioExample-iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-NioExample-iOS/Pods-NioExample-iOS.release.xcconfig"; sourceTree = ""; }; 41 | E69E91EBC43F8E72C9DA8677 /* Pods_NioExample_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NioExample_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | F5B19557812AC7BD21EC79F7 /* Pods-NioExample-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NioExample-iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-NioExample-iOS/Pods-NioExample-iOS.debug.xcconfig"; sourceTree = ""; }; 43 | /* End PBXFileReference section */ 44 | 45 | /* Begin PBXFrameworksBuildPhase section */ 46 | 33C5F38F1F1CD76600FAD900 /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | 8AA86B1E044CB9A13E1546A0 /* Pods_NioExample_iOS.framework in Frameworks */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXFrameworksBuildPhase section */ 55 | 56 | /* Begin PBXGroup section */ 57 | 33C5F3891F1CD76600FAD900 = { 58 | isa = PBXGroup; 59 | children = ( 60 | 33C5F3941F1CD76600FAD900 /* NioExample-iOS */, 61 | 33C5F3931F1CD76600FAD900 /* Products */, 62 | DF02ADBD4BE07404495C81CB /* Pods */, 63 | 3CD8178D8E471A20556D0FB5 /* Frameworks */, 64 | ); 65 | sourceTree = ""; 66 | }; 67 | 33C5F3931F1CD76600FAD900 /* Products */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 33C5F3921F1CD76600FAD900 /* NioExample-iOS.app */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | 33C5F3941F1CD76600FAD900 /* NioExample-iOS */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 33C5F3AA1F1CD99D00FAD900 /* Models */, 79 | 33C5F3951F1CD76600FAD900 /* AppDelegate.swift */, 80 | 33C5F3971F1CD76600FAD900 /* ViewController.swift */, 81 | 33C5F3991F1CD76600FAD900 /* Main.storyboard */, 82 | 33C5F39F1F1CD76600FAD900 /* Assets.xcassets */, 83 | 33C5F3A11F1CD76600FAD900 /* LaunchScreen.storyboard */, 84 | 33C5F3A41F1CD76600FAD900 /* Info.plist */, 85 | ); 86 | path = "NioExample-iOS"; 87 | sourceTree = ""; 88 | }; 89 | 33C5F3AA1F1CD99D00FAD900 /* Models */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 33C5F3AB1F1CD99D00FAD900 /* CoreDataModel */, 93 | 33C5F3AE1F1CD99D00FAD900 /* Model */, 94 | 33C5F3B21F1CD99D00FAD900 /* Plain */, 95 | ); 96 | path = Models; 97 | sourceTree = SOURCE_ROOT; 98 | }; 99 | 33C5F3AB1F1CD99D00FAD900 /* CoreDataModel */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 33C5F3AC1F1CD99D00FAD900 /* NioModel.xcdatamodeld */, 103 | ); 104 | path = CoreDataModel; 105 | sourceTree = ""; 106 | }; 107 | 33C5F3AE1F1CD99D00FAD900 /* Model */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 33C5F3AF1F1CD99D00FAD900 /* AdditiveModelObject.swift */, 111 | 33C5F3B01F1CD99D00FAD900 /* CategoryModelObject.swift */, 112 | 33C5F3B11F1CD99D00FAD900 /* PositionModelObject.swift */, 113 | ); 114 | path = Model; 115 | sourceTree = ""; 116 | }; 117 | 33C5F3B21F1CD99D00FAD900 /* Plain */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 33C5F3B31F1CD99D00FAD900 /* AdditivePlainObject.swift */, 121 | 33C5F3B41F1CD99D00FAD900 /* CategoryPlainObject.swift */, 122 | 33C5F3B51F1CD99D00FAD900 /* PositionPlainObject.swift */, 123 | ); 124 | path = Plain; 125 | sourceTree = ""; 126 | }; 127 | 3CD8178D8E471A20556D0FB5 /* Frameworks */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | E69E91EBC43F8E72C9DA8677 /* Pods_NioExample_iOS.framework */, 131 | ); 132 | name = Frameworks; 133 | sourceTree = ""; 134 | }; 135 | DF02ADBD4BE07404495C81CB /* Pods */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | F5B19557812AC7BD21EC79F7 /* Pods-NioExample-iOS.debug.xcconfig */, 139 | 80AFFC4AA4C0C537358E8BB6 /* Pods-NioExample-iOS.release.xcconfig */, 140 | ); 141 | name = Pods; 142 | sourceTree = ""; 143 | }; 144 | /* End PBXGroup section */ 145 | 146 | /* Begin PBXNativeTarget section */ 147 | 33C5F3911F1CD76600FAD900 /* NioExample-iOS */ = { 148 | isa = PBXNativeTarget; 149 | buildConfigurationList = 33C5F3A71F1CD76600FAD900 /* Build configuration list for PBXNativeTarget "NioExample-iOS" */; 150 | buildPhases = ( 151 | BE53EBDF3FCE3E8203B443A0 /* [CP] Check Pods Manifest.lock */, 152 | 33C5F38E1F1CD76600FAD900 /* Sources */, 153 | 33C5F38F1F1CD76600FAD900 /* Frameworks */, 154 | 33C5F3901F1CD76600FAD900 /* Resources */, 155 | 867797F583B85F4269DC7AC4 /* [CP] Embed Pods Frameworks */, 156 | 220E950EA62AD90DC9B13FA4 /* [CP] Copy Pods Resources */, 157 | ); 158 | buildRules = ( 159 | ); 160 | dependencies = ( 161 | ); 162 | name = "NioExample-iOS"; 163 | productName = "NioExample-iOS"; 164 | productReference = 33C5F3921F1CD76600FAD900 /* NioExample-iOS.app */; 165 | productType = "com.apple.product-type.application"; 166 | }; 167 | /* End PBXNativeTarget section */ 168 | 169 | /* Begin PBXProject section */ 170 | 33C5F38A1F1CD76600FAD900 /* Project object */ = { 171 | isa = PBXProject; 172 | attributes = { 173 | LastSwiftUpdateCheck = 0830; 174 | LastUpgradeCheck = 0830; 175 | ORGANIZATIONNAME = Incetro; 176 | TargetAttributes = { 177 | 33C5F3911F1CD76600FAD900 = { 178 | CreatedOnToolsVersion = 8.3.3; 179 | ProvisioningStyle = Automatic; 180 | }; 181 | }; 182 | }; 183 | buildConfigurationList = 33C5F38D1F1CD76600FAD900 /* Build configuration list for PBXProject "NioExample-iOS" */; 184 | compatibilityVersion = "Xcode 3.2"; 185 | developmentRegion = English; 186 | hasScannedForEncodings = 0; 187 | knownRegions = ( 188 | en, 189 | Base, 190 | ); 191 | mainGroup = 33C5F3891F1CD76600FAD900; 192 | productRefGroup = 33C5F3931F1CD76600FAD900 /* Products */; 193 | projectDirPath = ""; 194 | projectRoot = ""; 195 | targets = ( 196 | 33C5F3911F1CD76600FAD900 /* NioExample-iOS */, 197 | ); 198 | }; 199 | /* End PBXProject section */ 200 | 201 | /* Begin PBXResourcesBuildPhase section */ 202 | 33C5F3901F1CD76600FAD900 /* Resources */ = { 203 | isa = PBXResourcesBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | 33C5F3A31F1CD76600FAD900 /* LaunchScreen.storyboard in Resources */, 207 | 33C5F3A01F1CD76600FAD900 /* Assets.xcassets in Resources */, 208 | 33C5F39B1F1CD76600FAD900 /* Main.storyboard in Resources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXResourcesBuildPhase section */ 213 | 214 | /* Begin PBXShellScriptBuildPhase section */ 215 | 220E950EA62AD90DC9B13FA4 /* [CP] Copy Pods Resources */ = { 216 | isa = PBXShellScriptBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | ); 220 | inputPaths = ( 221 | ); 222 | name = "[CP] Copy Pods Resources"; 223 | outputPaths = ( 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | shellPath = /bin/sh; 227 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-NioExample-iOS/Pods-NioExample-iOS-resources.sh\"\n"; 228 | showEnvVarsInLog = 0; 229 | }; 230 | 867797F583B85F4269DC7AC4 /* [CP] Embed Pods Frameworks */ = { 231 | isa = PBXShellScriptBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | ); 235 | inputPaths = ( 236 | ); 237 | name = "[CP] Embed Pods Frameworks"; 238 | outputPaths = ( 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | shellPath = /bin/sh; 242 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-NioExample-iOS/Pods-NioExample-iOS-frameworks.sh\"\n"; 243 | showEnvVarsInLog = 0; 244 | }; 245 | BE53EBDF3FCE3E8203B443A0 /* [CP] Check Pods Manifest.lock */ = { 246 | isa = PBXShellScriptBuildPhase; 247 | buildActionMask = 2147483647; 248 | files = ( 249 | ); 250 | inputPaths = ( 251 | ); 252 | name = "[CP] Check Pods Manifest.lock"; 253 | outputPaths = ( 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | shellPath = /bin/sh; 257 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 258 | showEnvVarsInLog = 0; 259 | }; 260 | /* End PBXShellScriptBuildPhase section */ 261 | 262 | /* Begin PBXSourcesBuildPhase section */ 263 | 33C5F38E1F1CD76600FAD900 /* Sources */ = { 264 | isa = PBXSourcesBuildPhase; 265 | buildActionMask = 2147483647; 266 | files = ( 267 | 33C5F3BB1F1CD99D00FAD900 /* CategoryPlainObject.swift in Sources */, 268 | 33C5F3B81F1CD99D00FAD900 /* CategoryModelObject.swift in Sources */, 269 | 33C5F3BA1F1CD99D00FAD900 /* AdditivePlainObject.swift in Sources */, 270 | 33C5F3B61F1CD99D00FAD900 /* NioModel.xcdatamodeld in Sources */, 271 | 33C5F3981F1CD76600FAD900 /* ViewController.swift in Sources */, 272 | 33C5F3BC1F1CD99D00FAD900 /* PositionPlainObject.swift in Sources */, 273 | 33C5F3961F1CD76600FAD900 /* AppDelegate.swift in Sources */, 274 | 33C5F3B91F1CD99D00FAD900 /* PositionModelObject.swift in Sources */, 275 | 33C5F3B71F1CD99D00FAD900 /* AdditiveModelObject.swift in Sources */, 276 | ); 277 | runOnlyForDeploymentPostprocessing = 0; 278 | }; 279 | /* End PBXSourcesBuildPhase section */ 280 | 281 | /* Begin PBXVariantGroup section */ 282 | 33C5F3991F1CD76600FAD900 /* Main.storyboard */ = { 283 | isa = PBXVariantGroup; 284 | children = ( 285 | 33C5F39A1F1CD76600FAD900 /* Base */, 286 | ); 287 | name = Main.storyboard; 288 | sourceTree = ""; 289 | }; 290 | 33C5F3A11F1CD76600FAD900 /* LaunchScreen.storyboard */ = { 291 | isa = PBXVariantGroup; 292 | children = ( 293 | 33C5F3A21F1CD76600FAD900 /* Base */, 294 | ); 295 | name = LaunchScreen.storyboard; 296 | sourceTree = ""; 297 | }; 298 | /* End PBXVariantGroup section */ 299 | 300 | /* Begin XCBuildConfiguration section */ 301 | 33C5F3A51F1CD76600FAD900 /* Debug */ = { 302 | isa = XCBuildConfiguration; 303 | buildSettings = { 304 | ALWAYS_SEARCH_USER_PATHS = NO; 305 | CLANG_ANALYZER_NONNULL = YES; 306 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 308 | CLANG_CXX_LIBRARY = "libc++"; 309 | CLANG_ENABLE_MODULES = YES; 310 | CLANG_ENABLE_OBJC_ARC = YES; 311 | CLANG_WARN_BOOL_CONVERSION = YES; 312 | CLANG_WARN_CONSTANT_CONVERSION = YES; 313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 314 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 315 | CLANG_WARN_EMPTY_BODY = YES; 316 | CLANG_WARN_ENUM_CONVERSION = YES; 317 | CLANG_WARN_INFINITE_RECURSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 320 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 321 | CLANG_WARN_UNREACHABLE_CODE = YES; 322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 323 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 324 | COPY_PHASE_STRIP = NO; 325 | DEBUG_INFORMATION_FORMAT = dwarf; 326 | ENABLE_STRICT_OBJC_MSGSEND = YES; 327 | ENABLE_TESTABILITY = YES; 328 | GCC_C_LANGUAGE_STANDARD = gnu99; 329 | GCC_DYNAMIC_NO_PIC = NO; 330 | GCC_NO_COMMON_BLOCKS = YES; 331 | GCC_OPTIMIZATION_LEVEL = 0; 332 | GCC_PREPROCESSOR_DEFINITIONS = ( 333 | "DEBUG=1", 334 | "$(inherited)", 335 | ); 336 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 337 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 338 | GCC_WARN_UNDECLARED_SELECTOR = YES; 339 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 340 | GCC_WARN_UNUSED_FUNCTION = YES; 341 | GCC_WARN_UNUSED_VARIABLE = YES; 342 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 343 | MTL_ENABLE_DEBUG_INFO = YES; 344 | ONLY_ACTIVE_ARCH = YES; 345 | SDKROOT = iphoneos; 346 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 347 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 348 | }; 349 | name = Debug; 350 | }; 351 | 33C5F3A61F1CD76600FAD900 /* Release */ = { 352 | isa = XCBuildConfiguration; 353 | buildSettings = { 354 | ALWAYS_SEARCH_USER_PATHS = NO; 355 | CLANG_ANALYZER_NONNULL = YES; 356 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 357 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 358 | CLANG_CXX_LIBRARY = "libc++"; 359 | CLANG_ENABLE_MODULES = YES; 360 | CLANG_ENABLE_OBJC_ARC = YES; 361 | CLANG_WARN_BOOL_CONVERSION = YES; 362 | CLANG_WARN_CONSTANT_CONVERSION = YES; 363 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 364 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 365 | CLANG_WARN_EMPTY_BODY = YES; 366 | CLANG_WARN_ENUM_CONVERSION = YES; 367 | CLANG_WARN_INFINITE_RECURSION = YES; 368 | CLANG_WARN_INT_CONVERSION = YES; 369 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 370 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 371 | CLANG_WARN_UNREACHABLE_CODE = YES; 372 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 373 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 374 | COPY_PHASE_STRIP = NO; 375 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 376 | ENABLE_NS_ASSERTIONS = NO; 377 | ENABLE_STRICT_OBJC_MSGSEND = YES; 378 | GCC_C_LANGUAGE_STANDARD = gnu99; 379 | GCC_NO_COMMON_BLOCKS = YES; 380 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 381 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 382 | GCC_WARN_UNDECLARED_SELECTOR = YES; 383 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 384 | GCC_WARN_UNUSED_FUNCTION = YES; 385 | GCC_WARN_UNUSED_VARIABLE = YES; 386 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 387 | MTL_ENABLE_DEBUG_INFO = NO; 388 | SDKROOT = iphoneos; 389 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 390 | VALIDATE_PRODUCT = YES; 391 | }; 392 | name = Release; 393 | }; 394 | 33C5F3A81F1CD76600FAD900 /* Debug */ = { 395 | isa = XCBuildConfiguration; 396 | baseConfigurationReference = F5B19557812AC7BD21EC79F7 /* Pods-NioExample-iOS.debug.xcconfig */; 397 | buildSettings = { 398 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 399 | INFOPLIST_FILE = "NioExample-iOS/Info.plist"; 400 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 401 | PRODUCT_BUNDLE_IDENTIFIER = "com.incetro.NioExample-iOS"; 402 | PRODUCT_NAME = "$(TARGET_NAME)"; 403 | SWIFT_VERSION = 3.0; 404 | }; 405 | name = Debug; 406 | }; 407 | 33C5F3A91F1CD76600FAD900 /* Release */ = { 408 | isa = XCBuildConfiguration; 409 | baseConfigurationReference = 80AFFC4AA4C0C537358E8BB6 /* Pods-NioExample-iOS.release.xcconfig */; 410 | buildSettings = { 411 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 412 | INFOPLIST_FILE = "NioExample-iOS/Info.plist"; 413 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 414 | PRODUCT_BUNDLE_IDENTIFIER = "com.incetro.NioExample-iOS"; 415 | PRODUCT_NAME = "$(TARGET_NAME)"; 416 | SWIFT_VERSION = 3.0; 417 | }; 418 | name = Release; 419 | }; 420 | /* End XCBuildConfiguration section */ 421 | 422 | /* Begin XCConfigurationList section */ 423 | 33C5F38D1F1CD76600FAD900 /* Build configuration list for PBXProject "NioExample-iOS" */ = { 424 | isa = XCConfigurationList; 425 | buildConfigurations = ( 426 | 33C5F3A51F1CD76600FAD900 /* Debug */, 427 | 33C5F3A61F1CD76600FAD900 /* Release */, 428 | ); 429 | defaultConfigurationIsVisible = 0; 430 | defaultConfigurationName = Release; 431 | }; 432 | 33C5F3A71F1CD76600FAD900 /* Build configuration list for PBXNativeTarget "NioExample-iOS" */ = { 433 | isa = XCConfigurationList; 434 | buildConfigurations = ( 435 | 33C5F3A81F1CD76600FAD900 /* Debug */, 436 | 33C5F3A91F1CD76600FAD900 /* Release */, 437 | ); 438 | defaultConfigurationIsVisible = 0; 439 | defaultConfigurationName = Release; 440 | }; 441 | /* End XCConfigurationList section */ 442 | 443 | /* Begin XCVersionGroup section */ 444 | 33C5F3AC1F1CD99D00FAD900 /* NioModel.xcdatamodeld */ = { 445 | isa = XCVersionGroup; 446 | children = ( 447 | 33C5F3AD1F1CD99D00FAD900 /* NioModel.xcdatamodel */, 448 | ); 449 | currentVersion = 33C5F3AD1F1CD99D00FAD900 /* NioModel.xcdatamodel */; 450 | path = NioModel.xcdatamodeld; 451 | sourceTree = ""; 452 | versionGroupType = wrapper.xcdatamodel; 453 | }; 454 | /* End XCVersionGroup section */ 455 | }; 456 | rootObject = 33C5F38A1F1CD76600FAD900 /* Project object */; 457 | } 458 | --------------------------------------------------------------------------------