Cannot use removeObjectForKey in Parse (using Back4App on Objc) - objective-c

I'm using Back4App's service to host Parse server and I can't seem to successfully remove a field from a row. The field in question is a pointer to another object, and calling removeObjectForKey followed by a save does not work. Other updates work in the same batch, and I have seen that 4 times out the 36 that I have tried, it did successfully delete the object.
[self.myProfile removeObjectForKey:#"partnership"];
[self.myProfile saveEventually:^(BOOL succeeded, NSError * _Nullable error) {
NSLog(#"success %d", succeeded); //always returns true
}];
Is this a known problem with Back4App? Or Parse itself? I tried the same code in swift and it worked.
Any ideas?

When you need to run a callback, to confirm when is deleted, is recommended the deleteInBackgroundWithBlock: or deleteInBackgroundWithTarget:selector: methods. You can delete a single field from an object with the removeObjectForKey method:
// After this, the playerName field will be empty
[classScore removeObjectForKey:#"customName"];
// Saves the field deletion to the Parse Cloud
[classScore saveInBackground];
About the saveEventually, most save functions execute immediately, and inform your app when the save is complete. If you don’t need to know when the save has finished, you can use saveEventually instead. The advantage is that if the user currently doesn’t have a network connection.
Content from Parse =D

Related

After adding a lot of info into Realm one of my items do not work

I've been facing a very strange problem in Realm which doesn't occur every time , but it's been really annoying.
I'm saving a lot of information offline which come from a Webservice using realm. I don't get any exception while saving all these information.
Later I'm able to get all these objects by accessing them through MyObject.allObjects().
These objects contains a property which is an UUID, which I use to download the file related to this object and save it locally, after I finish downloading the file, I update my Realm Object with the path of the file, but some times when I do it:
let pred = NSPredicate(format: "UUID = %#", fileId)
print("This is the select \(pred.predicateFormat)")
let results = IssueFile.objects(with: pred) as! RLMResults<IssueFile>
The variable results is empty, but if I check Realm Database via Realm Browser, I can find the item I'm looking for.
So my question is: why some times Realm can't find the object I'm selecting? As I'm saving a lot of information, is there something I should change in the Realm Configuration?
I've already set the UUID as primary key of the table:
+ (NSString *)primaryKey {
return #"UUID";
}
Thanks,

Why does my core data object not show up using fetch requests between related objects that were created in the same session?

This is a really weird situation which I have been battling to resolve over the last couple of days.
I have a Card entity with a To-Many relationship on a Transaction entity. I am also using Magical Record to remove the boilerplate code around managing my data store.
My problem occurs in the following order:
Create a Card object
Then create a Transaction object in another view
When I inspect the transaction count with [card.transactions count] I get 1 as the size
However, if I perform a fetch request using the same context the transaction is not there. My predicate looks like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"card == %# && deleted == 0", card];
So logic says that I am perhaps not saving the context after saving the transaction, but the weird thing is that if I quit the app and then rerun it, the transaction is there. Steps 1-4 work perfectly too if I create the card, quit the app and then run the app and add a transaction. Then my save transaction code works fine.
So my question is, why aren't my objects showing up using fetch requests on a newly created parent object, where "newly created" means that it was created in the same session as the child object.
My code for creating the card looks like this:
GYCard *card = [GYCard MR_createInContext:[NSManagedObjectContext MR_defaultContext]];
[[NSManagedObjectContext MR_defaultContext] MR_save];
Then when I save the transaction my code looks like this:
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_defaultContext];
NSNumber *transactionAmount = [self.numberFormatter numberFromString:self.transactionAmountLabel.text];
GYTransaction *transaction = [GYTransaction MR_createInContext:localContext];
transaction.amount = transactionAmount;
transaction.deleted = [NSNumber numberWithBool:NO];
transaction.card = self.card;
[localContext MR_save];
The code that is not working is this:
+ (int) countTransactions:(GYCard *) card {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"card == %# && deleted == 0", card];
return [GYTransaction MR_countOfEntitiesWithPredicate:predicate inContext:[NSManagedObjectContext MR_defaultContext]];
}
The countTransactions always returns 0 if the card was created in the same session. But it works 100% if I quit the app and relaunch. It also works for adding any new transactions to the card after quitting and relaunching the app.
This appears to be a Magical Record issue. I was using the 2.0 beta branch of Magical Record and after reverting to the tagged version:1.8.3 the issue disappears. So 2.0 seems to be the culprit. It would still be interesting to know however, why version 2.0 is causing this problem.
I would strongly advise anybody who is using Magical Record to avoid the 2.0 branch until it comes out of beta.
Update: After further investigation what the 2.0 beta of Magical Record was doing was generating 2 save notifications for 1 save, this led to my app inadvertently have 2 versions of the card. This resulted in causing the transaction that I was logging to be logged on the first card but the second card obviously did not have a transaction on it. My fetch request was then fetching the second card and returning zero transactions. Quitting and restarting the app then made my app load the correct transaction from the data store and thus worked as expected.
This could be related to the includesPendingChanges property on NSFetchRequest. However the default for this is YES which means any unsaved changes should be included in any queries.
I'm not sure what the MR_ methods are doing under the hood, but the setIncludesPendingChanges: documentation states:
Special Considerations
A value of YES is not supported in conjunction with the result type
NSDictionaryResultType, including calculation of aggregate results
(such as max and min). For dictionaries, the array returned from the
fetch reflects the current state in the persistent store, and does not
take into account any pending changes, insertions, or deletions in the
context.
So I would make sure the MR_countOfEntitiesWithPredicate method is not doing anything funky. Maybe try calling the standard - (NSUInteger)countForFetchRequest:(NSFetchRequest *)request error: (NSError **)error method on your context and see what that returns.

