Odd behaviour of insertNewObjectForEntityForName leading to NSInternalInconsistencyException - core-data

I have a rather odd case of getting a core data error whilst experimenting with Swift. I am not sure whether it comes from Swift (beta error?) or whether it is me. However, here is the setup for my test cases (in VTModelTests.swift).
var bundle = NSBundle(forClass: VTModelTests.self)
var url = bundle.URLForResource("VTDocument", withExtension:"momd")
appleModel = NSManagedObjectModel(contentsOfURL: url)
assert (appleModel != nil)
var coord = NSPersistentStoreCoordinator(managedObjectModel: appleModel);
var store = coord.addPersistentStoreWithType(NSInMemoryStoreType,configuration:nil,URL:nil,options:nil,error:nil);
assert (store != nil)
ctx = NSManagedObjectContext();
ctx!.persistentStoreCoordinator=coord
ctx!.retainsRegisteredObjects=true;
var drwName = "Drawing"
var descs = ctx!.persistentStoreCoordinator.managedObjectModel.entitiesByName
for e : AnyObject in descs.allKeys{
assert (descs.objectForKey(e).name == e as String )
if (e as String == drwName) {
NSLog("yeah")
}
}
model = NSEntityDescription.insertNewObjectForEntityForName(drwName,inManagedObjectContext: ctx) as Drawing
My error message looks like this:
2014-06-22 22:12:25.584 xctest[63792:303] yeah
<unknown>:0: error: -[_TtC12VTModelTests12BaseTypeTest testTreeStructure] : failed: caught "NSInternalInconsistencyException", "+entityForName: could not locate an entity named 'Drawing' in this model."
In short, I can "prove" that the entity name is there (the 'yeah' in the log), but core data is showing the issue that the name would not be in the model. Previous versions of the loop printed out the entities and that looked good. I don't have any second versions, and a new changed name ('Model' is now called 'Drawing') is correctly shown in the model data when all entities are printed. The compiled model is in the resulting bundle.
Can anybody explain? Or do I have to wait for the next beta release of Xcode 6? What else did I overlook? Many thanks in advance!

I can confirm the issue. Not an answer but the way around I use is to split insertNewObjectForEntityForName into:
let entity = NSEntityDescription.entityForName("Photo", inManagedObjectContext:context)
let photo = Photo(entity:entity, insertIntoManagedObjectContext:context)

Related

OMNotebook Error: Class dev not found in scope (looking for a function or record)

I have modified the van der Pol example from DrModelica with the following changes:
model FPStirling "Free Piston Stirling engine model"
Real x(start = 1,fixed = true);
Real v(start = 1,fixed = true);
Real T(start = 1,fixed = true);
equation
der(x) = v;
dev(v) = T/x-1;
dev(T) = 1 - x;
end FPStirling;
It evaluates and returns: {FPStirling}
Then I run: simulate(FPStirling, startTime=0, stopTime=25 )
But I get the output:
record SimulationResult
resultFile = "",
messages = "Failed to build model: FPStirling"
end SimulationResult;
OMC-ERROR:
"[7:3-7:17] Error: Class dev not found in scope FPStirling (looking for a function or record).
Error: Error occurred while flattening model FPStirling
"
Could it be a path problem?
Do you really have a function dev defined somewhere? Or maybe its a typo for der.
Adeel.

How is the context treated?

