WidgetKit: deep-link from widget to macOS app - appkit

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?

Related

didDiscoverPeripheral is not called after upgrading from iOS 7 to iOS 8

I am calling scanForPeripheralsWithServices from didFinishLaunchingWithOptions callback of AppDelegate. The code looks like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSLog(#"didFinishLaunchingWithOptions");
// Override point for customization after application launch.
cm = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[cm scanForPeripheralsWithServices:nil
options:nil];
}
- (void) centralManager:(CBCentralManager*)central didDiscoverPeripheral:(CBPeripheral*)peripheral advertisementData:(NSDictionary*)advertisementData RSSI:(NSNumber*)RSSI{
NSLog(#"Did discover peripheral %#", peripheral.name);
[cm stopScan];
}
Before upgrading to iOS 8 everything was working well, however after the upgrade (exactly the same code, no single line was changed) I am not getting any error, but also didDiscoverPeripheral is not being called.
I appears that the major change which has occurred with Core Bluetooth in iOS 8 is that the BLE stack isn't powered on until you try to connect (or possible issue some other command).
CBCentralManager *cbCentralManager;
[cbCentralManager scanForPeripheralsWithServices:...];
This call used to issue a warning visible in the Xcode debug log saying that the central manager needed to be powered-up before it could be used. However, this warning was always a catch-22 — the only way to power-on the central manager was to send it a message, and the only way for it to process a message was for it to be powered-on.
Apple seems to have resolved this problem by handling power-on a bit differently. Now, after issuing the above command the central manager tells its delegate that its state changed via centralManagerDidUpdateState:.
We resolved the problem you describe by responding to centralManagerDidUpdateState: by re-issuing the scanForPeripherals... message.

Catch registered URL scheme and launch 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).

Cocoa Custom URL Scheme selector not called first time

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.

Refactor the Application Delegate

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.

Opening a url on launch

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

Resources