CloudKit Delete Self option for CKReference Doesn't work - ios

Does anybody have experience using the CloudKit option to DeleteSelf for a CKReference? Here is what I got from the docs:
DeleteSelf
The delete action for referenced records. Deleting a record also deletes any records containing CKReference objects that point to that record. The deletion of the additional records may trigger a cascade deletion of more records. The deletions are asynchronous in the default zone and immediate in a custom zone.
So I've been testing this out, I have created multiple CKReference objects both using the CloudKit Dashboard and by using my app. Whenever I do it with my app I create the reference like so:
let reference:CKReference = CKReference(recordID: savedFriend.friendID, action: CKReferenceAction.DeleteSelf)
I know that it is being assigned to delete itself, because in the dashboard it shows the option checked off:
I must be doing something wrong because whenever I go and manually delete that record that is referenced using the dashboard, or set my app to delete it programmatically, the record disappears but the reference never gets removed. I thought maybe I should just wait and it would happen eventually, but hours later it's still there checked off like it should have deleted itself. It's kind of frustrating because I designed some of my code assuming this would work, now I can have an app that's wasting resources trying to find a CKRecord that doesn't exist anymore. Should I just not rely on this to ever work? I appreciate any help or advice I can get.
UPDATE ~ 04/07/2016
I jumped the gun coming back here and posting an update that the issue had resolved itself. I wasn't totally convinced that the issue wouldn't pop back up so I sought some reassurance last night. I created 5 different CKRecords and created various different CKReference objects to reference them throughout my database. I then proceeded to set the CKReferenceAction.DeleteSelf option on each reference (I tried two manually through the dashboard and the other three done programmatically). Anyways, I waited a few minutes and then deleted the referenced records...after ten minutes the references were all still present. I waited another 5-10 minutes and they were still there so I went to bed assuming they should definitely be gone by morning, right? Wrong! Twelve hours later the CKReference entries are still there and the referenced records are still gone. I'm definitely scratching my head, it seems as though it's a bug with CloudKit. I should mention that I've also noticed some weird behavior in my dashboard. For the past four or so days, down in the bottom left hand corner it has consistently said it's "Reindexing development data", here is a picture for example:
Could that be causing this issue? Is anybody familiar with this issue and knows a way to solve this? Any suggestions would be appreciated. I have filed a bug report with Apple.

This is most likely a permission issue.
The cascading delete will only work if the user deleting the records has 'write' permissions to all the records needing to be deleted. So in the CloudKit Dashboard, the cascading delete will only work for the records created with the developer's iCloud account.
See my answer there: https://stackoverflow.com/a/38606004/6643055

Related

Swift InAppPurchases - give previous customers a free lifetime subscription

So my App was released to the AppStore some months ago and was free to download. I gained like 2k Users. Now I am implementing an auto renewable Subscription model, so future users can use the demo app for free and subscribe to get the full content.
How ever I want to thank my Users "from day one" by giving them free access to all content without paying the subscription.
Is there a "given way" how to implement this because it seems like a common scenario. If not, does someone with IAP experience has a smart workaround how to handle/implement it?
Thanks guys :D
The answer from Paul didnt work for me. Neither did any other solutions.
But i managed to find a solution.
In case you use CoreData as database within your app, you can use the solution i found out for my app.
The idea:
If someone downloads the app from the appstore, he will receive the latest database version in your app.
If someone updates your app, coredata will perform a migration. And this migration updates from bottom to top trough your database versions.
Through this behavior we have the opportunity to dinstinct the two cases.
Solution: We create two new database versions. One will only be updated by the former users. We will set a flag here. The new Users will never get in touch with that.
The first new one will create a new attribut field in any entity (e.g. User) e.g. isFormerUser as a Bool. You can set it per default on true.
Now we create a second new one (the latest one). Trough a Core Data mapper it will take the $source attributes if it migrates.
So by that case, all FormerUser were set on True and will keep that attribute.
Here will the default be False, so if $source didnt exist, set it on false (new Users).
This solution is nice because it gets set once by that migration/update and you dont have to carry hardcoded stuff in your app. Now just create a load/get Function from CoreData for that attribute and set a variable to use in an if-statement.

