Failed to read values in CFPrefsPlistSource iOS 10 - ios

I've updated my Xcode 8 to beta 2 today and I'm trying to share data between App and Today Extension. I'm facing with this log warning:
2016-07-08 18:00:24.732472 ProjetctX[941:42801] [User Defaults] Failed
to read values in CFPrefsPlistSource<0x1700f1280> (Domain:
group.x.p.t.o, User: kCFPreferencesAnyUser, ByHost: Yes, Container:
(null)): Using kCFPreferencesAnyUser with a container is only allowed
for System Containers, detaching from cfprefsd
Anyone can help me?

This is actually a spurious warning that was introduced in iOS 10 and macOS 10.12:
NSUserDefaults tip: in the current OSs there's a logged error "…with a container is only allowed for System Containers…".
This is spurious.
Trying to catch a particular failure mode, caught a normal operation case at the same time.
My successor on UserDefaults also has not figured out a way to make this less alarming without making the symptomatic case impossible to debug :/
https://twitter.com/Catfish_Man/status/784460565972332544 [thread]
The advice of prepending your team ID will silence the warning, but will also create a new empty user defaults. This will result in any previously stored data being unreadable.
For the time being, the solution is just to ignore it.
Also, Apple staff member CFM on the forums:
The logged message is spurious unless you're doing very specific things that I don't think are possible without using private functions (it was added to catch misuse of those functions, but unfortunately also caught a normal usage case).

Here’s how to use UserDefaults with App Groups to pass data between your main app and your extension:
In your main app, select your project in the Project Navigator.
Select your main app target and choose the Capabilities tab.
Toggle the App Groups switch to ON. This will communicate with the
Developer Portal in order to generate a set of entitlements.
Create a new container. According to Apple, your container ID must
start with "group", so a name such as "group.io.intrepid.myapp" is
perfect.
Select your extension target and repeat the process of enabling App
Groups. Do not create a new App Group, simply select the group that
was just created in the main app target.
When reading or writing UserDefaults in either your app or your
extension, do not access UserDefaults.standard.
Instead use UserDefaults(suiteName: "group.io.intrepid.myapp").
Note: The suite name is the name of your App Group container created
in Step 4.
Make sure, group enable and using same group id for both extension and app capability section!
Credit goes to http://blog.intrepid.io/ios-app-extensions

Change you group name in Xcode entitlements from:
group.com.mycompany.myapp
To
group.MYTEAMID.com.mycompany.myapp
ps: you can find your MYTEAMID in developer.apple.com membership

The solution for me was to not use the same identifier for the application Bundle Identifier and the part after "group.".
Say, the app bundle id is "com.app.id", then group id as "group.com.app.id" is causing issues. After I change it to "group.com.app.id.something" it stops.

Also had same issue with my macOS app.
Solved it by: Reboot the device!
https://stackoverflow.com/a/39876271

The SuiteName (postfix) must not be the main Bundle ID.

I’m facing this same issue when I’m trying to use initWithSuiteName. Seems that this is a bug from Apple.
The only solution / workaround I found is to reset all the settings of the device.
Go to Settings -> General -> Reset -> Reset All Settings.
This doesn’t erase any content on the iPhone, just erases all the settings.
After resetting the setting, everything worked fine. Let me know if it helps you too.

Build with Xcode 8.1 Beta and you will see the same warning, but you will also get the value.

By default, if you are using the Settings.Bundle/Root.plist for displaying and editing your app preferences via Apple Settings App, it uses the UserDefaults.standard dictionary.
So if you are using App-Groups and you want to share this defaults / settings within your apps and extension, you need to change the container of your settings.
Step 1: Open your Settings.Bundle -> Root.plist
Step2: Add the key ApplicationGroupContainerIdentifier and as value set your App-Group-Id, defined in your Signing & Capabilities: Looks like group.xx.yy
After you have implemented this step, the default container for your App-Settings will now switch from UserDefaults.standard (your apps Path) to the Shared Path.

