Move array from iPhone to AppleWatch programmatically - ios

I want to pass the data from iPhone to AppleWatch. It means I want to use the array data from iPhone to AppleWatch. So, how can I move or use NSMutableArray from iPhone to AppleWatch programmatically?.

Watch OS1:
You can use NSUserDefault for this purpose. You need to create an app-group for this. To find your app groups: in In your main app, select your project in the project navigator and then select your main app target and choose the capabilities tab and switch on app groups.
And then you could do like this:
var myArr: [NSString] = [NSString]()
myArr.append("First value")
myArr.append("Second value")
// Save
NSUserDefaults(suiteName: "group.myapp.test")!.setObject(myArr, forKey: "myArray")
NSUserDefaults(suiteName: "group.myapp.test")!.synchronize()
// Read
if let testArray : AnyObject? = NSUserDefaults(suiteName: "group.myapp.test")!.objectForKey("myArray") {
let readArray : [NSString] = testArray! as! [NSString]
}
Watch OS2:
If you want to save something from your phone to the NSUserDefaults on the Apple watch Target:
Use WatchConnectivity to send the data you want to save to the watch. Then when the watch receives the data you sent to it, save it to the Apple watch's default NSUserDefaults.
WCSession.defaultSession() will return the WCSession singleton for transfering data between your iOS and Watch app.
Here is a reference and guide for this.

Related

Transfer data from project to widget in swift

At my project i need to send user id's to widget in iOS. But for do that, my user needs to open application once. Without opening, information stays only 1 day, after that it vanishes and widget stops showing information and await for opening application.
For do that i used appGroup.
What is the correct way to use transfer data from my project to widget?
Swift 5
Follow these steps to pass data from the host app to extensions.
Select project target > Capabilities > add new app group (if you have enabled permissions for your developer account otherwise enable that first)
Select the extension target and repeat the same.
if let userDefaults = UserDefaults(suiteName: "group.com.yourAppgroup") {
createEventDic.removeAll()
let eventDic = NSMutableDictionary()
eventDic.setValue("YourString", forKey: "timeFontName")
createEventDic.append(eventDic)
let resultDic = try? NSKeyedArchiver.archivedData(withRootObject: createEventDic, requiringSecureCoding: false)
userDefaults.set(resultDic, forKey: "setWidget")
userDefaults.synchronize()
} else {
}
Now go to your app extension and do these steps to get the passed data.
if let userDefaults = UserDefaults(suiteName: "group.com.yourAppGroup") {
guard let testcreateEvent = userDefaults.object(forKey: "testcreateEvent") as? NSData else {
print("Data not found in UserDefaults")
return
}
do {
guard let eventsDicArray = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(testcreateEvent as Data) as? [NSMutableDictionary] else {
fatalError("loadWidgetDataArray - Can't get Array")
}
for eventDic in eventsDicArray {
let timeFontName = eventDic.object(forKey: "timeFontName") as? String ?? ""
}
} catch {
fatalError("loadWidgetDataArray - Can't encode data: \(error)")
}
}
Hopefully, it will help. Cheers!
For do that i used appGroup.
What is the correct way to use transfer data from my project to
widget?
What you did so far (App Grouping) is one of the steps that you should follow. Next, as mentioned in App Extension Programming Guide - Sharing Data with Your 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.
So, what you have to do so far is to let the data to be transferred by the UserDefautls. For instance:
if let userDefaults = UserDefaults(suiteName: "group.com.example.myapp") {
userDefaults.set(true, forKey: "myFlag")
}
thus you could pass it to the widget:
if let userDefaults = UserDefaults(suiteName: "group.com.example.myapp") {
let myFlag = userDefaults.bool(forKey: "myFlag")
}
And you follow the same approach for passing the data vise-versa (from the widget to the project).
In Xamarin Forms, we need to use DI to pass the data to the ios project then we can put it into NSUserDefaults
Info: Grouping application is mandatory
Xamarin iOS project - Putting Data into NSUserDefaults
var plist = new NSUserDefaults("group.com.test.poc", NSUserDefaultsType.SuiteName);
plist.SetBool(true, "isEnabled");
plist.Synchronize();
Today Extension - Getting data from NSUserDefaults
var plist = new NSUserDefaults("group.com.test.poc", NSUserDefaultsType.SuiteName);
var result = plist.BoolForKey("isEnabled");
Console.WriteLine($"The result of NSUserdefaults: logesh {result}");

