I am using TwinPushSDK to receive notifications using Swift language.
http://developers.twinpush.com/developers/ios?class=sidebar-header#twinpush-sdk-library
Everything it's working fine but I need to receive the event when the notification is shown.
My AppDelegate extends TwinPushManagerDelegate and as it's explained in the document I have to implement showNotification
From SDK
Once you have that controller, you have to override the default behavior to stop TwinPush from showing the default viewer. To achieve it, simply implement the method showNotification, declared in TwinPushManagerDelegate, in your application delegate and show your view controller. For example:
This is My AppDelegate
class AppDelegate: UIResponder, UIApplicationDelate, TwinPushManagerDelegate{
....
....
....
// Swift
// MARK: TwinPushManagerDelegate
func showNotification(notification: TPNotification!) {
// Only show content viewer for rich notifications
doWhatever()
}
}
http://developers.twinpush.com/developers/ios?class=sidebar-header#custom-rich-notification-viewer
This is never fired and I need to control it, I can stop it inside the lib class but not in my delegate
am I missing something?
Thanks for any help
The automatic Swift signature generated from Objective-C now doesn't include parameter names in the method name, try with this signature:
func show(_ notification: TPNotification!) {
doWhatever()
}
XCode should be able to auto-complete with the correct signatures in case any other has changed.
Related
I am getting An unknown error occurred. when I tap on parameter which is dynamically provide in my shortcut inside Apples Shortcut app. And the handle(intent: TestIntent) async -> TestIntentResponse is not getting called.
Implemented the Handing protocol provided and generated by Xcode.
class SiriKitAppClosingIntentHandler: NSObject, LogAppClosingIntentHandling {
func provideAppOptionsCollection(for intent: LogAppClosingIntent, searchTerm: String?) async throws -> INObjectCollection<SiriKitIntentAppName> {
let appOptionsCollection = AppName.appOptionsCollection
if let searchTerm = searchTerm, !searchTerm.isEmpty {
return INObjectCollection(items: appOptionsCollection.filter({ $0.displayString.contains(searchTerm) }))
} else {
return INObjectCollection(items: appOptionsCollection)
}
}
func handle(intent: LogAppClosingIntent) async -> LogAppClosingIntentResponse {
print(" closing intent \(intent) \(#file) \(#line)")
return LogAppClosingIntentResponse(code: .success, userActivity: nil)
}
}
Main reason is not wiring up everything together correctly. Here are the brief intro and the check lists.
SiriKit needs a handler that conforms to the corresponding intent handling protocol.
Each intent object has an associated protocol based on the name of the intent. Ex: <IntentName>IntentHandling (Intent name: given in the SiriKit intent definition). And this protocol is created by Xcode (If you cant find it you need to build your app after you add one of your intent in the intent definition file)
The protocol defines the methods that your handler implements to resolve any intent parameters and to let SiriKit know how your app handled the intent.
There are two way that you can let Sirikit know your handler that you conform to <IntentName>IntentHandling protocol.
A. Provide a Handler in Your Intents App Extension - lightweight , so that is quick.
File -> New -> Target..
Make availabe intent for the extension.
Implement <IntentName>IntentHandling protocol
Return 3) implemented class in the handler method in the extension.
Make sure your intent is included in the plist file of the extension under IntentsSupported . (otherwise add <Name Of The Intent>Intent)
B. Provide a Handler in Your App - need to wakeup your whole app ( with all the import statements. so that it is slow)
Implement <IntentName>IntentHandling protocol
In an iOS app or an app built with Mac Catalyst, implement application(_:handlerFor:) on your UIApplicationDelegate.
If you’re using SwiftUI, use UIApplicationDelegateAdaptor
Make sure your intent is included in the plist file of the App under Intents eligible for in-app handling . (otherwise add <Name Of The Intent>Intent)
I'm trying to open url from messages embedded in an NSAttributedString. I'm using the latest version of MessageKit. I'm using the function didSelectURL, but it doesn't seem to reach that part of the code. I came across this solution, but I wanted to follow up with regards to how to set up MessageLabelDelegate. Just like in the linked solution, I have implemented the delegate methods detectorAttributes and enabledDetectors.
I currently have MessageLabelDelegate set up as an extension to my ViewController, but it never seems to reach those methods.
extension ChatViewController:MessageLabelDelegate {
func didSelectURL(_url: URL) {
// .. open URL
}
}
It seems to be getting overwritten by the method didTapMessage in the MessageCellDelegate extension. I tried going through the example code in the MessageKit repo, but still unclear as to how it's meant to be set up or what I'm doing wrong.
UPDATE: The problem was the way I was declaring the NSAttributedString. I was setting its value as a string instead of a URL.
The MessageCellDelegate implements the the MessageLabelDelegate so you need to make sure that the messagesCollectionView.messageCellDelegate is set to the ChatViewController and that the ChatViewController has an extension for MessageCellDelegate where you can put your didSelectURL
public protocol MessageCellDelegate: MessageLabelDelegate {
Navigation keeps on constantly rerouting after every route progress even though the user device location is on the same route. I thought Mapbox automatically handles rerouting only when the user leaves the current route. After I read this part of the documentation, I thought I needed to handle it manually.
Based on documentation, I used below code to handle rerouting manually but the code is deprecated.
func navigationViewController(_ navigationViewController: NavigationViewController, shouldRerouteFrom location: CLLocation) -> Bool {
return navigationViewController.routeController.userIsOnRoute(location)
}
So crash redirects me to this part of Mapbox SDK
#available(*, deprecated, renamed: "navigationService", message: "NavigationViewController no longer directly manages a RouteController. See MapboxNavigationService, which contains a protocol-bound reference to the RouteController, for more information.")
/// :nodoc: obsoleted
#objc public final var routeController: RouteController! {
get {
fatalError()
}
set {
fatalError()
}
}
but navigationService not containing userIsOnRoute function. Is there an alternative function I could use, or is this a bug?
This issue appears to be a bug. Base on #luugiathuy report if you just change SDK to below code if will fix everything, voice and rerouting problem
index 47d8132..bc44ed7 100644
--- a/ios/Pods/MapboxCoreNavigation/MapboxCoreNavigation/NavigationService.swift
+++b/ios/Pods/MapboxCoreNavigation/MapboxCoreNavigation/NavigationService.swift
## -127,7 +127,7 ## public protocol NavigationService: CLLocationManagerDelegate, RouterDataSo #objc(MBNavigationService)
public class MapboxNavigationService: NSObject, NavigationService, DefaultInterfaceFlag {
- typealias DefaultRouter = RouteController
+ typealias DefaultRouter = LegacyRouteController
/**
The default time interval before beginning simulation when the `.onPoorGPS` simulation
In MapboxNavigationService change RouteController to LegacyRouteController and everything will work as expected.
The issue is on for almost 4 months, modifying SDK is not good idea but this is and alternative solution until Mapbox fix this issue.
I want to toggle the voice directions in my iOS app between on and off. The HERE maps instructions (https://developer.here.com/mobile-sdks/documentation/ios-hybrid-plus/topics_api_nlp_hybrid_plus/protocolnmaaudiomanagerdelegate-p.html) are still all in objective-C. It is quite clear in that language how to do this, but I am looking for the Swift 3 equivalent. That manual says:
#optional (BOOL) audioManager:( NMAAudioManager *) audioManager shouldPlayOutput:( NMAAudioOutput *) output
Called when the audio manager has output to play.
If the delegate returns YES, or the delegate does not implement this
method, the output is played immediately. If the delegate returns NO,
the delegate takes over responsiblity for handling the output.
I am guessing something similar to this, but I can't get it right:
func audioManagerShouldPlayOutput(_ audioManager: NMAAudioManager!, shouldPlayOutput:false) {
}
This is the signature created using the XCode "Generated Interface" assistant editor, hopefully it is helpful! Looks like you are off just a little bit.
optional public func audioManager(_ audioManager: NMAAudioManager!, shouldPlay output: NMAAudioOutput!) -> Bool
I have a swift file "SomeController.swift" it is like this:
import Foundation
func performSomeStuff() {
println("Performing stuff")
}
Now in the app delegate, I am trying to do this: (note that the swift bridging header is imported)
[SomeController performSomeStuff]
But its not working.
I have also tried this:
import Foundation
class SomeController:NSObject {
class func performSomeStuff() {
println("Performing stuff")
}
}
But it still fails.
What is the correct way?
Add:
#objc
before the class keyword in your swift code so it will be:
#objc class SomeStuff: NSObject {
}
Also add #obj in front of any function that you want to call.
Then in your app delegate make sure to use #import "projectName-Swift.h"
Are you able to access "SomeController" class in objective-c, if not then you firstly need to add "${ProjectName}-Swift.h file and add Swift compilation support in Build settings as:
And for accessing methods from Swift to Objective-C, add
import Foundation
class SomeStuff:NSObject {
#objc class func performSomeStuff() {
println("Performing stuff")
}
}
before functions name.
In some cases, you need finer grained control over how your Swift API is exposed to Objective-C. You can use the #objc attribute if your Swift class doesn’t inherit from an Objective-C class, or if you want to change the name of a symbol in your interface as it’s exposed to Objective-C code.
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html
Ok, So I figured it out. First, here's the correct way. Its like some of you said:
In the swift file, I have it like this:
class MyController:NSObject{
class func performTask {
// Here my task is running.
}
}
Then in the app delegate, I just import the swift header file. And do this:
[MyController performTask];
Now for the part I had wrong. It was an error on my part, but maybe it'll be useful to someone else out there.
When I first created the first swift file, I had placed it inside a folder within the my Source folder. But when I started having multiple swift files, I moved the bridging header outside that folder and into the main Source folder (just for organising).
The problem was, it did not give me a direct error to tell me what was the problem. I had to check the issue navigator to identify the problem.
Hope this helps someone out there.