Pass data from TodayExtension to app - ios

Is it possible to pass data from a today extension to an app? (Even when its not currently running). I wish to pass an array of objects to the main app and instantiate a viewController based on the objects passed from the today extension. I know how to open the app from the extension just not to too sure how to send data to the app.
var arrayToBePassed: [MyDataSource]
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
var url = ""
if currentSort == .recent{
url = "ext://recent"
}else{
url = "ext://popular"
}
//HOW DO I PASS arrayToBePassed to my app?
let myAppUrl = NSURL(string: url)!
extensionContext?.openURL(myAppUrl, completionHandler: { (success) in
if (!success) {
}else{
}
})
}

There's a few routes you could go down:
• In your app, implement a URL scheme that can quite literally take that array of objects, formatted as some sort of URL parameter. e.g. myAwesomeApp://objectArray=[these, are, strings]. You'll have to parse that URL yourself which should be a bit of fun.
• Look into NSUserDefaults. You can initialise a 'shared' user defaults object that both your app and your today extension can use, see here for more info. You could then store your array in here, and access it from the app when opened.
It really depends on what you're trying to do, but from the impression I get, I feel like the first option may be the best answer. I haven't provided any code, just an outline of how I'd go about it - but hopefully that should be enough to get you off to a good start.

Sharing of data is achieved through a new concept called “App Groups”. App Groups are allowed to share some data, including files, but it is worth noting that file access needs to be marshalled to avoid concurrent writes and so forth. This can be achieved through NSFileCoordination, but CoreData and NSUserDefaults handle this out of the box.
You can find the detial Steps here

Related

Swift iOS check if a file has been downloaded from json

I have an app that displays and plays a list of podcasts that is fetched from a json file, I would like to add a download feature but to do this I would like to only show a download icon if the podcast has not been downloaded already, is there a way that I can save something like the id element as well as the podcast title so I could then check to see if its been downloaded and saved on the phone already? Or is there an easier way? Obviously I would like to do this before the list is shown.
You can use UserDefaults for that.
Here's an example on how to read an array from UserDefaults
// Retrieves an array of strings from disk
func getDowloadedPodcasts() -> [String] {
UserDefaults.standard.array(forKey: "downloadedPodcasts") as? [String] ?? []
}
And here's an example on how to append a new value to an array on UserDefaults
func addDownloadedPodcast(podcastId: String) {
let downloadedPodcasts = getDowloadedPodcasts()
downloadedPodcasts.append(podcastId)
UserDefaults.standard.setValue(podcastId, forKey: "downloadedPodcasts")
}
Note that this functions alone won't solve your problem nor are the best solution of your problem, they are here jsut to show how easy it can be to work with UserDefaults and to read/write from non-volatile memory

Swift: How to change the language inside of the app?

I have an app with localized string files.
Here are what my localized string files look like.
I also have a tableView with cells containing accessoryType (check marks). I want to let the user change the language of my app when changing the check in the tableView.
Here are the codes I have in the tableView of the settings of the app:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.setValues(value: languageArray[indexPath.row]) // Upload new language settings to the server
// Here I want to set the language of my app to the selected value: languageArray[indexPath.row]
// For example, languageArray[indexPath.row] is "en"
var array = tableView.visibleCells
for i in 0 ..< array.count {
let cells: UITableViewCell = array[i]
cells.accessoryType = .none
}
let cell:UITableViewCell! = tableView.cellForRow(at: indexPath)
cell.accessoryType = .checkmark
}
Thanks!
As most of answer saying "this is not possible" but,
It is possible and can be done it by simple thing.
In iOS application there are bundle for each languages, like en.lproj for english. You just need to load that specific bundle from selected language and get localizable stuff like: string, images etc. from this bundle.
var selectedLanguage = "en"
let path = Bundle.main.path(forResource: selectedLanguage, ofType: "lproj")
let bundle = Bundle(path: path!)
let localizedText = bundle!.localizedString(forKey: YOUR_TEXT_KEY, value: YOUR_TEXT_COMMENT, table: nil)
For reference, i cerated an LanguageDemo app, you can found all implementation and complete source code.
There is a way to do it, but as the previous answers mentioned it's not the best idea and might no be approved by Apple app review. But here is what I've tried and it worked:
UserDefaults.standard.set(["en"], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()
Whenever the user select the language you need to apply this code, just replace ["en"] with your selected language. Keep in mind the user need to exit the app in order for this to work properly.
I know "this is not possible" answers are not really popular in Stack Overflow, but anyhow..
What you want to do is not possible. iOS doesn't allow you to change the language of the app from within the app. There is no API for that, and even if you somehow manage to achieve this thing by hacking (monkey patching) iOS, Apple wouldn't allow your app to be published to the itunes store.
There is a language setting within the "Settings" app (a system app), and there the user can set the language. All installed apps will use this language setting.
It is impossible to change the language of the iphone, but if you just want to change your app's language, I think there is the way: you can save the map as a plist or json file but the system .strings. And do not use the func NSLocalizedString, just encapsulation a func to get it, all the thing will be on the control.
This is so untrue about publishing etc, there is a way and you are not hacking anything, it is true there is not api for that but it is only a few lines of code, and it is nothing complicated... http://aplus.rs/2017/in-app-language-change-in-ios-app/
there is the link for your question, we have that o0n academy and this guy is our professor, if there is something you don't understand i am glad to help you with this because i got the same problem 2 years a go...

What is the purpose of `returningItems` in `NSExtensionContext.completeRequest`?

I'm working on a standard Action Extension in my iOS app and the Xcode template contains the lines:
#IBAction func done() {
// Return any edited content to the host app.
// This template doesn't do anything, so we just echo the passed in items.
self.extensionContext!.completeRequest(returningItems: self.extensionContext!.inputItems, completionHandler: nil)
}
Here is the documentation for completeRequest.
Questions
What is the purpose of passing returningItems to completeRequest?
Do apps actually receive edited content from an action extension?
If yes, where can I find the API on the receiving end?
What are the consequences for me to pass an empty array?
I made small research for other question, that may be found helpful here.
Shortly:
There is callback in UIActivityViewController with parameter:
returnedItems - An array of NSExtensionItem objects containing any modified data. Use the items in this array to get any changes made to the original data by an extension

