How to Set Response Data into Todayextenstion Widget

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:
Main App

Today Widget Extension:

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



Leave a reply



Submit