Deep link into macOS app is not recognized - swift

I'm trying to implement a deep link into an macOS application, but nothing seems to work.
So far, my AppDelegate.swift contains the following
func application(app: NSApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
print("opened by link");
return true
}
I also configured the info.plist with URLSchemes beeing my bundle identifier and URLIdentifier beeing simply zst
In a simple html-file I use the following code to test the deep link
Test
My app gets opened (or becomes active when already running), but the print statement is not executed.
What am I doing wrong here?

Thanks to #Ssswift I found a solution.
Used this code:
How do you set your Cocoa application as the default web browser?
and converted it to swift with: https://objectivec2swift.com
works with Swift 3
in AppDelegate.swift added these lines
func applicationDidFinishLaunching(_ aNotification: Notification) {
var em = NSAppleEventManager.shared()
em.setEventHandler(self, andSelector: #selector(self.getUrl(_:withReplyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
}
func getUrl(_ event: NSAppleEventDescriptor, withReplyEvent replyEvent: NSAppleEventDescriptor) {
// Get the URL
var urlStr: String = event.paramDescriptor(forKeyword: keyDirectObject)!.stringValue!
print(urlStr);
}

Related

How to disable reopening documents when app started via launchIsDefaultUserInfoKey

On macOS unlike iOS, it appears if you want to disable reopening documents at launch, you need to rely on the application delegate notifications vs the newer methods - with an options argument, like on iOS:
applicationWillFinishLaunching(_:), here you want to instantiate your sub-classed document controller
// We need our own to reopen our "document" urls
_ = DocumentController.init()
applicationDidFinishLaunching(_:), here you want to inspect the supplied userInfo
if let info = note.userInfo{
if let launchURL = info[NSApplication.launchIsDefaultUserInfoKey] as? String {
Swift.print("launchIsDefaultUserInfoKey: notif \(launchURL)")
disableDocumentReOpening = launchURL.boolValue
}
if let notif = info[NSApplication.launchUserNotificationUserInfoKey] as? String {
Swift.print("applicationDidFinishLaunching: notif \(notif)")
disableDocumentReOpening = true
}
}
so when my document controller is called to do the doc restores, it would see this flag within the app delegate: var disableDocumentReOpening = false.
func restoreWindow(withIdentifier identifier: NSUserInterfaceItemIdentifier, state: NSCoder, completionHandler: #escaping (NSWindow?, Error?) -> Void) {
if (NSApp.delegate as! AppDelegate).disableDocumentReOpening {
completionHandler(nil, NSError.init(domain: NSCocoaErrorDomain, code: NSUserCancelledError, userInfo: nil) )
}
else
{
NSDocumentController.restoreWindow(withIdentifier: identifier, state: state, completionHandler: completionHandler)
}
}
but unfortunately, I have something wrong but what? Manually launching the app in debugger, it appears the document controller restore call is ahead of the app delegate's routine to inspect the userInfo.
I had read a SO post on this, showing an objective-c code snippet, but flag was local to the controller, but didn't understand how you could have a read/write class var - as I tried. Also didn't understand its use of a class function as doc says its an instance method, but trying that as well didn't work either.
What am I missing?

Support URL schemes in macOS application

There are several (old) questions on this subject, but none of the solutions worked for me, so here's the question:
How to add a URL scheme, so it will be possible to open my app via the browser?
I did the following:
Added the required info to the info.plist:
I Added those functions:
func applicationWillFinishLaunching(_ notification: Notification) {
NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(handleEvent(_:with:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
}
#objc func handleEvent(_ event: NSAppleEventDescriptor, with replyEvent: NSAppleEventDescriptor) {
NSLog("at handleEvent")
}
I also tried to add this function:
func application(_ application: NSApplication, open urls: [URL]) {
for url in urls {
NSLog("url:\(url)")
}
}
None of the above worked. I have a webpage that redirect with MyAppLogin://test but nothing happens. It doesn't matter if the app is open or closed (I want it to work in both cases)
Any idea what's the problem here?
Edit: Two more details:
The app is sandboxed
I'm running it via Xcode (so the installation is not at the 'Applications' folder)
One year later, this is how I made it work:
Add this to your AppDelegate:
func applicationWillFinishLaunching(_ notification: Notification) {
let appleEventManager: NSAppleEventManager = NSAppleEventManager.shared()
appleEventManager.setEventHandler(self, andSelector: #selector(handleGetURLEvent(_:withReplyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
}
Add this, to parse the URL and do whatever you want:
#objc func handleGetURLEvent(_ event: NSAppleEventDescriptor, withReplyEvent: NSAppleEventDescriptor) {
if let urlString = event.forKeyword(AEKeyword(keyDirectObject))?.stringValue {
let url = URL(string: urlString)
guard url != nil, let scheme = url!.scheme else {
//some error
return
}
if scheme.caseInsensitiveCompare("yourSchemeUrl") == .orderedSame {
//your code
}
}
}

snapkit login kit not working Swift Xcode 11.3.1

I am using Xcode 11.3.1 and try to login with snapchat with loginkit I add the add information in info.plist and my code is
SCSDKLoginClient.login(from: self, completion: { success, error in
if let error = error {
print(error.localizedDescription)
return
}
if success {
self.fetchSnapUserInfo() //example code
}
})
this code show me the login ui of snapchat and I am login into snapchat with my account.
but I am stuck on this ui
when I am click on continue nothing is happing . SCSDKLoginClient completion block not called.
Please ensure your URL scheme is configured correctly.
URL Schemes
hello everyOne soo finally i found the solution
i am using 11.3.1 and when i create new project the add
AppDelegate and SceneDelegate default class.
so according to snapchat logkit documentation i add
func application(_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return SCSDKLoginClient.application(app, open: url, options: options)
}
method in my Appdelegate class. but this method never get called in xocode 11.3.1
so the solution of my problem is this
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else {
return
}
SCSDKLoginClient.application( UIApplication.shared, open: url, options: nil)
}
you need to add this method into your sceneDelegate file. then everything work fine.
synpchat need to update there doc for new xcode 11.3.1. i hope this answer help you guy's because i also wast my 3 day's on this issue.
happy Coding :)