Delete posts after a certain time, even when user isn't using the app

I'm using Swift on iOS and Firebase
I am trying to find a way to delete a post when it was shared more than X hours ago, no matter if the user is connected on the app, or not.
For that I have set a time stamp for my post object, which gives the date/time when the post is initially created.
I thought about adding a "timer" to my post node, that would be updated every second. The problem with that is that I would need for that to make a request to my database every second, and this would obviously be very data consuming.
I googled a lot and it seems like the only way of doing this is using some server-side code in Javascript using Google Functions, and I read the documentation but I still have no idea how I can do that and can't barely find anything refering to it.
Do you have an idea how to solve this problem?
Thanks!

CKReference .DeleteSelf attribute has no effect

How does .DeleteSelf really work? Docs says:
When the reference object’s action is set to
CKReferenceActionDeleteSelf, the target of the reference—that is, the
record stored in the reference’s recordID property—becomes the owner
of the source record. Deleting the target (owner) record deletes all
its source records.
but my impression is that deleting a target will not always delete source. And it is quite annoying when it remains in the container, client downloads it, and expect that the reference point to somewhere, but target does not exist when building up slice of the server data store on client?
How do you treat this case? You ignore that sort of records? Or periodically you look up the CloudKit storage, searching for corrupt records to delete them?
Or instead of deleting a record is it better to set an attribute that it is in a deleted state, but keep it in the database?
I just struggled with this one for a while and I thought I would share my findings...
It is fundamentally a permission issue. The cascading delete will only work if the user deleting the records has 'write' permissions to all the records needing to be deleted.
So in the CloudKit Dashboard, the cascading delete will only work for the records created with the developer's iCloud account.
If you need to delete records that don't belong to the user deleting them, you can add 'write' permissions for a Record Type under Security.
If you are deleting via CloudKit Dashboard you have to wait before switching record types to check the other end of the reference. More than likely you switched before the delete actually happened. You can use Safari's Web Inspector on the Network tab to check when the delete has actually finished. It takes a very long time to delete multiple records.

Alternatives to UPDATE notification that does not work

UPDATE notification stopped working. What workaround do you have, until Apple figures out something?
CKFetchNotificationChangesOperation sometimes does not return UPDATE, DELETE notifications
CloudKit push notifications on record update stopped working
https://forums.developer.apple.com/thread/7288
My quick fix, that in every minute, and when user triggers UIRefreshControl, then I downloading all the records that were modified since the last update. It works. But I have a better idea in my mind, curious, what do you think. Any drawbacks.
I am thinking adding a Change table to the database. It will have a recordName, recordType, changeType fields. changeType could have insert, update, delete string values. (or int enumerations accordingly)
And I would create and observe with CKSubscription only the Change table. Always when a record is create, updated, deleted in a custom table, I would do two things, do that action and as a second action I would make a 'log entry' into the Change table. Because it is an Insert operation in Change, and insert notification seems to work, all the device would get notified. They could download the refered record.
Do you see any drawbacks?
I have used a similar strategy. There are some drawbacks:
more data (storage and transfer) usage
limited subscription possibilities or you have to duplicate even more data.
extra code in your app that you actually don't want to be there.
The only good solution to this problem is:
Apple should fix it...

Parse.com object disappears after saving

This is a bit of a crazy one. I have an IOS app that saves an object to Parse.com's datastore. Until a couple of days ago everything worked well. Now, suddenly, the object is not going into the database. I would put the code here but it doesn't seem to be the issue, as it gets even more bizarre:
When I go directly to the data browser and insert a row manually, it shows up right there.
But when I refresh the data browser -- the object is gone.
Looking at the forums here's some more data:
When I save from the app, I have an existing current user.
The object itself exists.
The permissions on my class are all "Public."
The app codes are correct (I'm able to read from the database.)
I'm even seeing the saveInTheBackground success block getting called, and printing out the object it has a valid object id!!!
But then it goes pooooooffff and is gone.
Any idea what's happening?
EDIT: I added a different class with the exact same columns, changed the appropriate fields in the app, and now everything works. But this is obviously alarming, that a class stops saving objects all of a sudden. Any idea why?

Resources