I’m developing an application similar to an simple chat app and I need to use core data to save/fetch the chats based on specific user. I have now successfully created a model to save users, now I need to link them to their chats.
For Saving user data I’ve created Entity UserData and below are my swift files
UserData+CoreDataProperties.swift
import Foundation
import CoreData
extension UserData {
#NSManaged var firstName: String?
#NSManaged var userStatus: String?
#NSManaged var userId: String?
#NSManaged var userStatus: String?
#NSManaged var lastName: String?
#NSManaged var profilePic: String?
}
UserData.swift
class UserData: NSManagedObject {
convenience init(WithDictionary dict:NSDictionary){
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let newEntity = NSEntityDescription.entityForName("UserData", inManagedObjectContext:managedContext)
// initializer on NSManagedObject class
self.init(entity: newEntity!, insertIntoManagedObjectContext: managedContext)
self.userId = (dict.valueForKey(ID) != nil) && !(dict.valueForKey(ID) is NSNull)
? dict.valueForKey(ID) as! String
: ""
//similary initializing other variables
//Saving to database
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
I was able to successfully save the user list using this class. Now I’ve created a ChatData Entity, below is its structure.
ChatData+CoreDataProperties.swift
import Foundation
import CoreData
extension ChatData {
#NSManaged var chatId: String?
#NSManaged var chatOwnerName: String?
#NSManaged var chatReadStatus: Boolean?
#NSManaged var chatText: String?
#NSManaged var chatTimestamp: String?
#NSManaged var chatType: String?
#NSManaged var imageData: String?
#NSManaged var imageUrl: String?
}
Now for each specific user I should be able to create multiple ChatData objects corresponding to particular userId. I don’t have much experience with core data. I’ve looked at some samples on creating relationship, but I’m still not sure how it works. Do I need to create a relationship? If so how should I do it to make this work?
You can modify UserData like this
extension UserData {
#NSManaged var firstName: String?
#NSManaged var userStatus: String?
#NSManaged var userId: String?
#NSManaged var userStatus: String?
#NSManaged var lastName: String?
#NSManaged var profilePic: String?
#NSManaged var chats: Set<ChatData>?
}
and ChatData like this
extension ChatData {
#NSManaged var chatId: String?
#NSManaged var chatOwnerName: String?
#NSManaged var chatReadStatus: Boolean?
#NSManaged var chatText: String?
#NSManaged var chatTimestamp: String?
#NSManaged var chatType: String?
#NSManaged var imageData: String?
#NSManaged var imageUrl: String?
#NSManaged var user: UserData?
}
The corresponding core data model has a one-to-many releationship from UserData to ChatData (some attributes are missing):
Some code that shows how you can create a user with two messages:
let user=userWithName("MyName")
let chat01=chatWithText("How do you doing?")
let chat02=chatWithText("Fine.")
user?.chats=[chat01!,chat02!]
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.saveContext()
with
func userWithName(name:String) -> UserData? {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let userEntity = NSEntityDescription.entityForName("UserData", inManagedObjectContext:managedContext)
let user = NSManagedObject(entity: userEntity!, insertIntoManagedObjectContext: managedContext) as! UserData
user.firstName=name
return user
}
func chatWithText(text:String) -> ChatData? {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let chatEntity = NSEntityDescription.entityForName("ChatData", inManagedObjectContext:managedContext)
let chat = NSManagedObject(entity: chatEntity!, insertIntoManagedObjectContext: managedContext) as! ChatData
chat.chatText=text
return chat
}
Related
I have two entities
#objc(Movies)
public class Movies: NSManagedObject {
}
extension Movies {
#nonobjc public class func fetchRequest() -> NSFetchRequest<Movies> {
return NSFetchRequest<Movies>(entityName: "Movies")
}
#NSManaged public var id: Int64
#NSManaged public var isFav: Bool
#NSManaged public var overview: String?
#NSManaged public var poster: String?
#NSManaged public var release_date: String?
#NSManaged public var title: String?
#NSManaged public var genresID: NSSet?
}
// MARK: Generated accessors for genresID
extension Movies {
#objc(addGenresIDObject:)
#NSManaged public func addToGenresID(_ value: GenresID)
#objc(removeGenresIDObject:)
#NSManaged public func removeFromGenresID(_ value: GenresID)
#objc(addGenresID:)
#NSManaged public func addToGenresID(_ values: NSSet)
#objc(removeGenresID:)
#NSManaged public func removeFromGenresID(_ values: NSSet)
}
#objc(GenresID)
public class GenresID: NSManagedObject {
}
extension GenresID {
#nonobjc public class func fetchRequest() -> NSFetchRequest<GenresID> {
return NSFetchRequest<GenresID>(entityName: "GenresID")
}
#NSManaged public var id: Int64
#NSManaged public var name: String?
#NSManaged public var movieID: Movies?
}
When I click a button an action is triggered to save a movie, and then I would like to save that movie that has been "favored". A movie can have multiples genres (one-to-many relationship).
Method action:
func saveMoviesDB (movie: Movie) {
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let entityMovie = NSEntityDescription.entity(forEntityName: "Movies", in: managedContext)!
let entityGenres = NSEntityDescription.entity(forEntityName: "GenresID", in: managedContext)!
let movieDB = NSManagedObject(entity: entityMovie, insertInto: managedContext)
let genresDB = NSManagedObject(entity: entityGenres, insertInto: managedContext)
movieDB.setValue(movie.id, forKey: "id")
movieDB.setValue(movie.title, forKey: "title")
movieDB.setValue(movie.isFav, forKey: "isFav")
movieDB.setValue(movie.poster, forKey: "poster")
movieDB.setValue(movie.overview, forKey: "overview")
movieDB.setValue(movie.releaseDate, forKey: "release_date")
do{
try managedContext.save()
moviesDB.append(movieDB)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
I don't know how to assign multiple genresID to the Movie. For each movie, there is an Int array containing the Ids of the genres.
EDIT: I decided to remove the genre entity and create a transformable type property in Movies to store the arrays of Int. It went like this:
extension Movies {
#nonobjc public class func fetchRequest() -> NSFetchRequest<Movies> {
return NSFetchRequest<Movies>(entityName: "Movies")
}
#NSManaged public var id: Int64
#NSManaged public var isFav: Bool
#NSManaged public var overview: String?
#NSManaged public var poster: String?
#NSManaged public var release_date: String?
#NSManaged public var title: String?
#NSManaged public var genresID: [NSNumber]?
}
And then I cast it before saving it to the database
let genresID = movie.genre as [NSNumber]
I have six entities in my xcdatamodeld. Article, Section, References, Bookmarks, BookmarkReferences and BookmarkSections. I am trying to save the bookmarked articles separately to the Bookmarks entity. The Article has inverse set to Sections and References similarly Bookmarks has inverse set to BookmarkReferences and BookmarkSections. When i try to set the values from Article NSManagedObject to Bookmarks NSManagedObj i am getting KVC error. I have made sure that there are no typos in the key names. Have a look at the code and log.
extension Bookmarks {
#nonobjc public class func fetchRequest() -> NSFetchRequest<Bookmarks> {
return NSFetchRequest<Bookmarks>(entityName: "Bookmarks");
}
#NSManaged public var id: String?
#NSManaged public var status: String?
#NSManaged public var createdBy: String?
#NSManaged public var articleType: String?
#NSManaged public var modifiedBy: String?
#NSManaged public var tag: String?
#NSManaged public var sendNotification: Bool
#NSManaged public var bookmark: Bool
#NSManaged public var isRead: Bool
#NSManaged public var isArticleFromSearch: Bool
#NSManaged public var searchString: String?
#NSManaged public var isArticleFromCategory: Bool
#NSManaged public var modifiedDate: String?
#NSManaged public var createdDate: String?
#NSManaged public var category: String?
#NSManaged public var subCategory: String?
#NSManaged public var title: String?
#NSManaged public var general: NSDictionary?
#NSManaged public var bookmarkSections: NSSet?
#NSManaged public var bookmarkReferences: NSSet?
}
extension BookmarkSections {
static func saveSectionsForBookmarks(entity: Article, privateContext: NSManagedObjectContext) -> NSSet {
let sections = entity.sections
let sectionED = NSEntityDescription.entity(forEntityName: "BookmarkSections", in: privateContext)
let sectionMO = NSManagedObject(entity: sectionED!, insertInto: privateContext)
let sectionsSet = NSMutableSet()
let allSectionItems = sections?.allObjects
for (_, sectionItem) in (allSectionItems?.enumerated())! {
let castedSection = sectionItem as? Sections
sectionMO.setValue(castedSection!.id, forKey: "id")
sectionMO.setValue(castedSection!.text, forKey: "text")
sectionMO.setValue(castedSection!.imageUrl, forKey: "imageUrl")
sectionMO.setValue(castedSection!.imageName, forKey: "imageName")
sectionMO.setValue(castedSection!.title, forKey: "title")
sectionsSet.add(sectionMO)
}
return sectionsSet
}
}
[`
extension Bookmarks {
public static func saveToNew(Entity: Article) {
let managedContext = CoreDataStorage.sharedInstance.privateQueueContext
let entityDesc =
NSEntityDescription.entity(forEntityName: "Bookmarks",
in: managedContext)!
let articleMO = NSManagedObject(entity: entityDesc,
insertInto: managedContext)
articleMO.setValue(Entity.id, forKey: "id")
articleMO.setValue(Entity.status, forKey: "status")
articleMO.setValue(Entity.createdBy, forKey: "createdBy")
articleMO.setValue(Entity.articleType, forKey: "articleType")
articleMO.setValue(Entity.modifiedBy, forKey: "modifiedBy")
let isSendNotification=NSNumber(value: false)
articleMO.setValue(isSendNotification, forKey: "sendNotification")
let modifiedDate = String(describing: Entity.modifiedDate)
articleMO.setValue(modifiedDate, forKey: "modifiedDate")
let createdDate = String(describing: Entity.createdDate)
articleMO.setValue(createdDate, forKey: "createdDate")
articleMO.setValue(Entity.category, forKey: "category")
articleMO.setValue(Entity.subCategory, forKey: "subCategory")
let general = NSMutableDictionary()
let dict = Entity.general
for (key,subJson):(Any, Any) in dict! {
general.setValue(subJson as! String, forKey: key as! String)
}
articleMO.setValue(general, forKey: "general")
articleMO.setValue(Entity.title, forKey: "title")
articleMO.setValue(BookmarkSections.saveSectionsForBookmarks(entity: Entity, privateContext: managedContext), forKey: "bookmarkSections")
articleMO.setValue(Entity.references, forKey: "references")
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
`]
Error:
I am working on iPhone application where I need to implement one to many relationship from one entity to another entity.I have export NSManagedObject subclass from coredata database but could not find relation accessors in core data model file like Objective-C.
Although I'm able to set data in relationship NSSet but this only persist while iPhone app is running. Once I kill and restart the application I didn't get entity relationship for in fetch request from core data.
I am not sure what I am doing wrong. It will be great if anyone can tell me how to set data in NSSet relationship object. Any sample example will be a great help
Here is my core data model files. One folder can content multiple content as folder detail
extension FolderContent {
#NSManaged var contentID: NSNumber?
#NSManaged var contentTitle: String?
#NSManaged var contentType: String?
#NSManaged var publishDate: String?
#NSManaged var folderList: NSSet?
}
extension FolderList {
#NSManaged var folderID: NSNumber?
#NSManaged var folderName: String?
#NSManaged var folderDetail: NSSet?
}
func updateFolderList()
{
// Initialize Fetch Request
let fetchRequest = NSFetchRequest()
// Create Entity Description
let entityDescription = NSEntityDescription.entityForName(FOLDER_LIST, inManagedObjectContext: self.managedObjectContext)
// Configure Fetch Request
fetchRequest.entity = entityDescription
do {
let result = try self.managedObjectContext.executeFetchRequest(fetchRequest).last as! FolderList
let content = result.mutableSetValueForKey("folderDetail")
content.addObject(self.getContent())
var folderContent:FolderContent = result.folderDetail?.allObjects.first as! FolderContent
print(folderContent.contentTitle)
self.save()
print(result)
} catch {
let fetchError = error as NSError
print(fetchError)
}
}
func getContent()->FolderContent
{
let folderContent = NSEntityDescription.insertNewObjectForEntityForName(FOLDER_CONTENT, inManagedObjectContext: self.managedObjectContext) as! FolderContent
folderContent.contentID = 1
folderContent.contentTitle = "Sandeep"
folderContent.contentType = "Product"
return folderContent
}
If the relationship of FolderContent and FolderList is defined as
A FolderContent have many FolderList(s)
A FolderList only belongs to a FolderContent
FolderContent
extension FolderContent {
#NSManaged var contentID: NSNumber?
#NSManaged var contentTitle: String?
#NSManaged var contentType: String?
#NSManaged var publishDate: String?
#NSManaged var folderList: Set<FolderList>?
}
FolderList
extension FolderList {
#NSManaged var folderID: NSNumber?
#NSManaged var folderName: String?
#NSManaged var folderDetail: FolderContent?
}
Let say you want to persist the record and its relationship
func persistRecords() {
// Insert the new records
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let folderContentEntity = NSEntityDescription.entityForName("FolderContent", inManagedObjectContext: managedContext)
let folderListEntity = NSEntityDescription.entityForName("FolderList", inManagedObjectContext: managedContext)
//Create FolderContent record
let folderContentObject = FolderContent(entity: folderContentEntity!, insertIntoManagedObjectContext: managedContext)
folderContentObject.setValue(CONTENTID, forKeyPath: "contentID")
...
//Create FolderList record
let folderListObject = FolderList(entity: folderListEntity!, insertIntoManagedObjectContext: managedContext)
folderListObject.setValue(FOLDERID, forKeyPath: "folderID")
...
//Set relationship here
folderListObject.folderDetail = folderContentObject
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
I am guessing you did something like folder.folderDetail.addObject. With core data that won't work because core data behind the scenes is doing lots of things to maintain graph integrity. You have to use mutableSetValueForKey to get the set and have core data work its magic.
I have a User model class (generated by XCode with Swift):
#objc(User)
class User: NSManagedObject { }
And it's extension:
extension User {
#NSManaged var id: NSNumber?
#NSManaged var firstName: String?
#NSManaged var lastName: String?
#NSManaged var birthYear: NSNumber?
}
I can save/fetch data from CoreData.
But can I use this class for object management without CoreData things? Or i need to create other class/struct for this?
For example, create User object (without ObjectContext), set his attributes and send it as property in some func? Maybe i can create some struct in class User (like struct {var firstNameData, secondNameData,...}) and use it in code?
I updated class:
struct User {
var id: Int!
var firstName: String!
var lastName: String!
var birthYear: UInt?
}
#objc(UserManagedObject)
class UserManagedObject: NSManagedObject {
func toStruct() -> User {
var userData = User()
userData.id = Int(self.id)
userData.firstName = self.firstName
userData.lastName = self.lastName
if let by = self.birthYear {
userData.birthYear = UInt(by)
}
return userData
}
}
Now for object management i use struct User and UserManagedObject for CoreData in/out
I have Core Data with five objects. It's four String and one NSData (UIImage). I save them in Core Data. Then load in UIViewController and I want to delete them from Core Data and I got different errors. I tried different methods but it doesn't helped me. How do I delete these data?
var name: String!
var text: String!
var image: UIImage!
var url: String!
var data: String!
func deleteAll() {
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var managedObjectContext: NSManagedObjectContext = appDel.managedObjectContext!
var coreDataName: NSManagedObject = (name as AnyObject?) as! NSManagedObject
var coreDataImage: NSManagedObject = (image as AnyObject?) as! NSManagedObject
var coreDataText: NSManagedObject = (text as AnyObject?) as! NSManagedObject
var coreDataData: NSManagedObject = (data as AnyObject?) as! NSManagedObject
var coreDataURL: NSManagedObject = (url as AnyObject?) as! NSManagedObject
managedObjectContext.deleteObject(coreDataName)
managedObjectContext.deleteObject(coreDataImage)
managedObjectContext.deleteObject(coreDataText)
managedObjectContext.deleteObject(coreDataData)
managedObjectContext.deleteObject(coreDataURL)
managedObjectContext.save(nil)
buttonDelete.enabled = false
buttonShare.enabled = false
}
}
My Core Data file
import Foundation
import CoreData
#objc(News)
class News: NSManagedObject {
#NSManaged var dateNewsCoreDataString: String
#NSManaged var imageNewsCoreData: NSData // NSData
#NSManaged var nameNewsCoreData: String
#NSManaged var textNewsCoreData: String
#NSManaged var urlNewsCoreData: String
}
I changed my code and it work for me.
var detailObject: AnyObject? // It's data from FavoriteTableViewController
func deleteAll() {
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var managedObjectContext: NSManagedObjectContext = appDel.managedObjectContext!
var dataDelete = detailObject as! NSManagedObject
managedObjectContext.deleteObject(dataDelete)
managedObjectContext.save(nil)
managedObjectContext.save(nil)
buttonDelete.enabled = false
buttonShare.enabled = false
}