I am developing an application for OSX and have to handle custom URL handling in my application
Open My profile!
While Application is Running I am able to get event inside
- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent{
}
But when Application not running : it did Come to AppDidFinishedLaunching and i am not able to detect whether its invoked normally or by Custom URL ,
Is there any way to detect while App Launching ?
Thanks in advance
Instead of implementing -applicationDidFinishLaunching:, you should implement the more modern delegate method -application:didFinishLaunchingWithOptions:. You can then examine the launchOptions dictionary and look for the key UIApplicationLaunchOptionsURLKey. If you find that key in the dictionary, your app was launched in response to a custom URL. The URL itself is the value that corresponds to that key in the dictionary.
You can use the same method (looking for different keys, of course) to tell if your app was launched in response to a notifications, a location event, etc.
Related
I'm currently trying to set up a notification service using the old NSUserNotification API on macOSX (not iOS) in objective c++.
The catch is that I would need to know the system preferences associated with notifications that the user set (and preferably during the rest of runtime too) to determine if my notifications are actually seen. The application is meant to get the users attention in some way to guarantee things like reminders don't go unnoticed, so the thing I want to avoid is a notification delivered that silently doesn't produce any sound nor image on the screen whatsoever without the application knowing. If the notification is not allowed the application should handle it in some other way.
I am working on a macOS 10.14 Mojave machine. My overall code with NSUserNotificationCenter works fine with a custom Delegate that implements shouldDeliver, didActivate etc. Its just that I am currently assuming the user didn't press the "frick off" button on my notifications.
Unfortunately, NSUserNotificationCenter and related classes don't appear to feature a function that determines the permissions the way the new API (UNUserNotificationCenter) does. I have been trying to resolve this for a few hours so I was wondering if anyone else has found a solution to this. I can't really use the new API since this is strictly for back-compatibility in favour of the possibly rather prevalent amount of people who don't use mojave yet.
Things I have tried to make it work so far:
Try and see if there is a .plist somewhere where these settings are stored, in the User-specific Library folder as well as the general Library folder.
Try and find said .plist using CFPreferencesCopyKeyList and related methods. Apparently I don't really know the right domain name.
This answer from 2012 which appears to be outdated since I cannot locate the database on my machine anymore. Might be due to me using a mojave machine, or the file has since moved somewhere else.
Try and determine whether we can retro-actively check our permissions by checking a NSUserNotification's "presented" property on didDeliverNotification, shouldPresentNotification in the delegate. Unfortunately as stated in NSUserNotificationCenter itself it still behaves the same whether the preferences allow notifications or not.
Some code I tried includes the following:
CFPreferencesCopyKeyList((CFStringRef) #"com.apple.systemPreferences.plist", kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
CFPreferencesCopyKeyList((CFStringRef) #"com.apple.systemPreferences.plist", kCFPreferencesAnyUser, kCFPreferencesAnyHost);
//Unfortunately returns null with any combination of com.apple.notificationcenter.plist, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost
CFPreferencesCopyKeyList((CFStringRef) #"com.apple.notificationcenter", kCFPreferencesAnyUser, kCFPreferencesAnyHost);
On my system (only macOS High Sierra), it looks like the file you're after is:
~/Library/Preferences/com.apple.ncprefs.plist
That would correspond to a combination of kCFPreferencesCurrentUser, and kCFPreferencesAnyHost. (For the record, kCFPreferencesCurrentUser + kCFPreferencesCurrentHost equates to pref files in the ~/Library/Preferences/ByHost/ folder).
I don't think any settings would be stored in the local domain (by that I mean in the root /Library/Preferences/ folder).
I was able to get a list of apps and settings using the following code:
[[NSUserDefaults standardUserDefaults] addSuiteNamed:#"com.apple.ncprefs"];
NSArray *apps = [[NSUserDefaults standardUserDefaults] objectForKey:#"apps"];
NSLog(#"[%# %#] apps == %#", NSStringFromClass([self class]), NSStringFromSelector(_cmd), apps);
NOTE: this will not work if your app is sanboxed, as access to other pref files like that will be denied.
Is it possible using the web extensions API to get the default download folder for the current profile? I need to send it via native messaging to an external app.
I feel like https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/downloads should have it but it does't seem to.
Your best bet is probably making a dummy download and sending the "filename" property that you get back as a variable to your external app.
You would use the browser.downloads.onChanged event to get a reference to the filename value:
browser.downloads.onChanged.addListener(listener);
function listener(changed){
if(changed.filename != null){
// Do something
// Remove downloads.onChanged listener
browser.downloads.onChanged.removeListener(listener);
}
}
browser.downloads.download({url: dummyUrl});
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/downloads/onChanged
[1] When I select and right-click any text in any app, I get a Services menu where I can click to invoke any service like Search With Google.
After clicking, a NSPasteboard object is automatically sent to the service containing the selected text.
[2] 3rd party apps can use the BOOL NSPerformService ( NSString *itemName, NSPasteboard *pboard ) function to programatically invoke any service.
Here the app has to set the NSPasteboard object, which is sent to the service.
Is there a way to programatically invoke any service, but without setting the NSPasteboard object (the NSPasteboard object should automatically contain the selected text like in [1]) ?
How is the NSPasteboard object containing selected text sent to the service by OS X in [1]? Is there some private API?
This is documented in the Services Implementation Guide, in particular the Using Services chapter.
First, when the user opens the Services menu, Cocoa calls -validRequestorForSendType:returnType: on the objects in the responder chain to determine which combinations of send type and return type can be handled by which object, if any, based on its current state (e.g. the current selection). That controls which Services menu items are enabled.
When the user selects a service menu item, Cocoa creates a pasteboard and calls -writeSelectionToPasteboard:types: on the requestor object returned by -validRequestorForSendType:returnType:. That object should put the selection data on the provided pasteboard in whichever of the types it supports.
Cocoa then passes the pasteboard off to the system. The system communicates with Cocoa in the service provider process. Cocoa invokes -<messageName>:userData:error: on the service provider object in that process, where <messageName> comes from the description of the service in that app's Info.plist file. The service provider object is whatever the app registered with Cocoa using NSRegisterServicesProvider().
The service provider processes the input data, if any, from the pasteboard and stores the return data, if any, to it.
After the provider is done, Cocoa in the original app calls -readSelectionFromPasteboard: on the requestor object. Again, the pasteboard is provided to that method.
I'm working on an app for iphone where I load a JSON from a php server, parse it with a library and create an object with this data. My code works fine but the way I do it seems wrong to me:
A viewController shows to the user a loading view. Meanwhile the ViewController makes the get request and receive the data.
The VC parse the response and get a dictionary
The dictionary is send to a "creator class" who returns a object created from the dictionary
I do two times this operation but I think it's a bad design:
Should a View Controller do a http request? Don't shoud be a "objectLoader"? The main method of creation class makes a big bunch of if/else spaghettis, like:
for(NSString key in dictionary){
if(key isEqualToString "a key"){
perform action
}
else if(key isEqualToString "an other key"){
perform action
}
....
}
Any idea to solve that? I was thinking about make a dictionary of keys/selectors to solve it and do something like:
for(NSString key in dictionary){
[self performSelector:[selectors getObjectForKey:key]]
}
But I don't know if I can reference a selector in a dictionary...
Finally the other option that comes to me is send the parsed dictionary to the object with a class method like: [ClassName createObjectWithDictionary:parsedDictionary]. That's a good way to do it?
I know the question is a little ambiguous but I'm a little lost in what Design patterns I should apply and who is responsible of what in this story
the best way is to use MVC pattern and have model with data that has methods to push and remove some data inside it and a list of delegates (derived from UIViewController) which are notified in case of changed model data.
Controller (not UIViewController) is something that initiates fetching data from server and handles results.
And all of UIViewControllers handles data changes and user interaction.
For now, write some RequestController (singletone or not, doesn't matter) that handles request routines and stores all necessary data to trigger events in controller.
You can use blocks or NSNotificationCenter to handle request's completion.
After getting necessary data through RequestController from request, your Controller can create necessary parsers and push parsed data into model.
Personally, I would NOT let the ViewController do the HTTP request. I always write service classes in my apps, that do the low level stuff and inform the caller (e.g. a view controller) via delegation on any received result.
So the control flow in that case is:
-> ViewController locks screen with loading message
-> calls service with itself as delegate - the service does the work and receives the answer -> the answer is processed and the result passed to the delegate
-> the ViewController takes the response, removes the loading message and does whatever is necessary with the response.
Concerning your second question: yes, it is possible to dynamically chose a selector out of a dictionary - e.g. by storing the selector's name in the dictionary and then use
SEL selector = selectorFromString(#"doWork");
to create the right selector to call.
Is there any way to call App Expose in Lion programmatically, for example on an event tap, etc?
If you don't mind using a TOTALLY UNDOCUMENTED API, which might change at any point without notice:
void CoreDockSendNotification(CFStringRef, void *);
(...)
CoreDockSendNotification(#"com.apple.expose.front.awake", NULL);
Other known arguments are #"com.apple.expose.awake" and #"com.apple.dashboard.awake", which activate Mission Control and Dashboard, respectively. #"com.apple.showdesktop.awake" used to activate Show Desktop, but no longer works on current versions of macOS.
Note that most applications should not use these calls -- these actions are intended to be invoked directly by the user.
Expose does not exist in Lion, it has been merged with Spaces into the Mission Control application.
You can launch Mission Control:
[[NSWorkspace sharedWorkspace] launchApplication:#"Mission Control"];