How to set response data into TodayExtenstion widget
Hey as @LowKostKustomz explained, you need to activate app groups in both main app and extension. Then while saving from main app as well as extension, try something like
struct MarketIndexCache {
static let key = "MARKET_INDEX_KEY"
static let groupBundleID = <#you group identifier#>
static func save(_ value: [MarketIndex]!) {
let defaults = UserDefaults.init(suiteName: groupBundleID)
defaults?.set(try? PropertyListEncoder().encode(value), forKey: key)
}
static func get() -> [MarketIndex]! {
var marketIndex: [MarketIndex]!
if let data = defaults?.value(forKey: key) as? Data {
let defaults = UserDefaults.init(suiteName: groupBundleID)
marketIndex = try? PropertyListDecoder().decode([MarketIndex].self, from: data)
return marketIndex!
} else {
return marketIndex
}
}
static func remove() {
let defaults = UserDefaults.init(suiteName: groupBundleID)
defaults?.removeObject(forKey: key)
}
}
How to send and receive data in Today extensions
Apart from NSUserDefaults, you can use the NSNotificationCenter to send or receive data anywhere.
You need to set the observer where you can receive the data like below:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "dataReceived:", name: "SpecialKey", object: nil)
}
Funciton to catch data:
func dataReceived(notification: NSNotification) {
//deal with notification.userInfo
println(notification.userInfo)
println("Received Data")
}
And you need to define NSNotificationCenter from where you need to send the data:
NSNotificationCenter.defaultCenter().postNotificationName("SpecialKey", object: nil, userInfo: ["MyData": "Demo"])
References:
The complete guide to NSNotificationCenter
Hope it helps!
http://moreindirection.blogspot.in/2014/08/nsnotificationcenter-swift-and-blocks.html
How to convert an array of custom classes to Data?
First of all setup your Note class, must conform to the codable protocol:
class Note: Codable {
var text = "hi"
var date = Date()
init(t: String, d: Date) {
text = t
date = d
}
enum CodingKeys: String, CodingKey {
case text
case date
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
text = try container.decode(String.self, forKey: .text)
date = try container.decode(Date.self, forKey: .date)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(text, forKey: .text)
try container.encode(date, forKey: .date)
}
}
Then you can create your array of notes:
let arrayOfNotes: [Note] = [Note(t: "someNote", d: Date())]
And just save it in user defaults:
do {
let encoded = try JSONEncoder().encode(arrayOfNotes)
UserDefaults.standard.set(encoded, forKey: "SavedNotes")
} catch let error {
// catch any error if present
print(error)
}
to retrive your saved data you can simply use an if let or a do-catch like above:
if let savedData = UserDefaults.standard.value(forKey: "SavedNotes") as? Data {
if let notes = try? JSONDecoder().decode(Note.self, from: savedData) {
// do whatever you need
}
}
Shared UserDefaults between app and extension not working correctly
I would recommend to dig down step by step here.
First, make sure that both the main app and the widget extension have app group capability enabled and use the same and activated (the checkmark must be set) app group name:
Main App:
Today Widget Extension:
Then make a simple test with direct set/get access. In your main app's AppDelegate.didFinishLaunchingWithOptions
method (change the app group name and the keys to your needs):
if let userDefaults = UserDefaults(suiteName: "group.de.zisoft.GPS-Track") {
userDefaults.set("test 1" as AnyObject, forKey: "key1")
userDefaults.set("test 2" as AnyObject, forKey: "key2")
userDefaults.synchronize()
}
In your Today Widget Extension's ViewController:
if let userDefaults = UserDefaults(suiteName: "group.de.zisoft.GPS-Track") {
let value1 = userDefaults.string(forKey: "key1")
let value2 = userDefaults.string(forKey: "key2")
...
}
If this works, the problem must be related in your Preferences
singleton.
Crash when getting value from shared Userdefaults
When force unwrapping with !
you always run the risk of a crash if the value is nil (or with as!
if the cast fails).
In this case, you can do this:
let myString:String = UserDefaults(suiteName: "group.com.xxx.xxx.widgetsharing")?.string(forKey: "myKey") ?? "Default value"
Using string(forKey:)
avoids the need for the cast to String
and then the nil coalescing ??
lets you provide a default value if none is found in the UserDefaults
.
Cocoa Bindings, String value in Defaults bound to a Text Field. How can I programmatically read this string?
The fix was not to use NSKeyedUnarchiveFromData
as the value transformer on the binding (or any value transformer, at all).
When you use a value transformer, that makes the binding system transform the value from the view into some other value for the model to store and, when it retrieves a value from the model, to transform it to a value that the view can work with. In your case, a text field works naturally with string values and so does the user defaults system, so there's no need or benefit to transforming to/from data objects.
The main use for transforming via NSKeyedUnarchiveFromData
is for values of types that can't be directly stored in property lists, such as color objects.
Related Topics
Create Alert Function in All View Controllers - Swift
Extending a Delegate from a Base Class
Can't Change Uinavigationbar Prompt Color
Swift - Set Delegate for Singleton
Game Exits from Pause State After Resuming It from Background in Swift
Uitableviewcell with Intrinsic Height Based on Width
Saving an Image to Photos Library Using Swift 2.0
Swift 4: Timer Crashing - Unrecognized Selector Sent to Instance
How to Get a Substring from a Specific Character to the End of the String in Swift 4
A Simple Code to Detect Any Beacon in Swift
Dyld: Symbol Not Found: _Tmpdcss12Anygenerator
Uitraitcollection Clarification
Xcode 11 Archive Gives Phasescriptexecution Failed
Creating an Irregular Uibutton in Swift Where Transparent Parts Are Not Tappable
How to Add Two or More Buttons to Annotationview: Mkannotationview
iOS Swift Remove Uitableview Cell Separator Space