4

I am trying to create a Today Extension Widget which displays stored data in the widget.

Here's what I have done;

  • Added New Today Widget Target
  • Set up UIViewController for widget
  • Enable App Groups for both the app and extension

Now I have hit a road block, I am unsure the best way to retrieve and display a simple array of fetched data.

There is very little Swift tutorials and they often do not use core data.

In the main app project I fetch the array.

 let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
 let request = NSFetchRequest(entityName: "Objects")
    do {
      try
      self.objectsArray = moc.executeFetchRequest(request) as! [Objects]
    } catch {

    }

How can I use NSUserDefaults to store the objects array and then use in the today widget extension ? Or Even an array of string values.

RileyDev
  • 2,950
  • 3
  • 26
  • 61
  • You can access your Core Data model within Widget: [How to access Core Data model in Today Extension](http://stackoverflow.com/questions/25407428/how-to-access-coredata-model-in-today-extension-ios) – Sasha Kozachuk Mar 11 '16 at 22:49
  • @SashaKozachuk That may work but it is in Objective-C – RileyDev Mar 11 '16 at 23:16
  • var containerPath: String = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier(YOUR_SECURITY_APP_GROUP).path var sqlitePath: String = "\(containerPath)/\("database.sqlite")" – Sasha Kozachuk Mar 11 '16 at 23:18
  • http://stackoverflow.com/questions/32652795/sharing-data-in-between-apps-in-ios/32653801?s=1|0.7540#32653801 – Leo Dabus Mar 11 '16 at 23:35

2 Answers2

2

1) Get url to your database

var containerPath: String = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier‌​(YOUR_SECURITY_APP_GROUP).path 

var sqlitePath: String = "(containerPath)/("database.sqlite")"

2) Create Persistent Store Coordinator as you do in parent app.

3) Set it for your Managed Object context

context = NSManagedObjectContext()
context.persistentStoreCoordinator = coordinator

4) Retrieve objects as you do in your parent app

let moc = context
let request = NSFetchRequest(entityName: "Objects")
do {
  try self.objectsArray = moc.executeFetchRequest(request) as! [Objects]
} catch {}
Sasha Kozachuk
  • 1,283
  • 3
  • 14
  • 21
  • Thanks for your answer, I am experiencing an error `'Cannot create an SQL store with a nil URL.'` - I have posted it as a separate question. When I am able to fix that bug I will accept your answer http://stackoverflow.com/questions/35970725/cannot-create-an-sql-store-with-a-nil-url-today-widget-extension – RileyDev Mar 13 '16 at 15:01
  • @JKSDEV that is weird that URL is nil, did you check if database is under two targets? – Sasha Kozachuk Mar 13 '16 at 15:25
  • The reason I was getting nil is I used the bundle identifier not the Security app group. I got it all set up fine I without errors, however when fetching the objects the fetch request doesn't fetch anything. I have set the target memberships for the data model and the entities, is there something else I might be missing ? – RileyDev Mar 15 '16 at 17:23
0

If you set up the App Groups correct and added the same group for both Application and Extension you can use NSUserDefaults. Just for instance, to write something from the app, you need:

static func setSharedScoreNumber(score: Int) {
    let defaults = UserDefaults(suiteName: "group.bubblewrapSharedDefaults") // this is the name of the group we added in "App Groups"
    defaults?.set(String(score), forKey: "score")
    defaults?.synchronize()
}

And to read from Todays Extension:

private func getScore() -> String {
    let defaults = UserDefaults(suiteName: "group.bubblewrapSharedDefaults")
    defaults?.synchronize()
    return String(describing: defaults!.object(forKey: "score") ?? "0")
}

Here's the complete guide how to do so.

Mikita Manko
  • 1,133
  • 9
  • 9