RestKit Object Mapping: difficulty using setObjectMapping:forResourcePathPattern:withFetchRequestBlock

My setup
The following all works fine:
RKManagedObjectMapping* chanMapping = [RKManagedObjectMapping mappingForClass:[Channel class] inManagedObjectStore:objectStore];
chanMapping.primaryKeyAttribute = #"chanId";
[chanMapping mapKeyPathsToAttributes:
#"id",#"chanId",
#"name", #"chanName",
nil];
[objectManager.mappingProvider setMapping:chanMapping forKeyPath:#"Channels.channel"];
I can call
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:#"/channels" delegate:self];
and I get my channel's from the server and they're stored locally by Core Data. Perfect.
The issue
However, I now wan't to have RestKit automatically delete Channels from the Core Data store that have been removed from the server the next time a GET is performed. I understand this is supported by adding the following:
[objectManager.mappingProvider setObjectMapping:chanMapping forResourcePathPattern:#"/channels" withFetchRequestBlock:^ (NSString *resourcePath) {
return [Channel fetchRequest];
}];
However with this all the Channels get deleted whenever there is anything new on the server.
Things I've tried [UPDATED]
I've debugged using the steps in the answer below. It looks as though the mapping isn't working / is not being found (i.e. I haven't properly associated the mapping with the resource path).
In deleteCachedObjectsMissingFromResult the cachedObjects array looks good, has all the objects that should be there from the last time but the results array is empty which obviously results in [results containsObject:object] always being NO and all the objects being deleted.
Do I need to change something to do with the resource path mapping?
I looked at your updated description. Give this a try:
Switch back to the setObjectMapping:forResourcePathPattern:withFetchRequestBlock
Set the rootKeyPath on the object mapping you register to Channels.channel
Then give it another try. There is some API work in progress to provide URL and keyPath based mapping configuration in a single line, but its not merged to development yet.
Two things to check out to determine why you are seeing the described behavior:
Open up RKManagedObjectLoader and put a breakpoint within isResponseMappable. This method checks if the response was loaded from the cache and performs a load of the objects using the objects returned by the managed object cache if it returns YES. This is probably where you are seeing the return of the cached objects from.
As for the deletion of cached objects, put a breakpoint within deleteCachedObjectsMissingFromResult and see what is going on in there (if you are even making it into the routine).
The scenario to expect automatic pruning would be:
GET /channels returns 2xx status code with new payload
RKManagedObjectLoader performs pruning

How can I send different SMS' to multiple recipients in a loop

I'm using Symbian C++ to create my code, I'm using S60 5th Ed SDK
I want to know how to send different messages - Their body text not the same - to multiple recipients in a for-loop ?
I've tried the example below, but when I try to use it in a loop it crashes due to ActiveObjects properties, as I should wait to AO to finish before calling it again.
Sending_SMS_in_S60_3rd_Edition_MTM
Below is example of what I need to do:
SendSMSL(); // **I call this function once to start the process**
// **iRecepients is a CDesCArray contains phone numbers**
// ** iSMSBody is a CDesCArray contains each contact SMS body text**
void CSMS::SendSMSL()
{
if(iRecepients->Count() >= 1)
{
TInt x = iRecepients->Count()-1;
TInt y = iSMSBody->Count()-1;
// **If the sms validating and scheduling succeeded then delete last item from both arrays**
if(iSMSHandler->SendL((*iRecepients)[x],(*iSMSBody)[y])
{
iRecepients->Delete(x);
iSMSBody->Delete(y);
}
}
}
Now, in the code above I call iSMSHandler->SendL() which send sms using AO, and in iSMSHandler object RunL() function, I call back the function above CSMS::SendSMSL() , which in turn checks if there is still anymore iRecepients elements and then call again iSMSHandler->SendL() AO , and keeps this way till no more iRecepients.
Looking forward to hear your feedback on the modification above.
Many thanks in advance.
The link you posted doesn't work for me so I can't see the rest of the code.
Assuming that iSmsHandler is a class that uses active objects to send SMS messages,
I see several issues with your loop.
1) You need to wait for the first asynchronous SendL to complete before you can issue the next SendL
2) The buf variable can not go out of scope until the SendL completes. (This may be the reason for your crash)
I suggest that you keep the textbuffer somewhere else, like together with iSmsHandler, and then code the active object that is called when SendL completes to issue the next SendL.
All of this is guesses since I have no idea what class iSmsHandler is....

