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
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?
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
}
}
}
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 :)
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()
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
}