Pass data to Call Directory Extension

I cannot pass data call directory extension from main app
I've created one App group and turned it on in App capabilities for both targets (main app and extension)
I pass data with NSUser
-Create Data in main app
var userDefaults = UserDefaults(suiteName: "group.test.callapp")
userDefaults?.set("mynumber", forKey: "mykey")
-Retrieve Data in extension
var baseDescription = "test"
let newUserDefaults = UserDefaults(suiteName: "group.test.callapp")
if let testUserId = newUserDefaults?.object(forKey: "mykey") as? String
{
baseDescription = testUserId
}
When i do it in only main app - everything is ok, but when i do it in extension (i do it in 'addIdentificationPhoneNumbers' function) - it doesn't work, baseDescripton doesn't change
Your solutions shoud work, the only problem I can see is that you don't have App Groups enabled (with your "group.test.callapp" group) both for your application and the extension. Check Target->Capabilities if this is enabled for both. Another caveat is to pass the phone number in the international format (with country code).

Cannot access NSUserDefaults using app groups one to another

I'm working on an app and a widget that the widget needs to get data from app. I've used the following codes to read and write on NSUserDefaults. And also I used $(PRODUCT_BUNDLE_IDENTIFIER).widget for widget and $(PRODUCT_BUNDLE_IDENTIFIER) referring to this post. But widget cannot get the data from app or NSUserDefaults. How can I make it work?
func addTask(name: String?) {
let key = "keyString"
tasks.append(name!)
let defaults = NSUserDefaults(suiteName: "group.Mins")
defaults?.setObject(tasks, forKey: key)
defaults?.synchronize()
}
///////
let defaults = NSUserDefaults(suiteName: "group.Mins")
let key = "keyString"
if let testArray : AnyObject = defaults?.objectForKey(key) {
let readArray : [String] = testArray as! [String]
timeTable = readArray
timeTable = timeTable.sort(<)
print("GOT IT")
print("timetable: \(timeTable)")
}
To read and save from the same set of NSUserDefaults you need to the the following:
In your main app, select your project in the project navigator.
Select your main app target and choose the capabilities tab.
Switch on App Groups (this will communicate with the developer portal, as it is generating a set of entitlements, and relevant App Id and so forth).
Create a new container. According to the help, it must start with “group.”, so give it a name like “group.myapp.test”.
Select your Today Extension target and repeat this process of switching on app groups. Don’t create a new one, rather select this newly created group to signify that the Today Extension is a member of the group.
Write to your NSUserDefaults:
// In this example I´m setting FirstLaunch value to true
NSUserDefaults(suiteName: "group.myapp.test")!.setBool(true, forKey: "FirstLaunch")
Read from NSUserDefaults:
// Getting the value from FirstLaunch
let firstLaunch = NSUserDefaults(suiteName: "group.myapp.test")!.boolForKey("FirstLaunch")
if !firstLaunch {
...
}
Swift 4.x:
Write:
UserDefaults(suiteName: "group.myapp.test")!.set(true, forKey: "FirstLaunch")
Read:
UserDefaults(suiteName: "group.myapp.test")!.bool(forKey: "FirstLaunch")

iOS 9 ShareData between AppGroup through NSUserDefaults

