{"action":"created","issue":{"url":"https://api.github.com/repos/DenHeadless/DTModelStorage/issues/7","labels_url":"https://api.github.com/repos/DenHeadless/DTModelStorage/issues/7/labels{/name}","comments_url":"https://api.github.com/repos/DenHeadless/DTModelStorage/issues/7/comments","events_url":"https://api.github.com/repos/DenHeadless/DTModelStorage/issues/7/events","html_url":"https://github.com/DenHeadless/DTModelStorage/issues/7","id":119918163,"number":7,"title":"Realm Storage","user":{"login":"augmentedworks","id":5872585,"avatar_url":"https://avatars.githubusercontent.com/u/5872585?v=3","gravatar_id":"","url":"https://api.github.com/users/augmentedworks","html_url":"https://github.com/augmentedworks","followers_url":"https://api.github.com/users/augmentedworks/followers","following_url":"https://api.github.com/users/augmentedworks/following{/other_user}","gists_url":"https://api.github.com/users/augmentedworks/gists{/gist_id}","starred_url":"https://api.github.com/users/augmentedworks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/augmentedworks/subscriptions","organizations_url":"https://api.github.com/users/augmentedworks/orgs","repos_url":"https://api.github.com/users/augmentedworks/repos","events_url":"https://api.github.com/users/augmentedworks/events{/privacy}","received_events_url":"https://api.github.com/users/augmentedworks/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"DenHeadless","id":853604,"avatar_url":"https://avatars.githubusercontent.com/u/853604?v=3","gravatar_id":"","url":"https://api.github.com/users/DenHeadless","html_url":"https://github.com/DenHeadless","followers_url":"https://api.github.com/users/DenHeadless/followers","following_url":"https://api.github.com/users/DenHeadless/following{/other_user}","gists_url":"https://api.github.com/users/DenHeadless/gists{/gist_id}","starred_url":"https://api.github.com/users/DenHeadless/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DenHeadless/subscriptions","organizations_url":"https://api.github.com/users/DenHeadless/orgs","repos_url":"https://api.github.com/users/DenHeadless/repos","events_url":"https://api.github.com/users/DenHeadless/events{/privacy}","received_events_url":"https://api.github.com/users/DenHeadless/received_events","type":"User","site_admin":false},"milestone":null,"comments":1,"created_at":"2015-12-02T11:02:09Z","updated_at":"2015-12-02T14:59:38Z","closed_at":null,"body":"Hello,\r\n\r\nfirst of all thank you for the wonderful library! It saves a ton of code and it keeps the view controllers clean and light!\r\n\r\nI developed a Realm storage class. Since it's too time spending for me at the moment to create a pull request, due to the various dependencies, I paste it here:\r\n\r\n```\r\nclass RealmStorage: BaseStorage, StorageProtocol\r\n{\r\n    var sections: [Section] = [Section]()\r\n    \r\n    func objectAtIndexPath(path: NSIndexPath) -> Any? {\r\n        if path.section >= self.sections.count {\r\n            return nil\r\n        } else {\r\n            let sectionModel = self.sections[path.section] as? SectionObjects\r\n            \r\n            return sectionModel?.objectAtIndex(path.row)\r\n        }\r\n\r\n    }\r\n    \r\n    func setSectionHeaderModel<T>(model: T?, forSectionIndex sectionIndex: Int)\r\n    {\r\n        assert(self.supplementaryHeaderKind != nil, \"supplementaryHeaderKind property was not set before calling setSectionHeaderModel: forSectionIndex: method\")\r\n        (sectionAtIndex(sectionIndex) as! SectionResults).setSupplementaryModel(model, forKind: self.supplementaryHeaderKind!)\r\n    }\r\n    \r\n    func setSectionFooterModel<T>(model: T?, forSectionIndex sectionIndex: Int)\r\n    {\r\n        assert(self.supplementaryFooterKind != nil, \"supplementaryFooterKind property was not set before calling setSectionFooterModel: forSectionIndex: method\")\r\n        (self.sectionAtIndex(sectionIndex) as! SectionResults).setSupplementaryModel(model, forKind: self.supplementaryFooterKind!)\r\n    }\r\n    \r\n    func setSupplementaries<T>(models : [T], forKind kind: String)\r\n    {\r\n        self.startUpdate()\r\n        \r\n        if models.count == 0 {\r\n            for index in 0..<self.sections.count {\r\n                let section = self.sections[index] as! SectionModel\r\n                section.setSupplementaryModel(nil, forKind: kind)\r\n            }\r\n            return\r\n        }\r\n        \r\n        assert(sections.count < models.count - 1, \"The section should be set before setting supplementaries\")\r\n        \r\n        for index in 0..<models.count {\r\n            let section = self.sections[index] as! SectionModel\r\n            section.setSupplementaryModel(models[index], forKind: kind)\r\n        }\r\n        \r\n        finishUpdate()\r\n    }\r\n    \r\n    /// Set section header models.\r\n    /// - Note: `supplementaryHeaderKind` property should be set before calling this method.\r\n    /// - Parameter models: section header models\r\n    func setSectionHeaderModels<T>(models : [T])\r\n    {\r\n        assert(self.supplementaryHeaderKind != nil, \"Please set supplementaryHeaderKind property before setting section header models\")\r\n        self.setSupplementaries(models, forKind: self.supplementaryHeaderKind!)\r\n    }\r\n    \r\n    /// Set section footer models.\r\n    /// - Note: `supplementaryFooterKind` property should be set before calling this method.\r\n    /// - Parameter models: section footer models\r\n    func setSectionFooterModels<T>(models : [T])\r\n    {\r\n        assert(self.supplementaryFooterKind != nil, \"Please set supplementaryFooterKind property before setting section header models\")\r\n        self.setSupplementaries(models, forKind: self.supplementaryFooterKind!)\r\n    }\r\n    \r\n    /// Set items for specific section. This will reload UI after updating.\r\n    /// - Parameter items: items to set for section\r\n    /// - Parameter forSectionIndex: index of section to update\r\n    func addSection<O: Object>(withResults results: Results<O>, viewModel: ((object: O, index: Int) -> ViewModel)?)\r\n    {\r\n        let section = SectionResults<O>(results: results)\r\n        section.viewModel = viewModel\r\n        sections.append(section)\r\n        \r\n        self.delegate?.storageNeedsReloading()\r\n    }\r\n    \r\n    /// Delete sections in indexSet\r\n    /// - Parameter sections: sections to delete\r\n    func deleteSections(sections : NSIndexSet)\r\n    {\r\n        self.startUpdate()\r\n        \r\n        for var i = sections.lastIndex; i != NSNotFound; i = sections.indexLessThanIndex(i) {\r\n            self.sections.removeAtIndex(i)\r\n        }\r\n        self.currentUpdate?.deletedSectionIndexes.addIndexes(sections)\r\n        \r\n        self.finishUpdate()\r\n    }\r\n}\r\n\r\n// MARK: - Searching in storage\r\nextension RealmStorage\r\n{\r\n    func itemAtIndexPath(indexPath: NSIndexPath) -> Any?\r\n    {\r\n        return self.objectAtIndexPath(indexPath)\r\n    }\r\n    \r\n    func indexPathForItem<T: Equatable>(searchableItem : T) -> NSIndexPath?\r\n    {\r\n        for sectionIndex in 0..<self.sections.count\r\n        {\r\n            let rows = self.sections[sectionIndex].objects\r\n            \r\n            for rowIndex in 0..<rows.count {\r\n                if let item = rows[rowIndex] as? T {\r\n                    if item == searchableItem {\r\n                        return NSIndexPath(forItem: rowIndex, inSection: sectionIndex)\r\n                    }\r\n                }\r\n            }\r\n            \r\n        }\r\n        return nil\r\n    }\r\n    \r\n    /// Retrieve section model for specific section.\r\n    /// - Parameter sectionIndex: index of section\r\n    /// - Note: if section did not exist prior to calling this, it will be created, and UI updated.\r\n    func sectionAtIndex(sectionIndex : Int) -> Section?\r\n    {\r\n        self.startUpdate()\r\n        if sectionIndex < sections.count {\r\n            let section = sections[sectionIndex]\r\n            self.finishUpdate()\r\n            return section\r\n        }\r\n        self.finishUpdate()\r\n        return nil\r\n    }\r\n    \r\n    /// Index path array for items\r\n    func indexPathArrayForItems<T:Equatable>(items:[T]) -> [NSIndexPath]\r\n    {\r\n        var indexPaths = [NSIndexPath]()\r\n        \r\n        for index in 0..<items.count {\r\n            if let indexPath = self.indexPathForItem(items[index])\r\n            {\r\n                indexPaths.append(indexPath)\r\n            }\r\n        }\r\n        return indexPaths\r\n    }\r\n    \r\n    /// Sorted array of index paths - useful for deletion.\r\n    class func sortedArrayOfIndexPaths(indexPaths: [NSIndexPath], ascending: Bool) -> [NSIndexPath]\r\n    {\r\n        let unsorted = NSMutableArray(array: indexPaths)\r\n        let descriptor = NSSortDescriptor(key: \"self\", ascending: ascending)\r\n        return unsorted.sortedArrayUsingDescriptors([descriptor]) as! [NSIndexPath]\r\n    }\r\n}\r\n\r\n// MARK: - HeaderFooterStorageProtocol\r\nextension RealmStorage :HeaderFooterStorageProtocol\r\n{\r\n    /// Header model for section.\r\n    /// - Requires: supplementaryHeaderKind to be set prior to calling this method\r\n    /// - Parameter index: index of section\r\n    /// - Returns: header model for section, or nil if there are no model\r\n    func headerModelForSectionIndex(index: Int) -> Any? {\r\n        assert(self.supplementaryHeaderKind != nil, \"supplementaryHeaderKind property was not set before calling headerModelForSectionIndex: method\")\r\n        return self.supplementaryModelOfKind(self.supplementaryHeaderKind!, sectionIndex: index)\r\n    }\r\n    \r\n    /// Footer model for section.\r\n    /// - Requires: supplementaryFooterKind to be set prior to calling this method\r\n    /// - Parameter index: index of section\r\n    /// - Returns: footer model for section, or nil if there are no model\r\n    func footerModelForSectionIndex(index: Int) -> Any? {\r\n        assert(self.supplementaryFooterKind != nil, \"supplementaryFooterKind property was not set before calling footerModelForSectionIndex: method\")\r\n        return self.supplementaryModelOfKind(self.supplementaryFooterKind!, sectionIndex: index)\r\n    }\r\n}\r\n\r\n// MARK: - SupplementaryStorageProtocol\r\nextension RealmStorage : SupplementaryStorageProtocol\r\n{\r\n    /// Retrieve supplementary model of specific kind for section.\r\n    /// - Parameter kind: kind of supplementary model\r\n    /// - Parameter sectionIndex: index of section\r\n    /// - SeeAlso: `headerModelForSectionIndex`\r\n    /// - SeeAlso: `footerModelForSectionIndex`\r\n    func supplementaryModelOfKind(kind: String, sectionIndex: Int) -> Any? {\r\n        if let section = sections[sectionIndex] as? SectionResults {\r\n            return section.supplementaryModelOfKind(kind)\r\n        }\r\n        \r\n        return nil\r\n    }\r\n}\r\n```\r\n\r\nAnd then the SectionResults:\r\n\r\n```\r\nprotocol SectionObjects {\r\n    func objectAtIndex(index: Int) -> Any?\r\n}\r\n\r\nclass SectionResults<T: Object>: Section, SectionObjects {\r\n    var results: Results<T>?\r\n    \r\n    var viewModel: ((object: T, index: Int) -> ViewModel)?\r\n    \r\n    init(results: Results<T>?) {\r\n        self.results = results\r\n    }\r\n    \r\n    var objects: [Any] {\r\n        get {\r\n            return [\"\"]\r\n        }\r\n    }\r\n    \r\n    func objectAtIndex(index: Int) -> Any? {\r\n        if viewModel != nil {\r\n            return viewModel!(object: results![index], index: index)\r\n        }\r\n        return results?[index]\r\n    }\r\n    \r\n    var numberOfObjects: Int {\r\n        get {\r\n            return results!.count\r\n        }\r\n    }\r\n    \r\n    private var supplementaries = [String:Any]()\r\n    \r\n    /// Retrieve supplementaryModel of specific kind\r\n    /// - Parameter: kind - kind of supplementary\r\n    /// - Returns: supplementary model or nil, if there are no model\r\n    func supplementaryModelOfKind(kind: String) -> Any?\r\n    {\r\n        return self.supplementaries[kind]\r\n    }\r\n    \r\n    /// Set supplementary model of specific kind\r\n    /// - Parameter model: model to set\r\n    /// - Parameter forKind: kind of supplementary\r\n    func setSupplementaryModel(model : Any?, forKind kind: String)\r\n    {\r\n        self.supplementaries[kind] = model\r\n    }\r\n}\r\n```\r\n\r\n\r\nThe class doesn't retain the objects in memory but it uses the graph queries of Realm in order to be able to smoothly include thousands of objects in a table view.\r\nAs a final note, I added the viewModel var, because since sometimes it's better to provide a viewModel instead of the real object.\r\n\r\nAnyway, this is just a draft, feel free to modify as you like!\r\n\r\nThank you!\r\nDavide"},"comment":{"url":"https://api.github.com/repos/DenHeadless/DTModelStorage/issues/comments/161324418","html_url":"https://github.com/DenHeadless/DTModelStorage/issues/7#issuecomment-161324418","issue_url":"https://api.github.com/repos/DenHeadless/DTModelStorage/issues/7","id":161324418,"user":{"login":"DenHeadless","id":853604,"avatar_url":"https://avatars.githubusercontent.com/u/853604?v=3","gravatar_id":"","url":"https://api.github.com/users/DenHeadless","html_url":"https://github.com/DenHeadless","followers_url":"https://api.github.com/users/DenHeadless/followers","following_url":"https://api.github.com/users/DenHeadless/following{/other_user}","gists_url":"https://api.github.com/users/DenHeadless/gists{/gist_id}","starred_url":"https://api.github.com/users/DenHeadless/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DenHeadless/subscriptions","organizations_url":"https://api.github.com/users/DenHeadless/orgs","repos_url":"https://api.github.com/users/DenHeadless/repos","events_url":"https://api.github.com/users/DenHeadless/events{/privacy}","received_events_url":"https://api.github.com/users/DenHeadless/received_events","type":"User","site_admin":false},"created_at":"2015-12-02T14:59:38Z","updated_at":"2015-12-02T14:59:38Z","body":"Thanks, @augmentedworks!\r\n\r\nTo be honest, I don't have experience with Realm, so it might take some time before this feature can be released, but it looks like you are on the right track here.\r\n\r\nIf this feature will be finished, i'll probably make a podspec, something like DTModelStorage/RealmStorage, that includes RealmSwift as a dependency.\r\n\r\nI'll probably have some time next weekend to look this through. If you need this stuff earlier, i would really be glad to have your help, since you are clearly more educated with Realm stuff."}}