I'm creating my first iOS app in Swift, and I'm stuck on a basic thing. I want to create a custom class and set a variable. I keep seeing the error "Value of type [Item] has no member [name].
This is my custom class:
import UIKit
import Foundation
import CoreData
class Item:NSManagedObject {
var name:String?
convenience init(name: String?, insertIntoManagedObjectContext context: NSManagedObjectContext!) {
let entity = NSEntityDescription.entityForName("ItemEntity", inManagedObjectContext: context)!
self.init(entity: entity, insertIntoManagedObjectContext: context)
}
}
And this is my code that tries to use it:
func editItem(id:Int, category:String, brand:String, name:String, colour:String, purchasePrice:String, purchaseDate:String, expiryDate:String) -> Int {
// vars
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("ItemEntity", inManagedObjectContext: managedContext)
let item = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)
var listItem = [Item]()
let fetchRequest = NSFetchRequest(entityName: "ItemEntity")
// fetch the item from the core data with the same ID
do{
let predicate = NSPredicate(format: "id == %#", String(id))
fetchRequest.predicate = predicate
fetchRequest.fetchLimit = 1
let results = try managedContext.executeFetchRequest(fetchRequest)
listItem = results as! [Item]
}
catch {
let fetchError = error as NSError
print (fetchError)
}
// edit the item
listItem.name = "text" // !! THIS IS THE LINE WHICH DISPLAYS THE ERROR
// save the item
do {
try managedContext.save()
}
catch {
let saveError = error as NSError
print (saveError)
}
}
Really appreciate your help, this one seems so basic but a lot of googling hasn't helped me figure it out.
listItem is an array of Item, so if you want to change the name of one thing in this list you should specify the index you wanna change, like
listItem[0].name = "text"
Put spaces around the colon. Syntax if I'm not mistaken.
I think the problem code is here:
let item = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext) as! Item
By default, the item type is NSManagedObject, so listItem have no member [name]. You need to cast down it to Item Object.
Related
When I try to save a relationship to core data it throws the above error in the title. I'm basically creating a messaging app and data model is attached. This is doing the same thing when trying to save to other relationships too. Can I save all of my data models at once or should I save one at a time and then go back and add the relationships after the model has been saved with its regular attributes. **Data Model Visual
static func save(sender: UserCD, message: String) -> Conversation? {
let convo: Conversation? = nil
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return convo
}
if #available(iOS 10.0, *) {
let context = appDelegate.persistentContainer.viewContext
let now = Date()
let messageEntity = NSEntityDescription.entity(forEntityName: "Message", in: context)
let newMessage = NSManagedObject(entity: messageEntity!, insertInto: context) as! Message
let conversationEntity = NSEntityDescription.entity(forEntityName: "Conversation", in: context)
let newConvo = NSManagedObject(entity: conversationEntity!, insertInto: context) as! Conversation
newMessage.setValue(UUID().uuidString, forKey: "messageId")
newMessage.setValue(message, forKey: "text")
newMessage.setValue(now, forKey: "timestamp")
newMessage.setValue(sender, forKey: "sender")
newConvo.setValue(UUID().uuidString, forKey: "conversationId")
newConvo.setValue(now, forKey: "startDate")
newConvo.setValue(now, forKey: "lastMessageDate")
newConvo.addMessage(message: newMessage)
sender.addMessage(message: newMessage)
sender.addConversation(conversation: newConvo)
do {
try newMessage.managedObjectContext?.save()
try sender.managedObjectContext?.save()
try newConvo.managedObjectContext?.save()
return newConvo
} catch {
let saveError = error as NSError
print("Failed to save conversastion: \(saveError.debugDescription)")
}
}
return convo
}
It fails on line "newConvo.addMessage(message: newMessage)"
#NSManaged public var messages: Message?
func addMessage(message: Message) {
let messages = self.mutableSetValue(forKey: "messages")
messages.add(message)
}
The error message
The left hand side for an ALL or ANY operator must be either an NSArray or an NSSet
is pretty clear:
You declared messages as to-one relationship Message.
The sender of the method addMessage must be a to-many relationship Set<Message>
I'm making a game that has a few constants that are in it:
struct moneyConstants {
static var tapValue = NSInteger()
static var tapMultiplier = NSInteger()
static var moneyPerSecond = NSInteger()
static var money = NSInteger()
}
I'm using CoreData to save the values after when the application closes. I want to know if you are able to save multiple values at once. Lets say my code to save something is:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("Constants", inManagedObjectContext:managedContext)
let moneyS = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
moneyS.setValue(moneyConstants.money, forKey: "moneySave")
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
If I wanted to save a second value like:
let moneyPerSecondS = NSManagedObject(entity:entity!, insertIntoManagedObjectContext:managedContext)
moneyPerSecondS.setValue(moneyConstants.moneyPerSecond, forKey: "money")
Can I place those lines before the do { section? Or do I have to put it after the do { section and then write another do { section?
Of course you can (if the attributes are declared in the model):
let moneyS = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
moneyS.setValue(moneyConstants.money, forKey: "moneySave")
moneyS.setValue(moneyConstants.moneyPerSecond, forKey: "money")
Everything which does not throw is not required to be placed in a do scope.
I'm trying to add data to Core Data, which I think i'm on the right track (I'm fairly new to this so, apologies) From the code below, my 'Aim' is to check the Core Data and if it's empty add the default data.
Code:
class func musicIsEmpty(managedObjectContext: NSManagedObjectContext)-> Bool{
let defaultMusic = NSEntityDescription.entityForName("Music", inManagedObjectContext: managedObjectContext)
let defaultMusicSetOne = NSManagedObject(entity: defaultMusic!, insertIntoManagedObjectContext: managedObjectContext) as? Music
//defaultMusicSetOne = NSManagedObject(entity: defaultMusic!, insertIntoManagedObjectContext: managedObjectContext) as? Music
let fetchRequest = NSFetchRequest(entityName: "Music")
fetchRequest.entity = defaultMusic
defaultMusicSetOne!.uri = "spotify:track:1puJlKuYGH58SAFgXREUpE"
defaultMusicSetOne!.duration = 30.0
defaultMusicSetOne!.starttime = 49.0
defaultMusicSetOne!.xfade = 10.0
defaultMusicSetOne!.voiceover = "1.25s Next Up.mp3"
do{
if let MusicSetResults = try managedObjectContext.executeFetchRequest(fetchRequest) as? [NSManagedObject]{
if MusicSetResults == 0
{
defaultMusic!.setValue(defaultMusicSetOne?.uri, forKey: "uri")
defaultMusic!.setValue(defaultMusicSetOne?.duration, forKey: "duration")
defaultMusic!.setValue(defaultMusicSetOne?.starttime, forKey: "starttime")
defaultMusic!.setValue(defaultMusicSetOne?.xfade, forKey: "xfade")
defaultMusic!.setValue(defaultMusicSetOne?.voiceover, forKey: "voiceover")
return true
}
else
{
return false
}
}
}
catch let error as NSError{
print("Error: \(error.debugDescription)")
}
return false
}
Music.Swift:
extension Music {
#NSManaged var voiceover: String?
#NSManaged var xfade: NSNumber?
#NSManaged var duration: NSNumber?
#NSManaged var starttime: NSNumber?
#NSManaged var uri: String?
}
But I keep getting the error "This class is not key value coding-compliant for the key uri" i'm sure this will be for all .setValues. I'm not sure why this is showing as defaultMusic does have the "uri" field and defaultMusic is also an instance of Music Object. Is the format of .setValue wrong? or is it something else?
Any help would be great!
Thanks in advance!!
I suspect you actually mean this:
Check if the entity is empty, if yes insert a new object with default values
class func musicIsEmpty(managedObjectContext: NSManagedObjectContext)-> Bool {
let musicEntity = NSEntityDescription.entityForName("Music", inManagedObjectContext: managedObjectContext)!
let fetchRequest = NSFetchRequest()
fetchRequest.entity = musicEntity
do {
let musicSetResults = try managedObjectContext.executeFetchRequest(fetchRequest) as! [Music]
if musicSetResults.isEmpty
{
let defaultMusicSetOne = NSManagedObject(entity: musicEntity, insertIntoManagedObjectContext: managedObjectContext) as! Music
defaultMusicSetOne.uri = "spotify:track:1puJlKuYGH58SAFgXREUpE"
defaultMusicSetOne.duration = 30.0
defaultMusicSetOne.starttime = 49.0
defaultMusicSetOne.xfade = 10.0
defaultMusicSetOne.voiceover = "1.25s Next Up.mp3"
return true
}
}
catch let error as NSError{
print("Error: \(error.debugDescription)")
}
return false
}
You might consider also to save the managed object context to make the new object persistent.
defaultMusic is a NSEntityDescription, not a Music object.
(Sometimes letting Swift use default data types can be confusing.)
referring to my previous question: Unique value of object to use in section Swift
my problem now is core data. this is code to save data following the previous code to populate section and table:
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let entity = NSEntityDescription.entityForName("Movie", inManagedObjectContext: context)!
let movie = Movie(entity: entity, insertIntoManagedObjectContext: context)
movie.title = title.text
movie.plot = plot.text
movie.genre = genre.text
context.insertObject(movie)
do {
try context.save()
} catch {
print("Could not save movie")
}
and fetch data is:
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Movie")
do {
let results = try context.executeFetchRequest(fetchRequest)
self.loadMovie = results as! [Movie]
} catch let err as NSError {
print(err.debugDescription)
}
}
but nothing I receive the error on loadMovie Line..
where am I wrong?
First of all, delete the line
context.insertObject(movie)
because the object has already been inserted in the let movie = line.
To load the movies you need to recreate the data structure using the insertMovie(movie : Movie) function.
let movies = try context.executeFetchRequest(fetchRequest) as! [Movie]
loadMovie.removeAll()
for movie in movies {
insertMovie(movie)
}
As the answer of your previous question suggested, the self.loadMovie now has type [String:[Movie]], so you should probably try casting results as [String:[Movie]].
Try self.loadMovie = results as! [String:[Movie]] instead.
I have passed two parameters from another tableview in order to save my notes "my Text" in different array. I just want to save myText for different row for the tableview but now i can just save and see the common myText.
var allnote = [NSManagedObject]()
var csname:Int = 1
var cspath:Int = 1
func saveNote(myText:String){
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let managedObjectContext = appDelegate.managedObjectContext!
let entity = NSEntityDescription.entityForName("Logitem", inManagedObjectContext: managedObjectContext)
let notes = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedObjectContext)
notes.setValue(myText, forKey: "itemText")
allnote.append(notes)
var error: NSError?
if managedObjectContext.save(&error) {
println("Couldn't save\(error?.userInfo)")
}
fetchnote()
}