I have a NSArrayController subclass which sets an instance variable of a newly inserted object and prevents the user to remove it if this variable is zero.
I'd like to do this inside an entity subclass. Setting the variable is possible in the awakeFromInsert method. Is there a way to prevent the deletion, a sort of:
if (self.testVariable == 0) return; ?
I didn't find it, but maybe I missed something.
Implement this in your NSManagedObject:
- (BOOL)validateForDelete:(NSError **)error
based on a few tests, i believe the validateForDelete will not work to prevent deletion as desired.
validateForDelete is used to perform added validation prior to delete. essentially, the method name is misleading. Just like for example, for
moreover, prepareForDelete is called prior and will delete any Cascade relationships and mark null any Nullify ones. hence, those have to be 'backed out.' or alter your data model to only permit Deny that will leave those relationships alone in prepareForDelete. which is applying a stiff backhand to your business model and logic.
further, a Deny relationship is 'denied' when the user saves the data -- which might be too late for the user to undo and rectify the situation.
i believe the best option is to unactive the Remove Button that is bound to the canRemove method in the Controller.
Some solid opinions
Some possible solutions at SO
Related
I am a bit confused how to use the component <sw-entity-multi-select>. I understand that the difference between this component and the <sw-entity-multi-id-select> is that the first one returns the entities and the latter one returns just the id of the selected entities. But from the structure and the props they are totally different.
I am confused, because I mainly use the component as this:
<sw-entity-multi-select
entityName="language"
:entity-collection="languages"
:criteria="salesChannelLanguageCriteria"
:label="Language"
#change="selectLanguage"
>
</sw-entity-multi-select>
I could remove the entityName here, as the name is retrieved from the collection as well. But when I dig into the core, I see that inside selectLanguage I should do this:
selectLanguage(languages) {
this.languageIds = languages.getIds();
this.languages = languages;
}
I now understand that languageIds are kind of the v-model that determine, which entities should be selected in the component. Is this true? Why do I have to set the this.languages here again then? To me it's kind of magic if languageIds have this role here, because it's not referenced anywhere on the component. How does it work and how do I tell the component which items are selected - is using languageIds the correct way?
I now understand that languageIds are kind of the v-model that determine, which entities should be selected in the component. Is this true?
No. This example probably just extracts the IDs for some other use, e.g. for adding associations of language to another entity. One could arguably that if this is the only purpose of the selection sw-entity-multi-id-select might be the better component to use.
Why do I have to set the this.languages here again then?
Because you want to store the updated entity collection to persist the selection. Whatever is selected within the multi select is derived from that collection. So, let's say, initially you start out with an empty entity collection. You select some entities and the change is emitted with the updated collection containing the selected entities. Given we have :entity-collection="languages" we then want this.languages to be this updated collection, so the selection persists. So we kinda complete a loop here.
On another note, you could also use the collection with v-model="languages". In that case any additions or removals within the selection would be applied reactively to the collection and you wouldn't need to set this.languages after each change and you could also remove :entity-collection="languages". So basically, which of these approaches you use depends on whether you want your changes applied reactively or not.
I have an non-persistent attribute (SITEID) on my WOCHANGE object that originates from the parent object, WORKORDER. For some particular reason, this attribute has a few problems that I've never really seen with other attributes before.
Based on various configurations I have tried in an attempt to remedy the issue, here are the main issues:
It doesn't trigger the WOCHANGE to save when changed.
In addition to the value not being saved, I can change the value on one record, go to another and the value persists on the different record.
The field is readonly unless I define it to have an inputmode of DEFAULT. This is odd to me, because not defining inputmode usually implies default behavior (NOT readonly).
Here are the definitions for the SITEID attribute on both the WORKORDER
and WOCHANGE objects.
SITEID also uses a TABLE domain belonging to the SITE table.
Are there any attribute rules being applied from other sources that I should be checking?
That workorder field class on there may not be desired and may be messing with things, like setting the field to read-only. Site Id is commonly a read-only field, especially when the record is no longer a new record. Because of that, the logic to make that field read-only could be buried deeper in the Maximo business logic than just that field class. You are working with a field that has a lot of special meaning in Maximo, you are likely going to stumble into many built-in business rules.
Since non-persistent fields are not saved in the database (they are in memory fields only), I don't believe they trigger the flag for a record to be saved. What would be saved? Nothing in the database (a save) is to be changed yet.
Your screenshot however shows the field as persistent. Is WOCHANGE a view? I can't recall and no longer have the resources to check.
is there a simple and efficient/fast way to query a managedobjectcontext to get an array of all the managedobjects in the context that have not yet been added to the persistent store?
i ask this because i would like to be able to save nsmanagedobjects that have been added to the MOC only if they conform to certain criteria. basically i want to be able to do this so that if some unexpected event happened before my managed object attributes were properly populated, i can catch this fact and purge the object(s) before saving the context. given the complexity of the navigation possible in the app, i'd like to have a look at the data to be sure they are good before i save.
i suppose i could also do this with some kind of validation rule and a flag field that doesn't get set until i am sure the user has added all the data to the record, but i don't yet know how to implement this...
any help much appreciated.
The insertedObjects method of NSManagedObjectContext
returns the set of objects that have been inserted into the context but not yet saved in a persistent store.
This question covncerns my lack of understanding of how to use the core data undo manager and how to restore a NSManagedObject to its state before editing was done.
I am just learning my way around Core Data. I have my NSManagedObject classes set up with their dynamic accessors. I perform a fetch that returns several NSManagedObject entity results. Content from each of these entity results (first name, last name) get put into a table view, and then the user picks one out of the table for detailed view and then editing.
The detail view controller receives a pointer to the selected NSManagedObject entity. As the user edits the fields, the corresponding property value in the NSManagedObject entity is updated. This seemed like the cleanest way to manage these changes.
Now, rather than committing the changes using save, I want to provide a cancel-editing feature that rolls back to what is in the data base for that entity. I really only want to restore the one entity and not perform the entire refetch.
I tried rollback and I tried NSUndoManager (with beginUndoGrouping and endUndoGrouping), and that is not working. I don't think I understand what rollback is really supposed to do.
But in any case, I still want to restore the property values in just that single entity (taking the lazy approach to only fetch what is needed, which is the one entity) so that my detail view controller can refill its view with the correct information. Right now it is using the NSManagedObject entity values, which contain the edited values, which were cancelled.
I suppose I could just start the edit process by creating a copy of the NSManagedObject. If the cancel-editing button is pressed, I could copy it back into the original. (I might even be able to just replace the original with the copy by moving the pointer. But since the pointer has actually been passed through several objects, I'm not sure how to manage the retain number on the copy.)
Does anyone have any other suggestions?
Thanks
Using rollback should accomplish what you want and I'm not sure what it doesn't. It is probably an implementation detail error.
You can find the specific managed object/s that were updated but not yet saved by calling the context's updatedObjects.
I have core data app with an entity OBSERVATION that has as one of its attributes DEALNAME.
I want to reference through Interface Builder or by making custom modifications to an NSArrayController a list of unique sorted dealnames so that I can use them in a pop-up.
I have attempted to use #distinctUnionOfSets (and #distinctUnionOfArrays) but am unable to locate the proper key sequence.
I can sort the ArrayController by providing a sort descriptor, but do not know how to eliminate duplicates.
Are the #distinct... keys the right methodology? It would seem to provide the easiest way to optimize the use of IB.
Is there a predicate form for removing duplicates?
Or do I need to use my custom controller to extract an NSSet of the specific dealnames, put them back in an array and sort it and reference the custom array from IB?
Any help would be appreciated. I am astounded that other have not tried to create a sorted-unique pop-up in tableviews.
You need to take a look at -[NSFetchRequest returnsDistinctResults]. That is the level you need to be handling the uniquing of data.
Although I do not have a definitive answer for you, I think there are two ways you can go about it.
The way you already started. You need to bind the contents array of the PopUp button, not just against the arrayController.arrangedObjects, but continue on the path and somehow filter only objects with distinct "DealName"s. This means - the arrayController presents ALL the entities (and may sort them for you) but the PopUp button will have its contents filter via some sophisticated binding to the array controller.
Make your filtering at the ArrayController level (as suggested in another answer here). Here it depends how you set up the array controller. If It is set up to use an "Entity" (vs. "Class") which means the array controller will fetch CoreData entities directly - you can modify its "Fetch" to only bring a subset of the "OBSERVATION" entities with distinct values of "DEALNAME". I don't know how to control WHICH entities are filtered out in this case. Otherwise, you can setup the arrayController to work with "Class" objects, and then you can fetch the entities yourself (in code) and populate the arrayController programmatically, with just the entities you like.
In the second option, the Popup button should be bound normally to the arrayController's arrangedObjects.