I'm currently building an app that allows user to share events and check in their guests simultaneously using multiple phones. I managed to set up CKQuerySubscription and update, delete and create works fine but only on the primary phone (the one sharing the event).
I recently found out that for a non-primary user to get notifications, it has to get notifications from CKDatabaseNotification which i set up and it works as I am getting remote notifications when I make changes through CloudKit Dashboard.
But the notification i get (CKDatabaseNotification) does not come with anything that would allow me to find what records changed. I've tried casting it as CKNotification as suggested on this link but as expected it fails.
I have a custom zone set up and my questions are as below:
How do I get any information about what changed from a CKDatabaseNotification?
Am I even doing that the right way? I've read somewhere else as well that some people managed to set up subscription through CKQuerySubscription on a shared database as long as it is on a custom zone, which I have but my codes told me subscription failed.
The CKDatabaseNotification will only tell you that something has changed, not what it is. The recommended path forward is you use a CKFetchDatabaseChangesOperation to find out what record zones have changes. Then you use the record zone IDs from that operation in a CKFetchRecordZoneChangesOperation to get all the changes.
There's a bit more information in the CloudKit Quick Start Guide
I'm cherry picking some relevant info below:
After app launch or the receipt of a push, your app uses CKFetchDatabaseChangesOperation and then CKFetchRecordZoneChangesOperation to ask the server for only the changes since the last time it updated.
The key to these operations is the previousServerChangeToken object,
which tells the server when your app last spoke to the server,
allowing the server to return only the items that were changed since
that time.
First your app will use a CKFetchDatabaseChangesOperation to find out
which zones have changed
Then
Next your app uses a CKFetchRecordZoneChangesOperation object with the
set of zone IDs you just collected to do the following:
• Create and update any changed records
• Delete any records that no longer exist
• Update the zone change tokens
The WWDC video CloudKit Best Practices addresses this topic as well.
Related
I'm working on an app that uses CloudKit sharing functionality. The sharing features have been working great, but recently I no longer get the user names back from the CKShare.Participant when a user accepts the sharing request.
Details
I'm using the built-in UICloudSharingController to set up the share, which works and sets up the share properly.
When the invited user accepts the share, the owner gets a notification of the change in the zone and then fetches the CKShare.
The fetched CKShare object has an array of share participants (CKShare.Participant), which has a nameComponents property. I've used this in order to get the first and last name of the participants to display in the UI. This was all working fine until recently.
Now, however, I'm only getting values in nameComponents for the owner of the share. The accepted participants have nil values for the nameComponents.givenName and nameComponents.familyName.
I have not changed anything in this part of my code in some time, so don't think I've caused this. I've tried this on iOS 11, 11.4, 12, 12.1 and all have the issue. This leads me to believe there might have been a change on the server side from Apple.
Note
I am not requesting .userDiscoverability permissions. I have not had to do that in order to get the names once a user accepts. I realize that I can request that and then use CKDiscoverUserIdentitiesOperation to get the names. But I'd rather not as I don't want the dialog, which is confusing for users.
Has anyone seen this change? Or better, yet, does anyone have any suggestions for tracking down the cause or fixing it?
Thanks.
I want to store only 20 Notifications which include
"Title,Detail and Received Time" fields inside Notifications Table.But,I only found solution for working CoreData with CRUD some example.But,I am still seeking for working with limitation when user fetch new results from api inside device database.That is where I am stuck.I don't know how to do it using CoreData because I was beginner at that.
Requirement :
1.Application can only store 20 Records maximum.So,when it reach max length,it will do First-In-Last-Out to Notifications table base on Notifications Received Time.(First Problem)
2.Every time the user do pull to refresh,my app fetch new notification from Web-Backend and replace or overwrite on user device database when it successfully download new notifications like "Push Notification Service App" on App Store.(Second Problem)
I really need a hand to pick up with core data flow which I am stucking at things I am not familiar with.
Any help or guide please?(Posting Sample with .json is appreciated)
use NSUserDefaults for that if your data size is small
Consider using a service, like RestKit or similar, to support your web service interaction. Each record should have a unique identifier supplied by the server so you can find an existing copy and update it instead of needing to delete everything and recreated it.
To trim your data use a fetch request with a fetchOffset and a sortDescriptors by date. This allows you to skip the newest 20 items and gives you a list of everything that needs to be deleted. If you're using RestKit you can supply this fetch request in a fetch request block and the deletion will be done for you.
I am coding in Xcode 6.1.1 with objective-c.
In my app it is critical that I use the correct time.
I only want the app to use the time of the device when the time is synced with the servers.
If an user is somehow using his/her own "weird" time the app should detect that and tell the user to switch back to use the app.
I know there is NSSystemClockDidChangeNotification, but that only gives back when the time is changed. It does not give back what the change was and if the user switched to "custom" time or synced back to an NTP server.
Question: How do I detect if an user is connected to an NTP server or not?
Maddy is right that you can't specifically find this out from iOS.
However, in the past I've delivered a client for a premium subscription service that had a similar need to know if the user was messing with time. In particular we needed to verify this when there was no network available, in order to prevent the user from accessing premium content after their subscription had lapsed. The very simple mechanism we used was as follows (IIRC):
every time the app launches or comes in from the background, record the current time (eg: in NSUserDefaults)
compare the current time to the last recorded time--if the current time is earlier than the last recorded time, force the user to go online and sign in to the service.
I don't claim it is 100% foolproof, but for our purposes we felt it was good enough to prevent users from trying to circumvent time-based restrictions on accessing premium content.
I'm developing an application which holds a list of objects.
The user should be able to favorite some of these objects, which then gets saved for easy access. Simple enough, right.
However, in addition to that, I want it so that the application notifies the user (using a notification, like when you get a new SMS), whenever one of the favorited objects have had something changed (in my application the objects represent a pub, and a change to the pub is when it has a new event scheduled). The change is done on a remote server, using a webpage.
When my app is active I can just poll the server every few minutes and compare the properties of the object, and if I see a change notify the user.
But how will I do to make this work when my app is NOT in the foreground? I want the user to get a notification even if he/she is not currently running my app.
The app does not have any login-functionality, so I can't send out specific push notifications to specific users. So the only thing the server might have access to is perhaps the device ID. I.e. there is no real way for the server to know which favorites a device ID holds.
Is there some smart way to do this? On Android I can just use polling but as iOS doesn't allow code to run in the background in the same way I don't really know how to do.
All help greatly appreciated. Even if it's just a "I don't think that's possible".
Just create a table that associates device ID with favorites. When a favorite changes, send that device ID a push notification
The user is the device ID
I have a game where users can do a certain activity once per hour. How can I make sure it's been an hour since the last time they attempted something without them just changing their devices current time in settings?
Also, if I wanted to prevent the user from just deleting the app and re-installing it so they could constantly keep trying without having to wait to full hour is there any way I can store data on the device even after an app delete or would that have to be a server thing?
If I don't have a server can anyone think of a clever way to do this via Free in-app purchases or something?
The only way to persist data in a way that survives app reinstalls is to save it to the keychain. This works, because keychain data may be shared across multiple applications; the rest of your application's data is removed on uninstall.
If you need a reliable way to tell the current time, the device must be connected to the internet. In this case you would be able to check the current time using one of the time services through the NTP.
That sounds like exactly the sort of task you would need a server for.
When the user wants to perform this limited action, have them ask the server for permission. You can log the user's ID and request time, decide if they can execute the action, then return a small success/failure message. Works if they change their clock, works if they log in from a different device, works if they wipe the device data.