Initiate Parent iOS App Service Call from Today Widget Extension - ios

I am working on a POC iOS application that will eventually be released through an internal enterprise MDM solution. The app itself is pretty straightforward. It makes a quick call to an internal endpoint to return some simple json and then displays it on screen. At the same time, I have an app extension (Today Widget) displaying a small fraction of that data as well.
I have created a shared framework that includes the service calls, as well as any other common code I am using. Unfortunately, the parent app and extension all work perfectly fine if I'm on the internal network where the service endpoints live. However, this app will not always be on our trusted, internal network. As a result, we wrap the build with a secure container provided by our MDM solution and open up traffic to our specific internal endpoints. This works perfectly fine for the app, but our MDM provider doesn't currently provide similar capabilities for App Extensions.
As a result, I am working to come up with creative ways to best ensure the data in my Today Widget is up to date without it directly making a service call. To do so, I am sharing data between the app and extension via an app group, but if the service call is only made from the parent app and the user very rarely accesses the parent app, the data will still be out of date.
In order to simulate making the service call from the app extension to update the data, I would like a way to call the service on behalf of the parent app, which would then update the NSUserDefaults data being shared between app and extension.
So my question: What is the best way for me to initiate that service call in the parent app? Is it even possible? I know Apple provides the 'openURL' method to allow an extension to open it's parent app, but I don't want to actually open the app. I want the app to be running in the background while the extension makes the service call on it's behalf.
I have been looking into the following, but with not much luck:
Parent app has an observer on NSUserDefaults, watching a specific key, that when modified by the app extension will fire off the service call to update the shared data being displayed. Unfortunately, I don't believe this will work, since as long as the parent app is in the background, the NSUserDefaultsDidChangeNotification will not get fired off in the parent app.
Send a local notification from app extension to parent app, telling it to fire off the service call and update data shared via app group. Unfortunately, UIApplication.sharedApplication() is not accessible from an app extension.
Any suggestions of ways to simulate the service call, to give my Today Widget the highest likelihood of being up-to-date with it's information?
Note: Obviously giving Today Widgets access to internal resources has it's own security concerns, but for this POC, the data is non-sensitive and must only live internally..

Related

Make API call from message filter extension on iOS

I'm working on a message filter extension for iOS and I am kind of stuck. I would like to make an API call inside the extension class that is responsible with filtering the received messages but so far it's not working. I can use exactly the same code inside the ViewController class and everything is working fine.
So my question is: is it possible to make an API call from a message filter extension? (if it is, is there some kind of special setup that I am missing?)
According to the documentation it is not possible to make any network calls inside the extension, the system should handle it and communicate with server associated with your app for you
For privacy reasons, the system handles all communication with your associated server; your Message Filter app extension can't access the network directly.
Also for privacy reasons, your app extension can't write data to containers shared with the containing app.
So to make the call to your server you should call deferQueryRequestToNetwork(completion:) on the ILMessageFilterExtensionContext instance
If your app extension can't make this determination by itself, it tells Messages to send the information about the message to a server associated with your app. Your server examines the message information and sends a response to Messages, which passes the response to your app extension.

How to trigger an event in an iOS app from a UNNotificationServiceExtension?

My app has an UNNotificationServiceExtension object that exists in a separate project, which handles the receipt and processing of notifications.
I'd like to be able to trigger an event in the main app under certain circumstances, whether the app is active or not. Is this possible? If so, what mechanism would I use to achieve this?
If not, I'm worried that I'll have to use the main app to poll a shared data source when it's activated and respond to the data it reads.
Hmm.. after a bit of googling I found this:
Using URL Schemes to Communicate with Apps
This will allow me to communicate between apps.

Possible to present UIViewController from another app?

This may seem overly ambitious, but I'm exploring the ability to present a view controller from one app in a separate app (both authored by me). I'm not talking about reusing a class, I'm referring to literally presenting a controller from another process over the foremost one.
I believe this is in the realm of XPC on macOS, and how share extensions currently work on iOS. Unfortunately I'm not looking for a share controller though.
Is this at all possible (even using private APIs if I have to)?
Because both apps are sandboxed by iOS, there is no way for either of them to locate and load (something from) the other. Extensions are the only way provided by Apple to have another app perform some action.
Using private APIs will not lift sandbox restrictions. With a jailbroken device, it would be possible to locate the other app. In that case -[NSBundle loadClassNamed:] would allow you to obtain and instantiate a class from a loaded (application) bundle, but it would still be controlled by the process that instantiated it.
So, no, what you ask is not realistically possible for apps that would be distributed to other users than yourself. If it's just for yourself, you might be able to get somewhere with a lot of work on creating, controlling and communicating between processes on jailbroken devices.
If you have your own server, then this is possible. Just have app1 send a trigger to your server, and then your server sends push notification to your app2. when user tap notification, it will open your app2 viewcontroller.

WKInterfaceTable pull to refresh

Is it possible to create pull to refresh action in WKInterfaceTable in watch os 2?
There is one question but its related to watch os 1.
WatchKit pull to refresh
Short Answer:
No, it's not possible.
Long Answer:
All WKInterface Objects are just proxy objects that allows you to send queries to real UI Object. So basically they are not treditional UI Objects.
Connections between real UIs and WKInterface objects are managed by watchOS. What if some WKInterfaceController got deactivated, the connections in it will be disconnected also. In this state, you can't send queries anymore.
You may know that there are two bundles for watch Apps, one takes storyboard and icons, the other one is extension bundle. With sand-box concept, your code(in extension) can't access UI(storyboard bundle sided) directly. The only way to interact is using Interface Builder outlets and sent action.
It(Remote-UI concepts) makes sense for watchOS1 since all the code runs on iPhone. However with some reason, WatchOS2 App also use same strategy. With this restriction, You can't write code that react user interaction to real UI Objects directly likes iOS apps. As I told earlier, You can use pre-defined sent action only.
Since Xcode Interface Builder doesn't provide sent action likes did scroll, You can't write code that react pull down.

UIApplication.sharedApplication().beginIgnoringInteractionEvents() on Apple Watch

I can not use
UIApplication.sharedApplication().beginIgnoringInteractionEvents()
in WatchKit Extension, I have error:
'sharedApplication()' is unavailable: Use view controller based solutions where appropriate instead.
Is there some alternative ?
The short answer is: No there isn't.
The long answer:
Please keep in mind that the extension is not executed on the watch but on your phone. So if you would call UIApplication.sharedApplication() it would return you the application of the extension on your phone, anyway! Everything you do inside your extension is stuff that manipulates the extension on your phone. The only exception from this are the WatchKit methods. And even they are basically calls that are converted into instructions that are send over bluetooth to tell the watch what to do. At no time you can write code that executes on the watch!
You have no control what so ever about what the watch does with the instructions you send to it. You are basically acting as a server talking to a client and you have no control over the client. You should send as little instructions as possible and once you send them, your task is done, the rest is up to the watch.
That being said, you should carefully plan your UI in a way that you do not need any calls that manipulate the event delivery. You should focus on simple 'if user taps x I do y' interaction.
Another thing to keep in mind is, that your extension can not communicate with your main iOS app. You can create a shared app group between your iOS app and your watch extension to share data between them, however you can not directly communicate with your app. If you want to use parts of your apps logic, extract the module in question into a framework (this has become very easy with Xcode 6) and use the framework in both, your app and your extension.

Resources