iOS App Extension - Action - Custom Data

iOS App Extension - Action - Custom Data

Uniform Type Identifiers are indeed the correct way to do this.

I have not finished developing this, but I managed to get it minimally working. Basically you define a custom type like com.company.app.myThing and you can pass your custom object as a hash with whatever data structure you want. Obviously the consumer needs to know and follow this schema.

Here is the relevant portion of info.plist in the extension:

<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<string>SUBQUERY(extensionItems, $extensionItem, SUBQUERY($extensionItem.attachments, $attachment, ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.company.app.myThing").@count == 1).@count == 1</string>
<key>NSExtensionPointName</key>
<string>com.apple.ui-services</string>
<key>NSExtensionPointVersion</key>
<string>1.0</string>
</dict>

In the ActionViewController.viewDidLoad in the extension:

let item = self.extensionContext.inputItems[0] as NSExtensionItem
let provider = (item.attachments as Array<NSItemProvider>)[0] as NSItemProvider
provider.loadItemForTypeIdentifier("com.company.app.myThing", options: nil, completionHandler: { msg, error in
let my_thing = (msg as? NSDictionary) as Dictionary<String, AnyObject>
// do stuff with my_thing
})

Then in the host app:

let my_thing = [
"foo": "bar",
"baz": 123
]
let item = NSExtensionItem()
let attachment = NSItemProvider(item: my_thing, typeIdentifier: "com.company.app.myThing")
item.attachments = [attachment]
let activityViewController = UIActivityViewController(activityItems: [item], applicationActivities: nil)
self.presentViewController(activityViewController, animated: true, completion: actionComplete)

DISCLAIMER: Please do not consider this an authoritative how-to, but I hope it can point you in the right direction.

Share Data between Project and Share Extension

Your helper function getDataSourceArray() tries to access UserDefaults.standard which is not shared between your host app and the extension app. You need to use the shared container.

  • UserDefaults.standard -> not shared between host and extension
  • UserDefaults(suiteName:) -> shared between host and extension

Try to change your function to this:

func getDataSourceArray() - > [Wishlist] ? {
if let data = UserDefaults(suiteName: UserDefaults.Keys.groupKey).value(forKey: Keys.dataSourceKey) as ? Data {
if let dataSourceArray =
try ? PropertyListDecoder().decode(Array < Wishlist > .self, from: data) as[Wishlist] {
return dataSourceArray
}
}
return nil
}

Network request from share or action extension ios

You can use URLSession directly from the extension. There is a good tutorial at https://www.raywenderlich.com/158106/urlsession-tutorial-getting-started

let url = URL(...)
let dataTask = defaultSession.dataTask(with: url) { data, response, error in
if let error = error {

// Handle error (error.localizedDescription)
// ...

} else if let data = data,
let response = response as? HTTPURLResponse,
response.statusCode == 200 {

// Handle resonse data
// ...

DispatchQueue.main.async {
// Close extension
// ...
}
}
}

JavaScript won't help in this case. Just make a request to your url and handle the response.

Make iOS Action Extension get notified that the Host app became active

Answering my own question: there is at least one way to do it - using NotificationCenter, described in this answer to the "Why does viewWillAppear not get called..." question.

If someone has a better idea - I will be glad to experiment with it.



Related Topics



Leave a reply



Submit