[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.
Related
Apple's Accessibility Inspector tool displays the Objective-C class corresponding to the currently inspected UI Element. See NSButtonCell at the very bottom of this screenshot:
However, how can I extract this information in my own code? The accessibility methods in Apple's seven year old UIElementInspector sample code do not surface the element's class name.
Reverse engineering the Accessibility Inspector hinted that the Objective-C class name could be obtained via the AXClassName attribute, but that attribute is always nil for me.
AppKit limits access to the AXClassName attribute, and several other attributes, to applications that have the com.apple.private.accessibility.inspection entitlement. The XPC service that Accessibility Inspector uses to access accessibility information has this entitlement. Since this is a private entitlement, I believe it can only be added to applications signed by an Apple certificate.
You can confirm for yourself that the entitlement is key by stripping entitlements from the Accessibility Inspector's XPC service like so (make a back-up of Accessibility Inspector first!):
codesign -f -s - /Applications/Xcode.app/Contents/Applications/Accessibility\ Inspector.app/Contents/Frameworks/AccessibilityAuditDeviceManager.framework/XPCServices/axAuditService.xpc
If you then open Accessibility Inspector you'll see that most all of the functionality works correctly, except for things like the class name that are gated on the private entitlements.
Accessibility Inspector with entitled XPC service
Accessibility Inspector with unentitled XPC service
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.
How do you display the Oil/Water/Gas components of a BlackOil domain object programatically on the FunctionWindow? I tried calling FunctionWindow.ShowObject on BlackOil.OilPhase but received an error that it could not be found on the input tree.
I need to say sorry here, but this is the bad case when you can get an programmatically access to the object via FluidFunctionCollection (you can create/update it), but you cannot get access to the same object via InputTree interface (you will receive an UnknownEntity via GetType method when try to navigate from Petrel UI to this object type and send it to your plug-in (doesn't exposed for Ocean from this site yet)), and by this reason you cannot display this object programmatically. I submitted an internal ticket for your case.
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.
I have an array of filenames that i would like to pass to an external application for opening. I'd like to do one of the following:
a) Somehow instruct OSX to open all these files with an associated application, but it must invoke the target app's openFiles NSApplication delegate method
b) Specify the application to open these files with (and also invoke openFiles)
Basically it doesn't matter which solution to realise, because these files will be associated with the target application anyway. How would i do one of these things?
To open a whole bunch of files at once, send the shared NSWorkspace object an openURLs:withAppBundleIdentifier:options:additionalEventParamDescriptor:launchIdentifiers: message, or call the LSOpenURLsWithRole function or the LSOpenFromURLSpec function. Either way, you'll pass an array of URLs to items to open.
Each one of these will let you identify a specific application to use. NSWorkspace lets you specify it by bundle identifier, while the two Launch Services functions let you provide the URL or FSRef to a specific application bundle.
… it must invoke the target app's openFiles NSApplication delegate method
That isn't possible to require, because (a) the application may be document-based, in which case it probably does not have an NSApplication delegate and, even if it does, such a delegate would probably not respond to application:openFiles:, and (b) the application may not be Cocoa-based, in which case it would handle the Open Documents Apple Event directly. None of this is your application's business, so don't worry about it.
First add your video files to Resources Folder.The code like follow:
NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
NSString* videoPath = [bundlePath stringByAppendingPathComponent:#"/Contents/Resources/video.mov"];
[[NSWorkspace sharedWorkspace] openFile:videoPath];