Subscription type from development environment in Cloudkit not removed properly - cloudkit

I have created cksubscription with alertBody programatically and it works fine.For testing purpose at development environment,I deleted that subscription from cloudkit dashboard(not using code) and again created cksubscription with different alertBody using same code. After creating this I got 2 Alert message with both alertbody. I am not getting what's the problem? At dashboard it shows only one subscription type and when push notification fire is shows 2 message.
Does anyone know how to resolve it?

In the dashboard you will only see the subscriptions that are setup for the user where you loged in into the dashboard. When you remove that subscription, then you will only remove it for that user. If your device is loged in with a different user, then the old subscription will still be there.
You could check for available subscriptions at runtime. You could use code like this:
self.database.fetchAllSubscriptionsWithCompletionHandler({subscriptions, error in
for subscriptionObject in subscriptions! {
if let subscription: CKSubscription = subscriptionObject {
self.database.deleteSubscriptionWithID(subscription.subscriptionID, completionHandler: {subscriptionId, error in
...

Related

Custom Notification Depending on action

SWIFT 3 / Firebase
app like instagram/Facebook
Notifications
I am working on letting users know when another user e.g. liked their post, made a friend request etc.
I set up everything for cloud messaging with firebase and can send bulk messages at all my devices.
Now I want to introduce notifications which contain the current user, the user who did the action and what happened.
Unfortunately I did not find anything about this despite the general implementing of firebase cloud messaging.
My questions are:
1: Do i have to structure a database (e.g. .child("notifications").child(userId).... ?
2: How do I get the token from the stranger user I address with the notification?
3: How can I make the input variable?
I am happy about all kinds of help!

iPhone doesn't receive notificatins in debug mode

We have a really weird problem with the remote notifications on iPhone. Device just doesn't receive remote notifications however registration works fine. We checked all certificates and also provisioning profile, also tried to send test notification directly from Azure, the same result as we send with our api. When app is installed from HockeyApp notifications works fine. In debug DidReceiveRemoteNotification method is just not called.
public override async void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
// Opened by push notification.
if (application.ApplicationState == UIApplicationState.Background || application.ApplicationState == UIApplicationState.Inactive)
{
// Make userInfo readable.
PushNotification notification = CrossDevice.Current.ConvertToNotification(userInfo);
}
// Process notification so we can attach to it's received event.
CrossAzurePushNotifications.Platform.ProcessNotification(userInfo);
// No data is altered.
completionHandler(UIBackgroundFetchResult.NoData);
}
Note: we are using AzurePushNotifications plugin
xamarin forum question
You should use the 'sandbox' for testing with the debugger attached. See this link or this link for more information about sandbox vs production.
Please also note that switching from production to sandbox in Azure NotificationHub does not always work. Best solution is to create a separate notification hub for test and production.
You need two Notifications Hub: one for testing and one for production.
If you are developing and running the App from Xcode, you have to use the testing Hub with a testing certificate and when you want to upload it to the Apple Store o TestFlight, you have to change the URL and use the Production Hub. If not, there is not woing to work.
You need different certificates, you can check the process here: https://learn.microsoft.com/en-us/azure/notification-hubs/notification-hubs-ios-apple-push-notification-apns-get-started
Here is when you decide what kind of certificate you have to choose: https://learn.microsoft.com/en-us/azure/includes/media/notification-hubs-enable-apple-push-notifications/notification-hubs-appid-create-cert.png

Are public database subscription notifications received by all users with the same subscription?

I have set up a CKSubscription* so that I receive changes to a record type.
I'm using the public database.
When I test with the same user (same iCloud account) I receive the notification.
If I use a different user (different iCloud account) I don't receive the notification.
Are subscriptions designed to only work between devices of the same user?
Here is the documentation that describes subscriptions:
Use a CKSubscription object to track changes occurring on the server.
A subscription acts like a persistent query on the server that can
track the creation, deletion, and modification of records. When
changes occur, they trigger the delivery of push notifications so that
your app can respond appropriately.
https://developer.apple.com/library/ios/documentation/CloudKit/Reference/CKSubscription_class/index.html#//apple_ref/occ/cl/CKSubscription
I would expect to receive a notification no matter which user edits the record, and subscription predicate should still match.
UPDATE
*Every user has a subscription with the same predicate, essentially focused on a single recordType with a particular property value.
The payload for this subscription is only to push shouldSendContentAvailable=YES.
The documentation reads:
When this property is YES, the server includes the content-available
flag in the push notification’s payload. That flag causes the system
to wake or launch an app that is not currently running. The app is
then given background execution time to download any data related to
the push notification, such as the set of records that changed. If the
app is already running in the foreground, the inclusion of this flag
has no additional effect and the notification is delivered to the app
delegate for processing as usual.
The recordType's security permission is:
FURTHER UPDATE
Checked the logs of the device not receiving the push when it should and saw:
apsd[85]: Silent Push: Deny app not available
Rebooted the device and now it works fine!
This behaviour was due to a mistake in how my CKSubscription was configured. If we want all users to receive notifications from the subscription then it should not have a zoneID set (should remain nil). I was setting the zoneID to the value from the defaultRecordZone, this will restrict the notifications to the current user only as the defaultRecordZone's user is the current user.
UPDATE
Finally solved the problem. Not only was it an issue of zoneID, but there also seems to be a bug. My subscription notificationInfo simply had shouldSendContentAvailable set to YES. This doesn't cause the subscription notification to fire for changes made by anyone other than the current user (u1d1->u1d2, but not u1d1>u2d2). I simply added an alertBody and the notifications start firing.
Anyone else face this issue?
UPDATE 2
Rebooting the device solved the issue.
And to add another dimension to the answers above, CKSubscriptions are logged 'per iCloud Account' not per device. All devices logged into the same iCloud Account (*) will receive all notifications based on any subscription entered by any device under that iCloud Account. When the above refers to 'user' they mean 'any device logged into that iCloud Account'.
except for the particular device that modified the file leading to the notification
Every user should create it's own subscription. A subscription is only valid for the user that created it. On app startup you should test if the subscriptions are there for the current user (you could use the database.fetchAllSubscriptionsWithCompletionHandler function for that)
Then if there is a subscription for a recordType and predicate, then that user should receive the notifications of there are any changes for records within this recorType and predicate.
There is no guarantee that every change will be pushed. If there are multiple notifications, it could happen that you won't receive all. This is why after receiving a notification you should also query for outstanding subscription notifications on the server (using CKFetchNotificationChangesOperation)
If you create a record on your device, then you should not receive a notification for that on that device. So if you have a data colleciont for a subscription in your app, then you should also update this after you modified the data.
If you think this is complex, then you could try EVCloudKitDao

How to test Auto Renewal In App Purchase Model

I have to implement In App Purchase Auto-Renewal Model in my app. I have created a test user and getting the response from App Store for subscription. When I tap "Confirm" then sometimes its state becomes SKPaymentTransactionStatePurchased and sometimes it becomes SKPaymentTransactionStateRestored. My problem is that I want to prevent user to use the app if he has not subscribed the app. For that I am trying to track the state of "SKPaymentTransaction" so that I can allow or disallow the user to use the app. Such that, if the state is SKPaymentTransactionStatePurchased, only then he could be able to use the app, but I don't understand how its state changes.
One more thing, When I tap on the "Settings" to manage my Auto-Renewal, it shows me that my app will be expired on the current date i.e., today itself, but when I tapped on the "Confirm" button to subscribe my app for one month then expiry date should be after one month. I don't understand how this whole process is working.
I have read whole documentation of Auto Renewal, but didn't get any help from that.
Please help!
Not sure about your first problem. In my case, I can never get SKPaymentTransactionStateRestored called at all. I am debugging why.
Meanwhile, I was facing the second problem you described. When I decoded the receipt, it looks like they keep the subscription valid for 5 mins. Sounds like a feature for testing in sandbox. At least that's what I am assuming.

In App Purchase An unknown error has occured

I have created a test app that has in app purchasing. I am able to connect to the store and verify my product ID's. I then use my test user account to purchase a product. And guess what... it works... the first time. If I try to use the test user account to buy another product (the same product or a different one) then I get a pop up that says
"An unknown error has occurred"
with a "Cancel" and "Retry" option. If I retry then I get the same error. After hitting cancel I get the error:
Error Domain=SKErrorDomain Code=0 UserInfo=0x161180 "Cannot connect to iTunes Store"
Any ideas?
Update:
I have found a work around. For some reason apple does like Canadian test users. I switched to using US test users and everything worked.
I also found that after an OS upgrade I needed to delete the app off my phone and do a clean build to get things working again.
So the issue here doesn't have anything to do with wether or not your iTunes connect user is in Canada or the US. It's kind of a strange bug on Apple's side.
What happens is if you sign-out of an iTunes connect user in Settings.app and then sign back in with that user in Settings.app that test user is somehow poisoned and is broken permanently. You will no longer be able to use that account for testing.
To avoid this sign-out in Settings.app, but don't sign back in until you are inside your application and it prompts you during purchase.
I am having this EXACT same problem. I have some more details so let's get to the bottom of this!
When I create a new tester account, the first purchase always works. The second time gives me an alert that says "You've already purchased this but it hasn't been downloaded..." on the device. Every time after that I get an "Unknown error has occurred" message.
My NSLogs gives some more info. The first payment is normal. But it gets weird for any payment attempt after that. After I send the payment request and make myself a queue observer, I see TWO transactions in the purchasing state... weird, why two? After I get the error and tap cancel, I get two transactions in the failed state sent back. Why would I get two responses when I only sent one payment request?
I am using a consumable product type that the user should be able to purchase over and over again.
This worked perfectly for me the last month of testing. It only started acting like this in the past week. The two transactions seems to be from Apple's side, because I can't see any way my code might be causing it. Perhaps Apple made some changes to their purchasing system and haven't worked out the kinks yet.
In my case, I was logged in with another sanbox tester account(of different developer account I mean) in Settings -> iTunes & App Store -> Sandbox Account.
I simply logged out and then tried again to perform the In-App Purchase. And so it asked me to login with another sandbox account. I did so and it worked as it should!