I am developing a Mac application which registers a custom URL scheme. The application launches but my selector method is not being called so I am not able to parse the URL. After the application is launched, subsequent URL scheme calls result in a call to the selector method.
I had the
[NSAppleEventManager sharedAppleEventManager] setEventHandler:self
andSelector:#selector(getUrl:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
on AppDelegate applicationDidFinishLaunching and now moved it to the init method without any result.
Any ideas on how to solve it?
Actually, moving the event handler registration to the init method did the trick. In my case the URL was launching the XCode archived application instead of the newly archived one.
Related
I am adopting my iOS widget to my Mac app, and one thing I can't figure out is when I do a deep-link from the widget to the Mac app, where would that get detected? On iOS, it calls:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
But I can't find any equivalent method in the NSApplicationDelegate. The closest method is
- (void)application: (NSApplication *)application openURLs:(nonnull NSArray<NSURL *> *)urls
But this doesn't get invoked from the widget's Link.
Is there some other way to handle this on macOS? Do I need to configure something in particular for the openURLs method to be called?
EDIT:
After more testing, I've realized that the application: openURLs method should be called, whether through the widget Link or directly called using the URL scheme (as defined in the Info.plist). I verified this with another test app as well, where I can use [[NSWorkspace sharedWorkspace] openURL: testURL] to open the test app and the application: openURLs DOES get called. But it's not working for my main app for some reason, even though I've followed the same steps and defined the URL scheme in CFBundleURLTypes in the Info.plist file. The main app was created many years ago, whereas the test app was created just today.
Any ideas why the openURLs method isn't getting called in my main app?
I managed to launch my application whenever a URL scheme is called via the browser, by putting this scheme in the info.plist and adding these 2 lines:
NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
[appleEventManager setEventHandler:self andSelector:#selector(getUrl:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
and correctly implementing my getUrl function.
So I tried putting the two lines above in my appDelegates's applicationWillFinishLaunching, applicationDidFinishLaunching and init. But in the three cases, I have the same scenario: if my app is already running, then the getUrl function is correctly called, by if the app is not launched, then getUrl is never called.
I found on other posts (How to handle with a default URL scheme and get url event on app open in objective c (Mac OSX)) but the suggestion which comes often is using the applicationWillFinishLaunching, which didn't work in my case.
Edit: here is my info.plist: http://pastebin.com/yM8zabvY
I'm not sure where things are going sour for you. I've set up a test project, in which I just pasted the CFBundleURLTypes key from your Info.plist, and I used this in my app delegate:
-(void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor*)reply
{
NSLog(#"%#", event);
}
-(void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
// Register ourselves as a URL handler for this URL
[[NSAppleEventManager sharedAppleEventManager]
setEventHandler:self
andSelector:#selector(getUrl:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
}
And it works just like I'd expect. I get the log message regardless of whether the app was already running or not when I run open "feed://test" in the terminal.
Have you verified that your app is the default handler for the feed: scheme?
You can inspect the system's URL schemes using RCDefaultApp or the Launch Services API (LSCopyDefaultHandlerForURLScheme).
I am working on a Cocoa WebView based browser application.
Basically, I would like to have it so when the user navigates to a url, for example:
http://a/b.php, by clicking on a link on the previous page of a website, my application intercepts the "on navigate" event and changes the URL to http://a/b.php?enableapi=1
Any ideas??
Thanks in advance.
You need to assign an object as the web view's WebPolicyDelegate and implement the webView:decidePolicyForNavigationAction:request:frame:decisionListener: method.
In that method, you must call one of the WebPolicyDecisionListener protocol methods on the object that is passed as the decisionlistener parameter to the method. The three WebPolicyDecisionListener protocol methods are ignore, use or download.
You can then pass ignore to the listener and handle the link some other way for those links you're interested in intercepting.
I am a beginner to Obj-C and Xcode 4 and I am currently going through the "Your First Mac Application" on the Mac Dev website. I have managed to get through the main part but I'm struggling on the "Refactor the Application Delegate" section.
I have created a new class (to use as a controller), added an object set to this new class, made the connections from the class to the slider, mute button and textfield, and I have connected the new class object to the app delegate interface file.
Unfortunately an instance of the track class is never created, and therefore the program doesn't work, as the awakeFromNib function never gets called. I have tried placing it in both the app delegate file and the new controller class.
Where am I going wrong???
You have to either create an instance of your new class in IB, or you need to create it programmatically in your AppDelegate object (usually in init or awakeFromNib). You need to have a pointer to that object in your AppDelegate. If you create the new object in IB, you connect it to the Track* pointer in IB. If you do it in code, it's something like:
in .h file:
TrackClass *track;
in .m file:
track = [[Track alloc] init];
Which did you do?
I had the same issue while trying out the tutorial and found out the problem was with my implementation of awakeFromNib
Wrong Code:
- (void)awakeFromNib:(NSNotification *)aNotification
Right Code
- (void)awakeFromNib
There should be no argument passing the implementation of awakeFromNib.
What method must I implement in my cocoa application’s delegate so that on launch, it’ll open a url? (http/https, in this case) I’ve already implemented the url schemes, I just need to know how I can get my application to open on a url notification.
Update: I’m sorry, I wasn’t very clear. My application IS a browser that support https/http urls, but can only open them when it’s already running. What can I do to implement support for open urls in my app on launch?
When an application finishes launching on OS X, NSApp (the global NSApplication instance for the program) sends its delegate the applicationDidFinishLaunching: message (via the notification system). You can implement that method in your delegate to handle the notification and open a browser window in response, using NSWorkspace. Something like the following would work:
// Your NSApp delegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:#"http://www.example.com/"]];
}
It's not a delegate method. You need to implement an Apple Event handler for the getURL event.
As luck would have it, this is exactly the case Apple uses to demonstrate implementing an Apple Event handler.
I already had implemented the getURL event, so that alone isn’t enough to get the application to open a url on launch. The trick is that the AppleEvent must be installed in applicationWillFinishLaunching: not applicationDidFinishLaunching:. Otherwise, the event isn’t sent at all because the app hasn’t registered it in time.
To implement a protocol handler that you can select (in Safari preferences, for example) as the "default browser" and which will launch in response to HTTP / HTTPS, you need to do a few things.
Add .scriptSuite and .scriptTerminology files to your project resources. These will tell Mac OS X that you'll be handling the GetURL command.
Add a CFBundleURLTypes key to your Info.plist file listing the "URL Schemes" that your app will handle.
Also in Info.plist, add the NSAppleScriptEnabled key with the value YES.
Add a new class to your application as a subclass of NSScriptCommand and implement the -(id)performDefaultImplementation selector. From within this function you will find the clicked URL in [self directParameter]. Pass this on to your app's URL handler!
For the full details check out the article:
http://www.xmldatabases.org/WK/blog/1154_Handling_URL_schemes_in_Cocoa.item