Why can't our app store a simple key/value pair in iCloud? - iphone

I've configured our app for iCloud usage with the appropriate entitlements, under a provisioning profile that is set up for iCloud, and a developer profile that's associated with this provisioning profile.
The application identifier matches what's specified in the provisioning profile (com.ourcompany.ourproduct). I don't get any errors when building the app.
iCloud is enabled on my phone, and is working (as evidenced by my calendar, contacts, and bookmarks being updated).
And yet this fails (localID is a valid NSString):
NSUbiquitousKeyValueStore* iCloudStore = [NSUbiquitousKeyValueStore
defaultStore];
[iCloudStore setString:localID forKey:#"ourKey"];
If I call synchronize after this, it returns NO. If I allow plenty of
time for the update to occur, subsequent attempts to retrieve the data
still fail.
Any idea what the culprit could be here?
Thanks!

In the simulator, NSUbiquitousKeyValueStore will just store values on disk and won't even try to synchronize anything.
On the device, synchronize will generally fail because your kvstore-identifier entitlement is incorrectly set but you should then see an error log in your Console.

Are you running it in the simulator? iCloud sync doesn't appear to work in the simulator, only on a device. Beyond that, your code looks good. I would expect it to work.
I also noticed that I was able to store and retrieve keys even before I set up my entitlements. I'm assuming the entitlements just allow you to link a key-value store to your App ID so that multiple devices or multiple apps from your company can share a store.
Knowing this, you could try completely removing references to iCloud in your entitlements and see if that works. Just for testing purposes.

Related

tvOS unique device identifier

I'm developing now an app for Apple TV. It is a client-server app. On registration, users get a free trial period. My goal is to avoid situations when user will just register new account or reinstall the app and get the trial period again. I need to identify if trial was already activated for each concrete device. So I would like to know if there is a legal or semi-legal way to identify each device? I will appreciate any ideas!
You can store some value in the Keychain (read more about it
here) and check if this value was previously stored in the Keychain. If so, it means that user installed your application before.
You can use identifierForVendor (documentation) but that changes once the app is uninstalled.
The value in this property remains the same while the app (or another app from the same vendor) is installed on the iOS device. The value changes when the user deletes all of that vendor’s apps from the device and subsequently reinstalls one or more of them.
Perhaps you could couple that with a user's email address to prevent creating new accounts. Not foolproof, but certainly makes it more difficult for the user to get around it. They would need to uninstall the app and use a different email address to circumvent you.

"xxx has no valid com.apple.developer.ubiquity-kvstore-identifier entitlement" on one device only

I'm testing an iCloud-enabled App that uses the iCloud key-value store.
I'm testing it on an iPad and an iPod, both running 5.1.1.
Today, with no apparent reason, running on the iPad (and on the iPad only) causes the message "xxx has no valid com.apple.developer.ubiquity-kvstore-identifier entitlement" to be shown and I cannot access the key-value store, which means that I cannot run the App on that device.
Accessing the iCloud file sore works fine.
The provisioning profie hasn't changed, the entitlement file hasn't changed, the project and target settings haven't changed, and the code still runs fine on the iPod.
There's only one target for all devices.
Removing the App from the iPad and re-installing it doesn't help. Product Clean doesn't help. Removing the iPad from the Xcode organizer and re-enabling it doesn't help. Removing all the App's data from iCloud doesn't help. As far as I can tell, nothing helps.
Any ideas?
I've seen problems with older profiles being cached / sticking around on the device.
You might try opening Settings:
Go to General -> Profiles.
Delete all the profiles related to this app.
Delete the app.
Re-install the app and see if that helps.
Noticed yesterday that the automatically generated entitlement file does not contain all the required entitlements. One is for document storage, the other for key-value pair data.
"ubiquity-container-identifiers" and "iCloud Key-Value Store"
Apple Docs
...also, make sure the entitlements file is listed in " Code Signing->Code Signing Entitlements" tab in build settings, for both release and debug.

Using iCloud in iOS Simulator

In my App, when I try to run code in the iOS Simulator:
NSURL *iCloudURL = [fileManager URLForUbiquityContainerIdentifier:#"2VHM28566N.com.eept.TestICloud"];
NSLog(#"IS ICloud : %#", [iCloudURL absoluteString]);
It shows that iCloudURL is nil.
Can we use iCloud without an iPhone device?
I tried to run my iCloud app today on the simulator and there is no option to enable iCloud in the simulator as far as I can see. I looked in settings, but no luck. So the answer would be no, you can't really test iCloud unless you test it on an actual device.
If anyone has a workaround, that would be fabulous. It's a bit tedious to always test your app on the device.
In Xcode 5:
iOS Simulator now supports iCloud syncing of documents and KVS data
within an app, enabling apps to sync between devices using iCloud.
This feature is useful when testing to ensure that the app documents
and data are syncing properly across multiple devices.
Note: With the app running in the iOS Simulator, sign in to an Apple
ID account using the Settings app. After signing in, use the “Trigger
iCloud sync” command in the Debug menu to tell the simulator to sync
with other devices.
I know this is an old topic, but you can test iCloud by changing your deployment target to 'Device'. Plug your device in via USB and let the fun begin.
I would imagine that this is done for security reasons, and for a very good reason at that.
Because your device will have a mobile provisioning certificate which ties up with your iCloud 'bucket' as well as your App Bundle ID, it ensures that only you (your app and allowed devices) have access to your provisioned iCloud bucket.
If you could run it on the simulator without having all of these certificates and ID's in place, you could easily get a team ID from any other app which you download, slap together a project using that identifier and without a certificate marrying up developer, with iCloud bucket, you'd get full access to another App's bucket.
All I did to get around this was order a 5m USB extension so I can have my iPads, iPods and iPhones on the desk in front of me without having to crouch under a desk or sit in awkward positions whilst testing.
edit Just to add an slightly clearer answer as to what allthewayapps asks about the bundle ID.
2VHM28566N.com.eept.TestICloud
is made up of 3 parts in this case:
2VHM28566N - Being the TeamID which Apple assign you when you register as a developer
com.eept - Reverse domain notation of the App's related website i.e. Apple apps would have com.apple
TestICloud - The name of that app itself.
In short its:
teamid.com.yourdomain.appname
Hope this helps.

iphone keychain items persist after application uninstall?

I am playing with idandersen's scifihifi-iphone code for keychain and came across the following behavior - I set the password using, say
[SFHFKeychainUtils storeUsername:#"User" andPassword:#"123"
forServiceName:#"TestService" updateExisting:YES error:&error];
Then delete test application from device and install it again - the previously set password appears to remain in keychain...
Is it the expected behavior? And is there a way to make sure that password I set will be deleted with the application?
Yes, this is the expected and correct behavior.
Some keychain items may be shared with other apps you control (that share the same keychain item access group).
You should just leave the info alone when your app is removed. You have no callback or method of removing the keychain items on deletion of your app.
Edit:
They finally reverted the behavior described in my answers, so until everybody move away from that range of versions, this should not happen anymore.
Unfortunately, this is not the case anymore. It has been changed since iOS 10.3.
This is an intentional change in iOS 10.3 to protect user privacy. Information that can identify a user should not be left on the device after the app that created it has been removed.
It has never been a part of the API contract that keychain items
created by an app would survive when the app is removed. This has
always been an implementation detail.
See the reference here.

How long is an APNS token valid for?

With APNS, when a device registers, how long is the token it registers with good for? The entire time the app is installed? I seem to recall a note in the documentation saying it was only good until sync/reset, but looking at the docs again I can't find that note (and it hasn't held true in my (admittedly non-extensive) testing). Can anyone confirm how long each token is valid for?
In addition to changing when a device is wiped clean, a token for a app/device combo will also change when being debugged on a device with Xcode vs. when that same app is run from a released (app store) version of the app.
I ran into issues recently when I was storing multiple device tokens for my own phone. I had two tokens in our database for one phone. One was assigned to me when I was developing with Xcode and the other was assigned from the released version of the app.
The problem was the debug token only worked on the sandbox servers and the release token only worked on the production servers. When I was testing, I was sending alerts to both tokens and Apple would drop my SSL connection because one of them was invalid.
That being said, I believe Apple reserves the right to change them whenever they want, which is why it's necessary to request the token on every application launch.
I hope that helps.
Looks like it only changes when a device is wiped. Found this in the documentation for application:didRegisterForRemoteNotificationsWithDeviceToken:
Note that the device token is
different from the uniqueIdentifier
property of UIDevice because, for
security and privacy reasons, it must
change when the device is wiped.