Swift Command Line Tool Not Receiving DistributedNotificationCenter Notifications

I am trying to create a very basic Swift command-line application that signals to another application using a WebSocket when the macOS UI changes to/from light/dark mode.
For some reason, the command-line tool is not receiving any notifications from DistributedNotificationCenter, in particular, AppleInterfaceThemeChangedNotification. However, running the exact same code in a Cocoa UI app on applicationDidFinishLaunching works perfectly fine.
I found an old Obj-C CLI project on Github that is meant to print out every notification, but that doesn't do anything either. It makes me suspect Apple perhaps changed something, but I cannot seem to find anything online about it. Are there certain Xcode project settings I need to set?
// main.swift
import Foundation
class DarkModeObserver {
func observe() {
print("Observing")
DistributedNotificationCenter.default.addObserver(
forName: Notification.Name("AppleInterfaceThemeChangedNotification"),
object: nil,
queue: nil,
using: self.interfaceModeChanged(notification:)
)
}
func interfaceModeChanged(notification: Notification) {
print("Notification", notification)
}
}
let observer = DarkModeObserver.init()
observer.observe()
RunLoop.main.run()
I managed to get iTunes notifications working, so it was just the theme change notifications that weren't working. Given this, I suspect Apple only sends the notifications to UI/NSApplication applications. As such, replacing the last 3 lines from above with the following works:
let app = NSApplication.shared
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
let observer = DarkModeObserver.init()
observer.observe()
}
}
let delegate = AppDelegate()
app.delegate = delegate
app.run()

application openURL in Swift

I am having an issue with the Appdelegate method OpenURL.
I have setup my Imported UTI's and Document Type. But when opening my app from a mail attachment, the app crashes immediately when I have the method implemented.
The depreciated handleOpenURL works, but not OpenURL?
At the moment I have no code in the implementation, and am just returning true.
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String, annotation: AnyObject?) -> Bool {
return true
}
The crash says Thread 1: EXC_BAD_ACCESS (code-1, address-0x0)
I don't really want to have to use the deprecated method.
I have my head blow for a week with this issue.
My app keep crashing after Login Using Social Media Such as Wechat / LinkedIn.But Facebook and Google Sign in Works Fine.
I have notice my app will keep crash after confirm sign in on Wechat Apps and will enter foreground.and Getting BAD EXCESS error. I have try to remove my application open url method on AppDelegate and the app wont crash but the action for Social Media Login are not functioning. so I detect that my issue was on the specific method. after search the web I found that im using an deprecated method of ApplicationOpenUrl as reference from https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623073-application
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return true
} // this method is deprecated in iOS 9 https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623073-application
notice that the deprecated version are using annotation:Any which will cause issue if you had bridging to an Obj-c framework such as wechat.
So what I do was, I swap my code into a the new format
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
let sourceApplication = options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String
let annotation = options[UIApplicationOpenURLOptionsKey.annotation]
let application = app
return true
}
Hope this help. it will became my reference in feature also. thanks StackOverflow
This is fairly typical of a signature mismatch between the method signatures automatically generated by the Swift compiler and the actual signature. It happens when you try to pass nil from Objective-C into a Swift explicitly unwrapped optional. Change the annotation parameter to be implicitly unwrapped and you should be gtg.
Swift 5 version of Muhammad Asyraf's answer:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
let sourceApplication = options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String
let annotation = options[UIApplication.OpenURLOptionsKey.annotation]
return true
}