Swift: Load JSON from a url and store in cache or file system

I am currently in the process of writing an iOS APP that downloads information from an API in JSON format then displays it in the app.
One of the key features to this app is it being able to work offline as well as online, for this reason there should be a cached version as well as an online version.
After reading through the internet to my shock I have not found any examples what so ever of this approach.
The only thing I have found that's even come close to this is HanekeSwift but the documentation seems incomplete and there is no way to clear the cache and i'm not even sure if this is a memory based cache or a filesystem based cache.
Since there is lots of ways out there to do this, core data, file system frameworks etc.. I'm not sure which one would be the best to go for, theoretically to break down my thought process all I need to do is:
Check if the JSON file exists on the system
If not download it from the network and store it for later use (Preferably as a string format)
If file exists load it into a swiftyJSON object
I feel like core data would be overkill, I feel like the file system way is dated as most of the filesystem cocoa pods/libraries don't seem to be compatible with the current swift version (2.3)
Can anyone share some light on what the generic standard way of doing this is or what option would be the most suitable for my purpose of use and why.
Kindest regards
SwiftifyJSON makes objects that support archiving.
Try this
class HSCache: NSObject {
static var defaults: NSUserDefaults = NSUserDefaults()
class func cacheThis(key: String, object : AnyObject) {
defaults.setObject(NSKeyedArchiver.archivedDataWithRootObject(object), forKey: key)
defaults.synchronize()
}
class func getFromCache(key: String, type : AnyClass) -> AnyClass? {
if defaults.objectForKey(key) != nil {
return NSKeyedUnarchiver.unarchiveObjectWithData(defaults.objectForKey(key) as! NSData) as? AnyClass
}
return nil
}
class func deleteFromCache(key: String) {
defaults.removeObjectForKey(key)
defaults.synchronize()
}
}

How to pass Core Data objectID and use it with Continuity

Just trying to update some Core Data apps with Continuity and have run into a bit of an issue with using the selected objects ID in the userInfo dictionary to display the correct data on the continuing device.
My first thought was to use the ObjectID, however on the receiving device this would never find a corresponding object in the Core Data store.
As it turns out the URL representation of the objectID contains the UUID of the store itself, and because the two stores UUID's are different this is obviously going to fail.
So I guess I could replace the Core Data store's UUID in the URL with the continuing devices UUID and use this, and no doubt it would work.
The Url seems to be of the following format
Does anyone know what the correct way would be to pass a reference to an object between two devices with core data stores that are synchronised via iCloud?
I'll answer this one myself and see if there are any better answers...
I pass the url of the objectID (from objectID.URIRepresentation) using Continuity API and on the receiving device create a new URL using the following:
url is the url passed in the NSUserActivity.userInfo dictionary
let storeUUID = self.identifierForStore()
// Switch the host component to be the local storeUUID
let newURL = NSURL(scheme: url.scheme!, host: storeUUID, path: url.path!)
func identifierForStore()->NSString? {
if let store = self.persistentStoreCoordinator?.persistentStores[0] as? NSPersistentStore {
return store.identifier
} else {
return nil
}
}
This seems to work just fine - hope it helps someone

Resources