I'm trying to add TodayExtension to my existing app and I want that app and extension will share data through NSUserDefaults.
According to this tutorial http://www.glimsoft.com/06/28/ios-8-today-extension-tutorial/
I did like it say:
Create new target with Today extension
Add new App-Group in Extension and App
Add code to app
Add code to extension
App Code
func updateExtensionData() {
let key = "identityCode"
let valueForStore:Float = 2.0
let extensiontDefaults = NSUserDefaults(suiteName: "group.company.mineSharedDefaults")
extensiontDefaults?.setFloat(valueForStore, forKey: key)
let results = extensiontDefaults?.synchronize()
let checkCode = extensiontDefaults?.objectForKey(key)
print("code for save \(valueForStore) synchronize result \(results) readed code \(checkCode!)")
}
Extension code
private func updateData() {
let key = "identityCode"
let extensionDefaults = NSUserDefaults(suiteName: "group.company.mineSharedDefaults")
let checkCode = extensionDefaults?.floatForKey(key)
print("synchronize result \(resut) readed code \(checkCode!)")
}
Issue
My issue is that extension always read 0 instead of 2. Clearly I'm missing something. There is some major difference between iOS8 and 9 in case of AppGroup and NSUserDefaults? I know that there is but between app an watchOS2.
For being more clear this is keys from App and Extension NSUserDefaults
App Keys
AppleKeyboards
AppleKeyboardsExpanded
AddingEmojiKeybordHandled
AppleLanguages
ApplePasscodeKeyboards
PreferredLanguages
AppleLocale
NSInterfaceStyle
MSVLoggingMasterSwitchEnabledKey
NSLanguages
AppleITunesStoreItemKinds
identityCode
AppleLanguagesDidMigrate
PKEnableStockholmSettings
Extension Keys
AppleKeyboards
AppleKeyboardsExpanded
AddingEmojiKeybordHandled
AppleLanguages
ApplePasscodeKeyboards
PreferredLanguages
AppleLocale
NSInterfaceStyle
MSVLoggingMasterSwitchEnabledKey
NSLanguages
AppleITunesStoreItemKinds
AppleLanguagesDidMigrate
PKEnableStockholmSettings
It's clear that key identityCode is not appearing in extension at all.
Ok I'm not sure what helps but I've done two thing:
rename current AppGroup identifier and create new one with name group.my.entire.bundle.id.of.my.app.sharedData instead of group.appname.sharedData
remove and create new AppGroup identifier
I can use "identityCode" as key.
CThere could be several things!
first; did you allow keychain sharing under "Capabilities" for both your container app and the extension, and did you set the Keychain groups to the same group?
I recommend using this: https://github.com/kefbytes/KeychainWrapper
download it, it's very simple, just add the swiftfile to your project
allow keychain sharing under cabailities,
set your serviceName and accesgroup like this
KeychainWrapper.serviceName = "give it a name in here"
(servicename is neccessary for it to work)
KeychainWrapper.accessGroup = "write your accessgroup name here"
(accesgroup is optional, since you are setting it under Capabilities)
save a value to a key like this
KeychainWrapper.setString("2", forKey: "identityCode"
and retrieve with
KeychainWrapper.stringForKey("identityCode")

Sharing data between an iOS 8 share extension and main app

Recently, I've been making a simple iOS 8 share extension to understand how the system works. As Apple states in its App Extension Programming Guide:
By default, your containing app and its extensions have no direct access to each other’s containers.
Which means the extension and the containing app do not share data. But in the same page Apple brings a solution:
If you want your containing app and its extensions to be able to share data, use Xcode or the Developer portal to enable app groups for the app and its extensions. Next, register the app group in the portal and specify the app group to use in the containing app.
Then it becomes possible to use NSUserDefaults to share data between the containing app and the extension. This is exactly what I would like to do. But for some reason, it does not work.
In the same page, Apple suggests the standard defaults:
var defaults = NSUserDefaults.standardUserDefaults()
In a WWDC presentation (217), they suggest a common package:
var defaults = NSUserDefaults(suiteName: kDefaultsPackage)
Also, I enabled App Groups for both the containing app target and the extension target, with the same App Group name:
But all this setup is for nothing. I cannot retrieve the data I stored in the containing app, from the extension. It is like two targets are using completely different NSUserDefaults storages.
So,
Is there a solution for this method?
How can I share simple data between the containing app and the share extension? The data is just user credentials for an API.
You should use NSUserDefaults like this:
Save data:
objc
NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:#"group.yougroup"];
[shared setObject:object forKey:#"yourkey"];
[shared synchronize];
swift
let defaults = UserDefaults(suiteName: "group.yourgroup")
defaults?.set(5.9, forKey: "yourKey")
Read data:
objc
NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:#"group.yougroup"];
id value = [shared valueForKey:#"yourkey"];
NSLog(#"%#",value);
swift
let defaults = UserDefaults(suiteName: "group.yourgroup")
let x = defaults?.double(forKey: "yourKey")
print(x)
This will work fine!
Here is how I did it:
Open your main app target > Capabilities > App Groups set to on
Add a new app group and make sure it is ticked (e.g. group.com.seligmanventures.LightAlarmFree)
Open your watch target (the one with Capabilities tab) > App Groups set to on
Add a new app group and make sure it is ticked (e.g. group.com.seligmanventures.LightAlarmFree - but must be the same name as group above)
Save data to the group as follows:
var defaults = NSUserDefaults(suiteName: "group.com.seligmanventures.LightAlarmFree")
defaults?.setObject("It worked!", forKey: "alarmTime")
defaults?.synchronize()
Retrieve data from the group as follows:
var defaults = NSUserDefaults(suiteName: "group.com.seligmanventures.LightAlarmFree")
defaults?.synchronize()
// Check for null value before setting
if let restoredValue = defaults!.stringForKey("alarmTime") {
myLabel.setText(restoredValue)
}
else {
myLabel.setText("Cannot find value")
}
If you have
group.yourappgroup
use
var defaults = NSUserDefaults(suiteName: "yourappgroup")
This works for me
So apparently it works, only when the group name is used as the suite name for NSUserDefaults.
The documentation says NSUserDefaults.standartUserDefaults() should also work but it does not, and this is probably a bug.
In my scenario I'm sharing data between the parent iOS app and WatchKit. I'm using Xcode 6.3.1, iOS Deployment Target 8.3
var defaults = NSUserDefaults(suiteName: "group.yourappgroup.example")
In your viewDidLoad make sure you synchronize:
override func viewDidLoad() {
super.viewDidLoad()
defaults?.synchronize()
}
Example of a button sending text but of course you can pass whatever:
#IBAction func btnSend(sender: UIButton) {
var aNumber : Int = 0;
aNumber = aNumber + 1
//Pass anything with this line
defaults?.setObject("\(aNumber)", forKey: "userKey")
defaults?.synchronize()
}
Then on the other side make sure app group matches:
var defaults = NSUserDefaults(suiteName: "group.yourappgroup.example")
Then synchronize and cal: (In this case "lblNumber" is an IBOutlet label)
defaults?.synchronize()
var tempVar = defaults!.stringForKey("userKey")!;
lblNumber.setText(tempVar);
Then if you wanted to set something on this side and sync it back then just do the same thing and synchronize and just make sure the stringForKey that you call on the other side is the same:
defaults?.setObject("sending sample text", forKey: "sampleKey")
defaults?.synchronize()
Hope this makes sense
I translated in swift foogry's answer and it works!!
Save data:
let shared = NSUserDefaults(suiteName: "nameOfCreatedGroup")
shared("Saved String 1", forKey: "Key1")
shared("Saved String 2", forKey: "Key2")
Read data:
let shared = NSUserDefaults(suiteName: "nameOfCreatedGroup")!
valueToRead1 = shared("Key1") as? String
valueToRead2 = shared("Key2") as? String
println(valueToRead1) // Saved String 1
println(valueToRead2) // Saved String 2
You may share data by Following below steps:
1) Select your project -> Select Capabilities tab -> Enable App Groups -> Click on '+' -> paste your bundle Id after 'group.'
2) Select your Extension -> Select Capabilities tab -> Enable App Groups -> Click on '+' -> paste your bundle Id after 'group.'
3) Place below code in your main app for which data you want to share:
NSUserDefaults * appGroupData = [[NSUserDefaults alloc]initWithSuiteName:#"group.com.appname"];
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:[self allData]]; // Get my array which I need to share
[appGroupData setObject:data forKey:#"Data"];
[appGroupData synchronize];
4) You may get object in extension:
NSUserDefaults * appGroupData = [[NSUserDefaults alloc] initWithSuiteName:#"group.com.appname"];
NSData * data = [appGroupData dataForKey:#"Data"];
NSArray * arrReceivedData = [NSKeyedUnarchiver unarchiveObjectWithData:data];
You should use NSUserDefaults like this following and make sure
you must have enabled app group in your provisional profile and app group must configure as a green symbol and it should add to your provisional profile & BundleID.
NSUserDefaults *sharedUserDefault = [[NSUserDefaults alloc] initWithSuiteName:#"group.yougroup"];
[sharedUserDefault setObject:object forKey:#"yourkey"];
[sharedUserDefault synchronize];
NSUserDefaults *sharedUserDefault = [[NSUserDefaults alloc] initWithSuiteName:#"group.yougroup"];
sharedUserDefault value = [sharedUserDefault valueForKey:#"yourkey"];

Resources