Add buttons to dynamic notification interface - apple-push-notifications

I'm creating a custom dynamic notification to show the user. Once i receive this notification at didReceiveNotification function at NotificationController I set the interface outlets with the right data. My problem is that i did not realize how can i add a custom button above the default dismiss button, since the notification storyboard doesnt allow buttons insertion and Apple Documentation says that
Do not include buttons, switches, or other interactive controls.
But i saw a lot of watch applications that have their custom actions, as Messages and Facebook Messenger. There is any way to add custom actions to the dynamic interface at watchOS?

You simply cannot add buttons to Dynamic notification interfaces. If you try to do this, you will receive the error
Illegal Configuration: Buttons are not supported in Notification interfaces.
However, you can add system buttons to your notifications other than the Dismiss button. When setting up the categories for the notification center, you can specify custom UNNotificationActions to be added to your notification category.
var categories = Set<UNNotificationCategory>()
let myCategory = UNNotificationCategory(identifier: "MyCategory", actions: [/*your custom actions go here*/], intentIdentifiers: [], options: []) //set up the actions here
categories.insert(myCategory)
center.setNotificationCategories(categories)
Then you can handle the user interactions with these actions (which as displayed as normal buttons on your dynamic notification interface) in your the UNUserNotificationCenterDelegate method, userNotificationCenter(_:didReceive:withCompletionHandler:) like this:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
switch response.actionIdentifier {
case "Ok":
print("Ok action tapped")
case "Dismiss":
print("Dismiss action tapped")
default:
break
}
completionHandler()
}

Related

WKWebview: Handle the button click event from app

Can I handle the button click event of WKWebView from my app.
Simply I have opened a facebook login page in my WKWebView. Is it possible to handle the event of that login button from my app?
You can use the navigationDelegate of the WKWebView to listen to that action. The delegate method you should implement is:
Swift
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Swift.Void)
{
let request = navigationAction.request; // Inspect this request to see if it's from Facebook
let policy = WKNavigationActionPolicyAllow or WKNavigationActionPolicyCancel depending if you want the request to continue firing or not
decisionHandler( policy );
}
Objective-C
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSURLRequest *request = navigationAction.request; // Inspect this request to see if it's from Facebook
WKNavigationActionPolicy policy = WKNavigationActionPolicyAllow or WKNavigationActionPolicyCancel depending if you want the request to continue firing or not
decisionHandler( policy );
}

How do I reliably get windowDidBecomeMain and windowDidResignMain events?

I have a view controller in which I want to receive windowDidBecomeMain and windowDidResignMain events.
In viewWillApear() I set the window delegate to self.
view.window?.delegate = self
I have added an extension to my view controller that conforms to NSWindowDelegate and have implemented both methods in it thus:
extension CustomerListViewController: NSWindowDelegate
{
func windowDidBecomeMain(_ notification: Notification)
{
print("Customer list did become main")
}
func windowDidResignMain(_ notification: Notification)
{
print("Customer list did resign main")
}
}
This is not the initial window. It is opened via a menu item with a Window controller show segue.
When the window is first opened via the menu item, it does not receive windowDidBecomeMain.
When I click another window it does receive windowDidResignMain.
If I then click back into the newly opened window it does receive windowDidBecomeMain and will from that point on.
I suspect that I need to set my window delegate at a different point but don't have a clue where to do so, if that is the case.

Is there any way to disable dictation support of a UITextField?

So I'm working on a tvos app in swift and I was wondering if it's possible to disable dictation support for a custom UITextField. It doesn't really work well for it and I don't want the user to be able to do so
Did you try to use the textfield's keyboardType property? Maybe you can change the text input type, so the dictation function is automatically not shown.
Documentation: https://developer.apple.com/library/tvos/documentation/UIKit/Reference/UITextInputTraits_Protocol/index.html#//apple_ref/occ/intfp/UITextInputTraits/keyboardType
This is a Swift 4 solution based on #BadPirate's hack. It will trigger the initial bell sound stating that dictation started, but the dictation layout will never appear on the keyboard.
This will not hide the dictation button from your keyboard: for that the only option seems to be to use an email layout with UIKeyboardType.emailAddress.
In viewDidLoad of the view controller owning the UITextField for which you want to disable dictation:
// Track if the keyboard mode changed to discard dictation
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardModeChanged),
name: UITextInputMode.currentInputModeDidChangeNotification,
object: nil)
Then the custom callback:
#objc func keyboardModeChanged(notification: Notification) {
// Could use `Selector("identifier")` instead for idSelector but
// it would trigger a warning advising to use #selector instead
let idSelector = #selector(getter: UILayoutGuide.identifier)
// Check if the text input mode is dictation
guard
let textField = yourTextField as? UITextField
let mode = textField.textInputMode,
mode.responds(to: idSelector),
let id = mode.perform(idSelector)?.takeUnretainedValue() as? String,
id.contains("dictation") else {
return
}
// If the keyboard is in dictation mode, hide
// then show the keyboard without animations
// to display the initial generic keyboard
UIView.setAnimationsEnabled(false)
textField.resignFirstResponder()
textField.becomeFirstResponder()
UIView.setAnimationsEnabled(true)
// Do additional update here to inform your
// user that dictation is disabled
}

