├── 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 | 
2 |
3 | DAO
4 |
5 |
16 |
17 |
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 |
--------------------------------------------------------------------------------