I'm using PS to store data in my app. I think I have a misunderstanding of how PS works. If anyone could tell me how to make it so that the bill I retrieve from PS is unencrypted as opposed to the encrypted bill I end up with? Note: I originally store and unencrypted bill!
From what I can tell, it considers both bills, and both PO objects to be the same objects! When I look at their memory locations in Eclispe, both bill and both PO objects have identical memory locations! What am I missing?
Thanks!
//create an unencrypted bill
BillDAO testBill = new BillDAO();
//store it in PS
PersistentObject po = PersistentStore.getPersistentObject(4);
po.setContents(testBill);
po.forceCommit();
//encrypt the bill
testBill.encrypt();
//retrieve it from PS using a different PO
PersistentObject po2 = PersistentStore.getPersistentObject(4);
BillDAO retrievedBill = (BillDAO) po2.getContents();
//and now for some reason my retrieved bill is encrypted!
//it should be unencrypted
The two objects (in PS and in RAM) are linked, therefore changes to one reflect on the other. See Mike Kirkup response to this thread on the BB forum and in specific:
You should only ever call setContents() once. This would occur on the very first time that you are adding data. For each subsequent call you should be calling getContents() and then modifying that object directly. By modifying the object directly, you would then call commit at the end of your work where the system would properly commit your changes...
Also, you might wanna checkout his recommendations for key generation :)
Hope this helps!
Related
I'm sorry the title may mislead you, since I'm not so good at English. Let me describe my problem as below (You may skip to the TL;DR version at the bottom of this question).
In Coredata, I design a Product entity. In app, I download products from a server. It return JSON string, I defragment it then save to CoreData.
After sometimes has passed, I search a product from that server again, having some interaction with server. Now, I call the online product XProduct. This product may not exist in CoreData, and I also don't want to save it to CoreData since it may not belong to this system (it come from other warehouse, not my current warehouse).
Assume this XProduct has the same properties as Product, but not belong to CoreData, the developer from before has designed another Object, the XProduct, and copy everything (the code) from Product. Wow. The another difference between these two is, XProduct has some method to interact with server, like: - (void)updateStock:(NSInteger)qty;
Now, I want to upgrade the Product properties, I'll have to update the XProduct also. And I have to use these two separately, like:
id product = anArrayContainsProducts[indexPath.row];
if ([product isKindOfClass:[XProduct class]] {
// Some stuff with the xproduct
}
else {
// Probably the same display to the cell.
}
TL;DR
Basically, I want to create a scenario like this:
Get data from server.
Check existed in CoreData.
2 == true => add to array (also may update some data from server).
2 == false => create object (contains same structure as NSManagedObject from JSON dictionary => add to array.
The object created in step 4 will never exist in CoreData.
Questions
How can I create an NSManagedObject without having it add to NSMangedObjectContext and make sure the app would run fine?
If 1 is not encouragement, please suggest me a better approach to this. I really don't like to duplicate so many codes like that.
Update
I was thinking about inheritance (XProduct : Product) but it still make XProduct the subclass of NSManagedObject, so I don't think that is a good approach.
There are a couple of possibilities that might work.
One is just to create the managed objects but not insert them into a context. When you create a managed object, the context argument is allowed to be nil. For example, calling insertNewObjectForEntityForName(_:inManagedObjectContext:) with no context. That gives you an instance of the managed object that's not going to be saved. They have the same lifetime as any other object.
Another is to use a second Core Data stack for these objects, with an in-memory persistent store. If you use NSInMemoryStoreType when adding the persistent store (instead of NSSQLiteStoreType), you get a complete, working Core Data stack. Except that when you save changes, they only get saved in memory. It's not really persistent, since it disappears when the app exits, but aside from that it's exactly the same as any other Core Data stack.
I'd probably use the second approach, especially if these objects have any relationships, but either should work.
I'm creating two PFObjects at the same time that should reference each other's object IDs when they're saved. In the example below, the second object is supposed to save the first object's object ID in an array.
let objectForFirstClass = PFObject(className:"ClassOne")
let objectForSecondClass = PFObject(className: "ClassTwo")
objectForSecondClass.setObject([objectForFirstClass.objectId!], forKey: "classOneObjectArray")
The last line is causing the error because objectForFirstClass.objectId is nil. I'd assume this is because the object hasn't been saved yet. How can I fix this?
You want to save after creating the first object, and in the completion handler, create the second one with a reference to the first one.
You can use saveAllInBackground:block: for this.
Correct, the object id is assigned by the server when saved. I'd be tempted to write some cloud code to do what you want so you can send some details and the cloud code will create and connect the objects, then return both of them to you. You can of course do the same thing locally in your app, there's just more network comms.
You should also consider using pointers or relationships. These are better for querying, though the same save requirements apply before you can set the connections.
I need to synch up Core Data on phone with MYSQL database on server. I have gotten as far as capturing JSON feed in iOS in array. My question is, what is the best way to compare and sync up the items?
I know there are many SO posts and tutorials on syncing however the comparison is often brushed over. Once you have the JSON feed in an array and also have a managed object context, how do you compare one entry against the other?
My strategy is to give each locally saved object (record) a local id. Then when syncing occurs if the local object (record) has no server id, add it to the server table. However, I'm not sure how that works with the managed object context.
Do you iterate through the local records and compare them against server records?
Or do you iterate through the JSON array against the local managed object context?
for (NSDictionary *item in names) {
id serverid = [item objectForKey:#"serverid"];
// .... check against something in managed objectcontext
if (!items.serverid ) {
///insert on server and also provide obtained serverid to managedobjectcontext
}
}
Would appreciate any insights or suggestions.
Tim Isted addressed a similar issue in his exceptional talk at WWDC 2013.
You should watch the whole thing, because it's pretty awesome. However, the relevant part for this topic starts about 12:43 into the presentation.
I'm having some problems storing a change to a complex object. I've done a lot of digging and can't figure this out for the life of me.
From debugging, I can clearly see that the object is correct before storing, but when I retrieve the stored data, it's empty(say the increase of a stat). Specifically here is the breakdown below
StatSheet has ArrayList of Players
Player has ArrayList of Stats
ArrayList of StatSheets -> ArrayList of Players -> ArrayList of Stats
The ArrayList of Stat objects doesn't store after a change is made, no matter what I do. The arraylist of players seems to update fine which confuses me. I have tried changing the update depth to 2, 3, 4, 5, and beyond. I have also tried specifically setting cascadeOnUpdate to true. Can someone please help, I've been at this for days.
It's been a while that I looked at db4o and you didn't give a lot of details about your environment or code but maybe you can look at these solutions:
Do you use web environment? So look at this first answer:
A few questions about working with db4o
Do you use 'commit' when you store your objects? Because after storing and updating process you should commit the changes.
The array list of objects is store but db4o don't know what to do with the inner objects. The ArrayList isn't 'Activatable', so you can't retrieve yours objects.
You must put activationPurpose on every getter/setter of your stored object to enable the activation of object.
As you can't do this on native java objects, DB4O provide you some objects that have been tagged with activationPurpose on there getter/setter : like :
com.db4o.collections.ActivatableArrayList
So every java collection that should be store must be replace with it db4o equivalent (com.db4o.collections.*).
What is wrong in this code?
I was expected "titi" in person.name but I still have "toto"!
More explicitly, how to modify a record in a function?
init1()->
S=#person{name="toto"}, %record creation and field setting
fct(S),
io:format("~s~n",[S#person.name]).
fct(R)->
R#person{name="titi"}. %record updating
You need to get a result of fct():
init1()->
S=#person{name="toto"}, %record creation and field setting
S2 = fct(S), % Get updated record
io:format("~s~n",[S2#person.name]).
fct(R)->
R#person{name="titi"}. %record updating
Bertaud, I think you are getting ahead of yourself a bit. You really need to understand the basics of immutability before you write any more code. (i.e. "variables" do not vary : you can only assign a value to them once.) I suggest you read the free online guide "Learn You Some Erlang For Great Good", at http://learnyousomeerlang.com/. The section that covers the basics of variables is http://learnyousomeerlang.com/starting-out-for-real#invariable-variables.
It is impossible to stress too much that all data in Erlang is immutable. So to do something like in your original question you need to modify it like #hdima did. The record is not updated but rewritten. In the same way there is no global data in Erlang, all data belongs to a process. This is even true of ETS tables as they basically behave like a process, albeit a built-in one without explicit communication.
So if you use the process dictionary or an ETS table the data itself can never be updated, only the dictionary/table. This means that to modify some data in the dictionary/table you basically have to:
"Read" the data
Update the data making new data
"Write" the new back into the dictionary/table
Without writing the new data back into the dictionary/table it will be lost, as your new data was.
Within fct(), you're not mutating the record, but you're returning a new value for the record, which needs to be used further. If you're calling fct(S), without handling the return value, then you'll lose that new value ("titi").