Share datas between two apps with iOS 8 App Groups (using NSUserDefaults)
Check out this thread on the Apple Developer Forums:
https://devforums.apple.com/message/977151#977151
I believe that both instances need to use the group ID (initializing with initWithSuiteName:) or else they are reading/writing to different user defaults sets.
So your Swift code would change to:
var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
userDefaults.setBool(true, forKey: "Bool")
userDefaults.synchronize()
Communicating and persisting data between apps with App Groups
Another benefit to App Groups is the ability to share a NSUserDefaults
database. This also works for App Extensions (notification center widgets, custom keyboards, etc).
Initialize your NSUserDefaults
object like this in all applications in the app group and they will share the database:
Objective-C:
[[NSUserDefaults alloc] initWithSuiteName:@"<group identifier>"];
Swift:
NSUserDefaults(suiteName: "<group identifier>")
Keep in mind everything from the [NSUserDefaults standardUserDefaults]
database for each application will not carry over into this database.
The documentation gives a correct example as well (As of Beta 3).
And don't forget to synchronize the database:
[yourDefaults synchronize];
App Groups Data Sharing Between Applications iOS
You can store shared data using App Groups, but I've only tried to do this with built in types.
If you're trying to store your own classes you may need to look at something like NSKeyedArchiver and NSCoding (maybe look here).
If you can find a way to use the built in types you can use App Groups as follows:
Sharing NSUserDefaults data between multiple apps
In order to have shared defaults between an app and an extension or between 2 apps you have to add an App Group in your settings using the following steps:
- In the Project Navigator click on the *.xcodeproj file (should be at the top).
- To the right of the Project Navigator look for Project and Targets. Under targets click on your primary target (should be the first thing under Targets).
- Towards the top, click on the Capabilities tab.
- In the App Groups section click the switch to the right to turn App Groups ON.
- Click on the + button and add an App Group named group.com.company.myApp.
- Go to the same place in your other apps and this group should now be available to select. Turn this group on for each app that will be using this shared data.
Note: If you go to the Apple Developer Portal (the Apple website that shows all of your Certificates, Identifiers, Devices and Provisioning Profiles) and go to Identifiers > App Groups you should see this new App Group.
To store data:
var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
userDefaults!.setObject("user12345", forKey: "userId")
userDefaults!.synchronize()
To retrieve data:
var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
if let testUserId = userDefaults?.objectForKey("userId") as? String {
print("User Id: \(testUserId)")
}
iOS 8 widget, sharing data between app groups forward and backward
The nil
problem occurs because you try to access application's storyboard from widget. It's not straightforward, since the containing app and widget extension are being kept in a separate bundles. So the [NSBundle mainBundle]
in step 2) is not the same bundle as the one in your app.
Possible solutions include:
including the app's
Main.storyboard
in extensions bundle either via adding it toCopy Bundle resources
list at widget's targetBuild Phases
tab or just adding widget target toMain.storyboard
list of Target Membershipmoving the code responsible for getting the messages from
MainController startGetMessages:
into a shared framework that will be accessible both from the app and the widget, preferably into a dedicated object.
The second one is way better. As a rule of thumb it's best to follow SOLID principles when doing the object-oriented programming, where S stands for single responsibility. It should not be a responsibility of view controller to provide the messages fetching system-wide. Creating a dedicated object that will have only one job - to get messages - and sharing it across the targets is a way to go.
Please consult the docs for the detailed explanation on how to create the shared framework: https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1
Sharing UserDefaults between extensions
You cannot use UserDefaults.standard
to share data between a host app and its app extension. You instead have to create a shared container with UserDefaults(suiteName:)
to share data.
Even though an app extension bundle is nested within its containing
app’s bundle, the running app extension and containing app have no
direct access to each other’s containers.To enable data sharing, use Xcode or the Developer portal to enable
app groups for the containing app and its contained app extensions.
Next, register the app group in the portal and specify the app group
to use in the containing app.After you enable app groups, an app extension and its containing app
can both use the NSUserDefaults API to share access to user
preferences. To enable this sharing, use the initWithSuiteName: method
to instantiate a new NSUserDefaults object, passing in the identifier
of the shared group.
For more, refer to: https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1
How to use App Groups: https://github.com/pgpt10/Today-Widget
Standard or SuiteName?
Use standard one for data that is only for Host App. Use suiteName for data that you want to share between Extension and Host App. Just don't persist the same data in both of them. Avoid data redundancy. Use both of them according to the context.
Can I share files/data through App Groups but in different developer accounts applications?
The answer is no.
If you create a provisioning profile with an app group my.app.group
and extract entitlements from it, you will see that the group is referenced as XXXXXXX.my.app.group
where XXXXXXX
is your developer ID, so on another account the group will be YYYYYYY.my.app.group
and it will be perceived as a different group by any device.
More info: App ID, Application Groups
Related Topics
How to Release an Mtaudioprocessingtap
Core Bluetooth State Preservation and Restoration Not Working, Can't Relaunch App into Background
Com.Facebook.Sdk Error 2 on iOS
Uipinchgesturerecognizer. Make Zoom in Location of Fingers, Not Only Center
How to Convert String to Unicode(Utf-8) String in Swift
Does iOS Calendar Support a Url Scheme
Arkit Session Paused and Not Resuming
How to Connect SQLite Database in iOS
Nsstrikethroughstyleattributename , How to Strike Out the String in iOS 10.3
Add a Text Overlay with Avmutablevideocomposition to a Specific Timerange
How to Get Assets.Xcassets File Names in an Array (Or Some Data Structure)
Locking Orientation Does Not Work on iPad iOS 8 Swift Xcode 6.2
How to Change Tint Color of Uialertcontroller
How to Customise Uislider Height
Make Swift Assume Degrees for Trigonometry Calculations
Switching from Xcode3 to Xcode4 - Can't Load Programs Onto Older Ipod Touch