How to Implement callback for file downloading?

I wrote a script that downloads file from web using file URL. I have an ActiveXObject of following type.
var objHTTP = new ActiveXObject("MSXML2.XMLHTTP");
objHTTP.open("GET", strFileURL, false);
It works perfect for small size file says, file size less than 100MB. But when I try to download file with size greater than 100MB my script hanged. Then I tried,
objHTTP.open("GET", strFileURL, true);
but in this case we have to implement a callback function. I don't know how to implement callback and then use it. Can somebody help me. I am using TestComplete 7. Script that I wrote;
var objHTTP = new ActiveXObject("MSXML2.XMLHTTP");
objHTTP.open("GET", strFileURL, true);
objHTTP.onreadystatechange = Callback;
objHTTP.send();
while((objHTTP.readyState != 4) && (objHTTP.readyState != 'complete'))
{
Delay(100);
}
if(200 != objHTTP.Status)
{
Log.Error("The " + strFileURL + " file was not found." + " The returned status is " + objHTTP.Status);
return;
}
I don't know how to implement Callback function. Can somebody provide me implementation?
Thanks
Probably, the hanging is the result of the while loop waiting for a specific value of the readyState property. If the property never gets one of the expected values, the script will work forever.
I think the MSXML2.XMLHTTP object fails to load the large file, and never sets the readyState to one of the values your script expects. To understand what exactly is happening, I would check what value the property has after very long time, which is enough either for the file to load, or for the attempt to fail (say, 2 hours). If you know what value the readyState property has when the downloading fails, you can handle it in the script to avoid hanging.
That's it about the hanging itself. Now about the cause of the file downloading problem. I have found a page that tells about the problem and suggests setting higher timeouts - take a look:
http://edgylogic.com/blog/downloading-large-files-vbscript/
The example is in VBScript, but it should be easy to implement the same approach with JScript. Please note that the example uses a different COM object - ServerXMLHTTP. You can read about it (including differences from XMLHTTP) here:
http://msdn.microsoft.com/en-us/library/ms762278(v=VS.85).aspx
I hope this helps.