Swift 2 Is it possible to add a web link to an annotation callout?

I'm able to create pin's with their popup's as well as the info-light button to the right. And when tapped, the info button pops up an alert with some text and an "ok" button at the bottom. Is it now possible to add a link at the bottom of the text that will direct the user to a URL, saw wikkipedia for example in safari?
I've used the following called function to succesfully do so with a regular button in the mapview, but I can't figure out how to implement it the way I've stated above
#IBAction func webLink(sender: AnyObject) {
if let url = NSURL(string: "http://www.wikipedia.com") {
UIApplication.sharedApplication().openURL(url)
}
}

xcode tvos app exiting issue when overriding menu button

I am currently writing a tvOS app. I've been detecting and overriding the menu button with tapRecognizer to switch between storyboards and other functions. My issue is when I am on my home screen and press menu it does not exit the app. Instead it remembers the last function I used when overriding the menu button and performs that function. Any thoughts on how to clear the tapRecognizer? Or a function that will exit the app?
I'm overriding the menu button with
in Storyboard1
tapRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(home)];
tapRecognizer.allowedPressTypes = #[[NSNumber numberWithInteger:UIPressTypeMenu]];
[self.view addGestureRecognizer:tapRecognizer];
in my home subroutine I send the user back to my home page storyboard. But from then on the menu button will not exit the app but send me back to storyboard1.
thanks,
SW
Instead of using your own gesture recognizer, override pressesBegan:
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
if(presses.first?.type == UIPressType.Menu) {
// handle event
} else {
// perform default action (in your case, exit)
super.pressesBegan(presses, withEvent: event)
}
}
If you are using UIGestureRecognizer instead of responding to presses, all you need to do is to disable the recognizer:
tapRecognizer.enabled = NO;
So if no recognizer with UIPressTypeMenu is listening, tvOS suspends the app and displays the home screen. (I've tested this)
You have to override 2 methods to prevent exiting app by pressing Menu button.
Here is ready-to-use template:
override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
for press in presses {
switch press.type {
case .Menu:
break
default:
super.pressesBegan(presses, withEvent: event)
}
}
}
override func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
for press in presses {
switch press.type {
case .Menu:
//Do some staff there!
self.menuButtonPressed()
default:
super.pressesEnded(presses, withEvent: event)
}
}
}
If you overwrite the menu button, the app won't be accepted:
EDIT: You can overwrite, but the menu button has to work as a back button to homescreen from the entry point of the app.
10.1 Details
The Menu button on the Siri Remote does not behave as expected in your
app.
Specifically, when the user launches the app and taps the Menu button
on the Siri remote, the app does not exit to the Apple TV Home screen.
Next Steps
Please revise your app to ensure that the Siri remote buttons behave
as expected and comply with the Apple TV Human Interface Guidelines.
It may be help you...
it is swift code.
let menuPressRecognizer = UITapGestureRecognizer()
menuPressRecognizer.addTarget(self, action: #selector(YourViewController.menuButtonAction(_:)))
menuPressRecognizer.allowedPressTypes = [NSNumber(integer: UIPressType.Menu.hashValue)]
self.view.addGestureRecognizer(menuPressRecognizer)
As per Apple's documentation, for custom press handling, we should override all four of these methods-
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
This is the official documentation from XCode:
Generally, all responders which do custom press handling should
override all four of these methods.
Your responder will receive either pressesEnded:withEvent or pressesCancelled:withEvent: for each
press it is handling (those presses it received in pressesBegan:withEvent:).
pressesChanged:withEvent: will be invoked for presses that provide
an analog value
(like thumbsticks or analog push buttons)
*** You must handle cancelled presses to ensure correct behavior in
your application. Failure to
do so is very likely to lead to incorrect behavior or crashes.
SwiftUI Seekers:
I don't know how much this answer helps, but just adding available actions in SwiftUI.
YourAnyView
.onExitCommand(perform: {
print("onExitCommand")
})
.onMoveCommand { direction in
print("onMoveCommand", direction)
}
REF:
onmovecommand
onexitcommand

Resources