How is the context treated? - core-data

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.

Related

Application skipping frames while accessing sound files

I have this for statement triggered by a button that iterates through a MutableList of strings.
For each string it completes a file path and checks if that file path is valid. If it is, it's attempted to be sent to the mediaPlayer via a function to be played as a sound file. It should play the sound for all files it can find with a pause at certain stated points (2,5,7).
Unfortunately, when I test it out, the button animation comes in delayed, followed by a Logcat info of 363 skipped frames, doing too much work on the application's main thread.
I tried to consecutively commenting out certain lines of the function but was not able to identify the computationally intensive part of it. Could anybody tell me where the issue lies or how I could improve the function?
Here's the function itself:
btnStartReadingAloud.setOnClickListener {binding.root.context
Toast.makeText(binding.root.context, "Reading the exercise out loud", Toast.LENGTH_SHORT).show()
println("Reading the exercise out loud")
for (i in 0 until newExercise.lastIndex){
val currentElement : Pair<String,Array<Any>> = newExercise[i]
val currentDesignatedSoundFile : String = "R.id.trampolin_ansage_malte_"+replaceSpecialChars(currentElement.first)
val path : Uri = Uri.parse(currentDesignatedSoundFile)
val file = File(currentDesignatedSoundFile)
if (doesFileExist(file)){
System.out.println("Playing file named$file")
playSound(path)
Toast.makeText(binding.root.context, "Playing sound for: %path", Toast.LENGTH_SHORT).show()
}
val pauseTimes = listOf<Int>(2,5,7)
if (i in pauseTimes){
Thread.sleep(2000)
}
}
Here is the dedicated function to play the sound
fun playSound(soundFile : Uri) {
if (mMediaPlayer == null) {
mMediaPlayer = MediaPlayer.create(requireContext(), soundFile)
mMediaPlayer!!.isLooping = false
mMediaPlayer!!.start()
} else mMediaPlayer!!.start()
}
Any hint is appreciated, thanks already for reading & brainstorming :)

Censoring words in lua

Im currently making a discord censor bot for my friend, and I was wondering if any advanced scripters could help me, or if theres an easier way to complete my code.
local BadWords = {
['poop']=true,
}
client:on('messageCreate', function(msg)
Msg = msg.content
local msgs = string.split(Msg,' ')
for i,v in pairs(msgs) do
if BadWords[v:lower()] then
msg:reply({
embed = {
fields = {
{name = "Bad Word",value=v,inline = true},
},
color = discordia.Color.fromRGB(114, 137, 218).value,
--footer = os.time(),
}
})
--msg:reply(('Blacklisted word: %s'):format(v))
end
end
--[[table.foreach(msgs,function(i,v)
if BadWords[i] or BadWords[v] then
msg:reply(('Blacklisted word: %s'):format(v))
end
end)--]]
end)
client:run(Settings.Token)
Theres nothing wrong with it, nor is it complete but my idea was to split, or concatenate all the words they send respectively, mutate into all versions of the word (i.e. farm, f4rm, type shit) and then checking the BadWord list.
Mostly what I was wondering was if theres a more efficient way to do this, or if I j gotta do what I gotta do

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)

Odd behaviour of insertNewObjectForEntityForName leading to NSInternalInconsistencyException

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)

Resources