Set by example
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.com.xxx.xxx"];
[userDefaults setValue:#"value" forKey:#"key"]
[userDefaults synchronize]; // return maybe false, but it doesn't matter
Get by
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] init];
[userDefaults addSuiteNamed:#"group.com.xxx.xxx"];
NSString *value = [useDefaults valueForKey:#"key"];
Although the same error will still be printed when setting, the value is indeed set and can be read correctly. But I don't know why this is happening, it's just the result of various attempts.

if you suffer this problem when you try to save data to extension APP by using userDefault, maybe you had written this code:
[[NSUserDefaults standardUserDefaults] initWithSuiteName:#"group.xxx.com"];
This code reset default userDefault.
Actually,the correct code is:
[[NSUserDefaults alloc] initWithSuiteName:#"group.xxx.com"];
http://www.jianshu.com/p/e782104c3bc3

Change from
[[NSUserDefaults alloc] initWithSuiteName:#"group.com.xxx.xxx"];
to
[[NSUserDefaults alloc] initWithSuiteName:#"nnnnnnnnnn.group.com.xxx.xxx"];
Where nnnnnnnnn is your team number, the one which you use to sign your code.
Tested under Xcode 8 GM and iOS 10 GM, and worked!

Related

Could not locate installed application Xcode

I am trying to build share extension. Created the target, fixed the project settings (provisioning profile, app group, NSExtension).
Tried to run and saw the logs I added to the three methods isContentValid, didSelectPost, and configurationItems. This is my first time to create a share extension so, I was just looking around first and see when each method is called.
Now for some reason (I don't know what I did wrong), I am unable to see the logs from the extension. When I hit the run button in Xcode, the message Finished running ... gets displayed in the status bar on top.
Tried to change the scheme settings to the extension in the executable field, I get the following message when trying to run:
Could not locate installed application
Install claimed to have succeeded, but application could not be found on device. bundleId = <my-bundle-id-value>
Followed every solution I could find on the internet. Tried the solution from here and here.
UPDATE
I wanted to check if the extension actually runs or just the logs don't work. So I added the following logic to isContentValid:
- (BOOL)isContentValid {
// Do validation of contentText and/or NSExtensionContext attachments here
NSLog(#"isContentValid");
NSUserDefaults * userDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"<group-id>"];
[userDefaults setObject:#"haha" forKey:#"key"];
[userDefaults synchronize];
return YES;
}
and read then read the haha in the main application it worked! So, the question is: Why can't I debug the application? Why doesn't the application print the log statements. Developing without logging and/or debugging could take 2x, if not more, time.
UPDATE 2
The best I was able to come up with is to manually attach the debugger to the extension, add breakpoints here and there (where I wanted to put logs) and edited the breakpoints to log as action and continue after evaluation.

iOS 10 Today extension can't read shared user defaults any more

I have an application that implements Today extension. Till iOS10 it was working fine, but now I see that it can't read keys stored in shared NSuserDefaults.
My Host app code:
NSUserDefaults *sharedPrefs = [[NSUserDefaults alloc] initWithSuiteName:kSharedGroupIdentifier];
[sharedPrefs setObject:username forKey:#"username"];
[sharedPrefs setObject:#"Test" forKey:#"test"];
[sharedPrefs synchronize];
My extension code:
NSUserDefaults *sharedPrefs = [[NSUserDefaults alloc] initWithSuiteName:kSharedGroupIdentifier];
NSString *str = [sharedPrefs valueForKey:#"test"];
And str var is always nil in extension. I have set up my App Groups in Capabilities for both Host app and extension app, and I have checked it against the settings on Apple developer portal. It is all OK. Can anyone please help, is there something different that I must do?
EDIT
Another thing that I have noticed is that I have a red exclamation mark on: "Add the Add Groups entitlement to your entitlement file", and when I fix the issue, the exclamation mark goes away, but when I close and reopen project it is there again. I have recreated provisional profiles, but still the same issue
It sounds like the issues is that your Entitlements file is missing the relevant line.
To diagnose where the issue is, start with your build settings:
Under Code Signing Entitlements there should be a file listed
Open that file and ensure that it has the App Groups key with the value that matches your kSharedGroupIdentifier
Ensure that the file is not marked read-only (this would potentially cause the "fix" to not work correctly)
Verify that all of the following match:
kSharedGroupIdentifier in both apps
kSharedGroupIdentifier and the value in your entitlements file for App Groups
Next, we can narrow the issue down to the specific key or the entire preferences domain as follows:
NSUserDefaults *sharedPrefs = [[NSUserDefaults alloc] initWithSuiteName:kSharedGroupIdentifier];
if (sharedPrefs == nil) {
NSLog(#"Error loading shared user defaults!");
}
A nil value indicates that the suite name is invalid.
Rebooting the mac solved the issue for me.
Apple RNotes WWDC Seed: Running multiple iOS simulators can cause NSUserDefaults to not work Running an iOS 8 or 9 simulator followed by an iOS 10 simulator will cause NSUserDefaults to stop working in the simulator. This can be worked around by rebooting the host Mac.
I hope it will helps you,
Thanks.

iOS Keychain writing value results in error code -34018

I have an iOS application that stores some sensitive information in the keychain.
While writing values into the keychain, I am getting error code -34018.
I am currently using Apple's iOS KeyChainItemWrapper class.
Both of the following lines of code receive the same error code.
OSStatus res1 = SecItemCopyMatching((__bridge CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes);
OSStatus res = SecItemUpdate((__bridge CFDictionaryRef)updateItem, (__bridge CFDictionaryRef)tempCheck);
This issue does not occur every time, but intermittently. Once I get this error, I am no longer able to write any values to the keychain.
I have printed the error description like so:
NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:res userInfo:nil];
and this is what the error prints out:
Error: Error Domain=NSOSStatusErrorDomain Code=-34018 "The operation couldn’t be completed. (OSStatus error -34018.)"
Seems like this is a bug in Keychain, which only appears when you launch your app from xcode. See here: https://github.com/soffes/sskeychain/issues/52
We debugged it a lot and it seems an issue accessing the keychain when
the app is launched from the background. This is only happening with
the debugger (i.e. when launched from Xcode). We think the issue
might be related in our case to the debugger keeping alive the app
even if it should be killed by the OS. We tried in fact to run the
app and then put it in background and launch many other app to occupy
RAM. With the debugger the bug came up when resuming the app from the
background, while without the debugger it didn't (we did run at least
10 tests each).
If someone will come here back with this error and XCode8 with iOS10, probably you have to enable KeyChain Share in the tab Capabilities:
As others have mentioned, this is a Keychain bug, one that Apple is aware of and has been aware of since at least mid-2015.
As of March 22, 2016, however, Apple has said:
We believe these problems were resolved in iOS 9.3.
iOS 9.3 was released on March 21, 2016.
See the thread: https://forums.developer.apple.com/thread/4743
To quote the response by an Apple employee:
Mar 22, 2016 3:28 AM
OK, here’s the latest. This is a complex problem with multiple possible causes:
Some instances of the problem are caused by incorrect app signing. You can easily distinguish this case because the problem is 100% reproducible.
Some instances of the problem are caused by a bug in how iOS supports app development (r. 23,991,853). Debugging this was complicated by the fact that another bug in the OS (r. 23,770,418) masked its effect, meaning the problem only cropped up when the device was under memory pressure.
We believe these problems were resolved in iOS 9.3.
We suspect that there may be yet more causes of this problem.
So, if you see this problem on a user device (one that hasn’t been talked to by Xcode) that’s running iOS 9.3 or later, please do file a bug report about it. Try to include the device system log in your bug report (I realise that can be tricky when dealing with customer devices; one option is to ask the customer to install Apple Configurator, which lets them view the system log). And if you do file a bug, please post your bug number, just for the record.
On behalf of Apple I’d like to thank everyone for their efforts in helping to track down this rather horrid issue.
Share and Enjoy
This held me up for 2 hours before I found a quick "fix" - reboot the iOS device
A quote from the discussion at http://forums.developer.apple.com/thread/4743,
From user littledetails
As others have reported, this mysterious keychain error is most easily observable when launching via Xcode with the debugger attached. Once the error starts occurring, the keychain doesn't seem to right itself regardless of memory pressure until one reboots the device.
When I rebooted my device the error went away, allowing me to continue testing. Not sure what else to do. In my situation, moving to NSUserDefaults or some other storage solution was not a possibility.
One way to get around this issue with the keychain is to use dispatch_async to allow the app to launch. This works when the app is opened from the background. Also make sure you have the kSecAttrAccessibleAfterFirstUnlock accessibility setting on the keychain.
dispatch_async(dispatch_get_main_queue(), ^{
// save/write to keychain
})
I am using GenericKeychain classes from apple:
https://developer.apple.com/library/content/samplecode/GenericKeychain/Introduction/Intro.html#//apple_ref/doc/uid/DTS40007797-Intro-DontLinkElementID_2
struct KeychainConfiguration {
static let serviceName = "MyAppService"
/*
Specifying an access group to use with `KeychainPasswordItem` instances will create items shared accross both apps.
For information on App ID prefixes, see:
https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/AppID.html
and:
https://developer.apple.com/library/ios/technotes/tn2311/_index.html
*/
// static let accessGroup = "[YOUR APP ID PREFIX].com.example.apple-samplecode.GenericKeychainShared"
/*
Not specifying an access group to use with `KeychainPasswordItem` instances
will create items specific to each app.
*/
static let accessGroup: String? = nil
}
In this file I was specifying my custom accessGroup in this line static let accessGroup = "[YOUR APP ID PREFIX].com.example.apple-samplecode.GenericKeychainShared"
After returning to static let accessGroup: String? = nil the problem was gone. :)
Make sure keychain sharing must on under Capabilities in project Target.
In my case the App_Name.entitlements file has different bundle id than of my project bundle id. So, I change bundle id in the App_Name.entitlements file as of my project bundle id.
e.g., Suppose your project bundle id is com.Apple.testApp then got to
App_Name.entitlements file open key Keychain Access Groups key which is of Array type.
Under item0 set value of your project bundle id as eg:- $(AppIdentifierPrefix)com.Apple.testAp.
According to #iCaramba's answer. I've found a workaround:
Stop the task to kill the app (if you are already running the app)
Launch the app on your device manually. DO NOT use Xcode
Use Xcode to re-launch the app

Access the settings.bundle from today-extension

In the app I can choose in the settings which language of three should be used. If nothing is selected, the iPhone language is detected and selected for english, french or german. If none of this languages is the iPhone language, english is set to be used. Manually changing the language in the settings works as it should. Now I added a today-extension which works nearly well but I need to access the settings-bundle to get the NSUserDefaults for the languages (if manually changed). In both targets I activated the App-Groups with
group.com.companyname.appname
and selected it.
In the app I get the language with
NSString *manualLanguageSet = [[NSUserDefaults standardUserDefaults] valueForKey:SPRACHWAHL];
and in the today-extension I try to get it by:
NSString *manualLanguageSet = [[[NSUserDefaults alloc] initWithSuiteName:#"group.com.companyname.appname"] valueForKey:SPRACHWAHL];
For NSLog(#"Settings-Sprache: %#", manualLanguageSet); when running the today-extension the result is (doesn't matter if and which language is selected in the settings)
2014-09-13 16:48:36.331 HdB today[3734:284836] Settings-Sprache: (null)
What can I do it correct / how can I access to the settings (settings.bundle)?
If you create a WatchKit preferences bundle, it also contains the key
ApplicationGroupContainerIdentifier
at the root level of dictionary of the bundle's Root.plist, with the value being the group identifier (what you provide to NSUserDefaults as suiteName).
I found that you can also use this key in the iOS settings bundle. If added, preferences will go to the respective container.
I verified this to work on iOS 8.3 across the iOS Settings app, the iPhone app and the WatchKit extension.
UPDATE: Apple lists this key as supported in iOS 8.2 and later at
https://developer.apple.com/library/ios/documentation/PreferenceSettings/Conceptual/SettingsApplicationSchemaReference/Articles/RootContent.html
I'm searching for it as well. The only way i know how to do it is via SharedContainer. In your example you should open your
[[[NSUserDefaults alloc] initWithSuiteName:#"group.com.companyname.appname"] valueForKey:SPRACHWAHL];
in container app and then copy the language value from NSUserDefaults of container app like this :
[[[NSUserDefaults alloc] initWithSuiteName:#"group.com.companyname.appname"] setObject:[NSUserDesaults standardUserDefaults] objectForKey:SPRACHWAHL] forKEY:#"Your Key in extension"]];
then you will be able to access your shared container in you extension and get those values.
If someone have a better way of doing it i would be happy to know as well.

iOS Keychain SecItemAdd returns -25243

I'm working on updating an iPhone application with a minor change in its default configuration. It's been awhile since I've built it last, though, and so I've upgraded Xcode to 4.2 and included iOS 5 support in the latest builds.
When I go to test on the device, I get the following assertion error:
2011-11-02 20:57:18.869 RoseBandwidth[903:707] Tried to add item, got result: -25243
2011-11-02 20:57:18.870 RoseBandwidth[903:707] *** Assertion failure in -[KeychainItemWrapper writeToKeychain], /Users/tim/code/RoseBandwidth/Classes/KeychainItemWrapper.m:312
2011-11-02 20:57:18.872 RoseBandwidth[903:707] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Couldn't add the Keychain Item.'
I'm using the implementation of the KeychainItemWrapper class from Apple's GenericKeychain project. It's worth noting that this error only shows up on the device, not in the Simulator (and I'm aware of the access group restriction differences between platforms, but usually I thought that caused problems on the Simulator, not actual hardware).
Why would I be getting this error back? I've touched nothing relevant to the keychain-related parts of the app; it stores and retrieves data exactly like it used to.
Okay, I couldn't quite get your project to build, but from How to share keychain data between iOS applications I think you might want to check your entitlements file. At least in the github project you didn't have anything specified in the Keychain Access Groups.
For future searchers who happen to end up here, another possible cause of the -25243 error (which means No access control, BTW) is running on the simulator.
My best theory is the app's provisioning profile (or the signature thereof) is how the app knows what its bundle seed is. And the bundle seed needs to be part of the your keychain's access group name. But apps run on the simulator don't get signed, and so have a missing (or different?) bundle seed than you specified keychain-access-group.
Or something. It's all so poorly documented, it's hard to tell what's what. Just try running it on a device and see if that helps.
For those of you getting this error and trying to achieve "Shared Key Chain Access" between two apps:
You need to create an App Id for your app with same Team Id you selected when you first activated "Shared Keychain Access" in 'Capabilities'. Create your App Id in here:
Apple Member Center
After that you need to create provisioning profile from that App Id and download it to your computer.(Double click it to install to x-code)
I assume you already know you need "App ID Prefix" to access key chain, but for those who don't know:
"App ID Prefix" is unique text identifier associated with your Apple developer account:
To access "SharedKeychain" you need to implement it like this before you try to write or read from keychain
keychainAccessGroupName = "AB123CDE45.myKeyChainGroup":
You can check out this tutorial for further info:Share Keychain between iOS apps.
Hope that helps.
I get the same error from time to time in the simulator even if I did not touch the code. A reset of the simulator solves the problem for me.
See this question/answer how to reset the simulator: https://stackoverflow.com/a/3442326
As others have pointed out, in device builds error -25243 is often caused by trying to access a keychain access group that you don't have permissions for. (It's missing from your Entitlements.plist file or your provisioning profile.)
But in the simulator there can be another cause. The simulator doesn't support keychain access groups at all, so if you set the kSecAttrAccessGroup property on a keychain item and try to write it you'll get this -25243 error code.
FYI, Apple's GenericKeychain sample code has this comment:
// Ignore the access group if running on the iPhone simulator.
//
// Apps that are built for the simulator aren't signed, so there's no keychain access group
// for the simulator to check. This means that all apps can see all keychain items when run
// on the simulator.
//
// If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
// simulator will return -25243 (errSecNoAccessForItem).
This worked for me when I used a production certificate and provisioning profile. Using debug did not work.
In my experience, I get that return value -25243 when I realized that I was trying to pass kSecMatchLimit with kSecMatchLimitOne and kSecReturnData with kCFBooleanTrue values to the SecItemAdd() function. I removed those and double checked the app ids and provisioning profiles and everything is good.
I am not sure if this is helpful or not, but in my experience if you will use SecItemAdd() function for shared keychain access, those two parameters must not be there.

Resources