I have a weird behaviour on Core Data with my App. I have an App where user can create their own words entries with translation. When deleting all my Core Data I checked the nb of item and it was 0. When adding later 4 items the nb of items was 5?? I found the issue after a lot of tests and it seems not consistent for me: the issue was with this code:
fileprivate func duplicateCheckAndImport() {
// Check for duplicates
do {
self.words = try context.fetch(Word.fetchRequest()) // grab all Words
let nbOfWords = words!.count
print ("The nb of words in duplicateCheck...: \(nbOfWords ?? 0)")
}
catch {
// error message to add
}
let newWord = Word(context: self.context)
do {
self.words = try context.fetch(Word.fetchRequest()) // grab all Words
let nbOfWords = words!.count
print ("The nb of words in duplicateCheck...: \(nbOfWords ?? 0)")
}
catch {
// error message to add
}
the result of the 2 prints is 0 for the first grab and 1 for the 2nd grab which means that just this line of code -> let newWord = Word(context: self.context) adds an entry in Core Data but my purpose was just to take the context add words later on like this:
let newWord = Word(context: self.context)
newWord.name = item.name.trimmingCharacters(in: .whitespaces)
newWord.definition = item.definition.trimmingCharacters(in: .whitespaces)
Can someone explain me?
The line of code you mention
let newWord = Word(context: self.context)
...creates a new instance. That's what Word(context: self.context) does-- it says, create a new instance of Word using the context that you pass in.
From the code you provide, it's hard to tell exactly what you're trying to do that would not create a new instance. Your variable is called newWord, which suggests that you do mean to create a new Word, and that's what's happening.
Update: If you don't want the new instance, you can delete it just like any other managed object. So if you don't want newWord, you can
context.delete(newWord)
And then save changes. There are other ways to do this, but this is the simplest.

Variable value got changed unexpectedly in nodeJS

let fulfillmentMessages = []
let multipleRides = formats.text_message
multipleRides.payload.data.text = predefined_responses.intent_report_lost_credential_confirmation_yes.case_ids.response
console.log("Multiple rides Message")
console.log(JSON.stringify(multipleRides))
let noRides = formats.text_message;
noRides.payload.data.text = predefined_responses.intent_report_lost_credential_confirmation_yes_2.response;
console.log("Multiple rides Message after")
console.log(JSON.stringify(multipleRides))
fulfillmentMessages.push(multipleRides)
fulfillmentMessages.push(noRides)
console.log("Going to send these messages")
console.log(JSON.stringify(fulfillmentMessages))
After this code executes multipleRides and noRides have same values in it and array contains the same value twice. Can someone please explain what I am doing wrong here?
The main problem here is that both variables, multipleRides and noRides, are referencing the same object, formats.text_message and thus, multipleRides.payload.data is the same object as noRides.payload.data. For that reason, the value stored in multipleRides.payload.data.text is overwritten by the assignment to noRides.payload.data.text. In JavaScript objects are copied by reference and not by value. You will need to do a deep clone of formats.text_message. A shallow copy wont be enough, due to how deep that text is.
This article will give you some hints for doing a deep clone. My advice is to use lodash, the code will be:
const _ = require('lodash')
let fulfillmentMessages = []
let multipleRides = _.cloneDeep(formats.text_message)
multipleRides.payload.data.text = predefined_responses.intent_report_lost_credential_confirmation_yes.case_ids.response
console.log("Multiple rides Message")
console.log(JSON.stringify(multipleRides))
let noRides = _.cloneDeep(formats.text_message);
noRides.payload.data.text = predefined_responses.intent_report_lost_credential_confirmation_yes_2.response;
console.log("Multiple rides Message after")
console.log(JSON.stringify(multipleRides))
fulfillmentMessages.push(multipleRides)
fulfillmentMessages.push(noRides)
console.log("Going to send these messages")
console.log(JSON.stringify(fulfillmentMessages))
You could also use JSON.parse(JSON.stringify(formats.text_message))
I hope this helps!

QTreeWidgetItem does not get Checked

I am trying to Check Tree items from a function after the Tree is initialized. Check marks never appear. I'm not sure if I need to 'refresh' the Tree or that I am not interacting with the right object.
I've read about this widget a lot and I see the same question more or less on several websites but the answers are 8+ years old, two pages of code or I just don't understand them.
What am I doing wrong here? Why are there no check marks showing up in the tree when I call checkActiveTreeItems()?
After a REST call, I want to update the checked items in the tree. This seems to be ok but the items never get checked.
def checkActiveTreeItems(self):
for label in self.transactie['transactie']['labels']:
test = QtWidgets.QTreeWidgetItem([label])
test.setCheckState(0, QtCore.Qt.Checked)
This is the function that creates the tree, I do not call it again after setting the QTreeWidgetItem to Checked in the function above.
def initTree(self):
print("initTree")
self.treeWidget = QtWidgets.QTreeWidget(self.gridLayoutWidget)
self.treeWidget.setSelectionMode(QtWidgets.QAbstractItemView.ContiguousSelection)
self.treeWidget.setObjectName("treeWidget")
inkomstenstructuur = requests.get(url="http://localhost:32769/_db/piekenpijp/incoming/inkomstenstructuur")
iscontent = json.loads(inkomstenstructuur.content)
self.inkomsten = iscontent
inkomstentree = QtWidgets.QTreeWidgetItem(["Inkomsten"])
for groep in iscontent:
child = QtWidgets.QTreeWidgetItem([groep['groep']])
inkomstentree.addChild(child)
for categorie in groep['categorien']:
child2 = QtWidgets.QTreeWidgetItem([categorie])
child2.setCheckState(0, QtCore.Qt.Unchecked)
child.addChild(child2)
uitgavenstructuur = requests.get(url="http://localhost:32769/_db/piekenpijp/incoming/uitgavenstructuur")
uscontent = json.loads(uitgavenstructuur.content)
self.uitgaven = uscontent
uitgaventree = QtWidgets.QTreeWidgetItem(["Uitgaven"])
for groep in uscontent:
child = QtWidgets.QTreeWidgetItem([groep['groep']])
uitgaventree.addChild(child)
for categorie in groep['categorien']:
child2 = QtWidgets.QTreeWidgetItem([categorie])
child2.setCheckState(0, QtCore.Qt.Unchecked)
child.addChild(child2)
self.treeWidget.itemChanged.connect(self.vinkje)
self.treeWidget.resize(500, 200)
self.treeWidget.setColumnCount(1)
self.treeWidget.setHeaderLabels(["Categorie"])
self.treeWidget.addTopLevelItem(inkomstentree)
self.treeWidget.addTopLevelItem(uitgaventree)
self.treeWidget.expandItem(uitgaventree)
self.gridLayout.addWidget(self.treeWidget, 0, 2, 1, 1)
Your current method creates a new item, sets its check-state, and then throws it away without using it. Instead, you need to find the items in the tree that you have already created:
def checkActiveTreeItems(self):
for label in self.transactie['transactie']['labels']:
for item in self.treeWidget.findItems(label, Qt.MatchExactly):
item.setCheckState(0, QtCore.Qt.Checked)

The Button.connect syntax in Genie

I want to apply a certain behaviour to a label. When a lateral button is clicked, the corresponding label should rotate 90 degrees. It can be easily done in vala, but I can't discover the particular syntax on genie.
The vala code I am trying to reproduce comes from elementary OS getting started guide:
hello_button.clicked.connect(() =>
{
hello_label.label = "Hello World!";
hello_button.sensitive = false;
});
rotate_button.clicked.connect(() =>
{
rotate_label.angle = 90;
rotate_label.label = "Verbal";
rotate_button.sensitive = false;
});
I actually managed to reproduce almost entirely the code in Genie, for the exception of the rotation. Here is how far I got:
/* ANOTHER GTK EXPERIMENT WITH GENIE BASED ON ELEMENTARY INTRODUCTORY PAGE
** compile with valac --pkg gtk+03.0 layoutgtkexample.gs */
[indent=4]
uses Gtk
init
Gtk.init (ref args)
var window = new Gtk.Window()
window.title = "Hello World!"
window.set_border_width(12)
var layout = new Gtk.Grid ()
layout.column_spacing = 6
layout.row_spacing = 6
var hello_button = new Gtk.Button.with_label("Say Hello")
var hello_label = new Gtk.Label("Hello")
var rotate_button = new Gtk.Button.with_label ("Rotate")
var rotate_label = new Gtk.Label("Horizontal")
// add first row of widgets
layout.attach (hello_button, 0, 0, 1,1)
layout.attach_next_to (hello_label, hello_button, PositionType.RIGHT, 1, 1)
// add second row of widgets
layout.attach(rotate_button, 0,1,1,1)
layout.attach_next_to(rotate_label, rotate_button, PositionType.RIGHT, 1, 1)
window.add(layout)
hello_button.clicked.connect(hello_pushed)
rotate_button.clicked.connect(rotate_pushed)
window.destroy.connect(Gtk.main_quit)
window.show_all ()
Gtk.main ()
def hello_pushed (btn:Button)
btn.label = "Hello World!"
btn.sensitive = false
def rotate_pushed (btn:Button)
btn.label = "Vertical"
//btn.angle = 90
btn.sensitive = false
The problem is to do with where identifiers are valid and is known as "scope".
The Vala example makes use of an anonymous function, also called a lambda expression in Vala. An anonymous function can be a "closure", when the variables in the scope that defines the anonymous function are also available within the anonymous function. This is useful because the callback occurs after the original block of code has been run, but the variables are still available within the callback. So in the Vala example, where both the button and label are defined in the enclosing scope, the button and label are also available in the callback anonymous function.
Unfortunately Genie isn't able to parse anonymous functions as function arguments, in this case within the connect() call. Although some work has been done on this in 2015. So you have rightly used a function name instead. The problem is the callback only passes the button as an argument and not the adjacent label. So to make the label available within the callback function we could use a class:
/* ANOTHER GTK EXPERIMENT WITH GENIE BASED ON ELEMENTARY INTRODUCTORY PAGE
** compile with valac --pkg gtk+-3.0 layoutgtkexample.gs */
[indent=4]
uses Gtk
init
Gtk.init (ref args)
new RotatingButtonWindow( "Hello World!" )
Gtk.main ()
class RotatingButtonWindow:Window
_hello_label:Label
_rotate_label:Label
construct( window_title:string )
title = window_title
set_border_width(12)
var layout = new Grid ()
layout.column_spacing = 6
layout.row_spacing = 6
// add 'hello' row of widgets
var hello_button = new Button.with_label("Say Hello")
_hello_label = new Label("Hello")
layout.attach (hello_button, 0, 0, 1,1)
layout.attach_next_to (_hello_label, hello_button, PositionType.RIGHT, 1, 1)
// add 'rotate' row of widgets
var rotate_button = new Button.with_label ("Rotate")
_rotate_label = new Label("Horizontal")
layout.attach(rotate_button, 0,1,1,1)
layout.attach_next_to(_rotate_label, rotate_button, PositionType.RIGHT, 1, 1)
add(layout)
hello_button.clicked.connect(hello_pushed)
rotate_button.clicked.connect(rotate_pushed)
destroy.connect(Gtk.main_quit)
show_all ()
def hello_pushed (btn:Button)
_hello_label.label = "Hello World!"
btn.sensitive = false
def rotate_pushed (btn:Button)
_rotate_label.label = "Vertical"
_rotate_label.angle = 90
btn.sensitive = false
A few notes:
By placing the definitions of the _hello_label and _rotate_label within the scope of the class they become available to all the functions defined in the class. Definitions like this are often called "fields". The underscore means they are not available outside the class, so in the example you cannot access them from init
construct() is called when the object is created, in the example the line new RotatingButtonWindow( "Hello World!" ) instantiates the object. If you repeat the line you will have two separate windows, that is two instances of the RotatingButtonWindow data type
You will notice that the RotatingButtonWindow type is also defined as a Window type. This means it is adding more detail to the Gtk.Window class. This is why title and set_border_width() can be used within the new class. They have been "inherited" from the parent Gtk.Window class
By using the Gtk namespace with uses Gtk we don't need to prefix everything with Gtk
As your Gtk application gets more complex you probably want to look at GtkBuilder. That allows windows and widgets to be laid out in an external file. Then use GResource to build the file into the binary of your application so there is no need to distribute the UI file separately.

Resources