Can I use an application as a library (Mac, Objective-c)?
Is there a way to load classes from a mac app, and use开发者_如何学C them in a different mac app?
I'd like to make an Automator action that accesses some of the classes in my mac app, and this seems like the sort of way I'd ideally do it (means you have to have bought my app to use the Automator action, etc.)
Depending on what you want to do (I'm not quite clear), a Service might do the trick for you. You make a helper app which can pass data back and forth with your app, using a shared pasteboard. You can get a fairly wide range of action, because you can pass any object that conforms to the NSPasteboardWriting and NSPasteboardReading protocols; as it says there in the docs, NSString
, NSAttributedString
, NSURL
, NSColor
, NSSound
, and NSImage
are already available for you, and of course you can write a custom class that suits your needs exactly.
Have you tried creating a stand-alone Automator plugin project, or tried adding an Automator bundle target to your application's project?
I'm assuming that you want to create Automator actions for your main app, but are unclear how you get these actions to interact with your application (or with the classes present in your application).
There are 3 basic types of Automator actions: AppleScript-based, shell-script based, and Objective-C based. You'll most likely want to make yours Objective-C-based, which will allow you to easily incorporate other Objective-C code from your main application into the action itself (see Implementing an Objective-C Action). (Note that by default, when you add a new target for an automator bundle, it's an AMAppleScriptAction
type).
To see how an Objective-C automator action is set up compared to an AppleScript-based action, you might want to try creating a separate standalone project.
Let's say your app is document-based, and uses the KWDocument
class, which exposes a method named -duplicateObjects:(NSArray *)objects toDocument:(KWDocument *)destDocument;
. You also have a KWRegistrationManager
that knows whether your app is registered or not. And let's say you want to create an automator action that's called "Duplicate Objects to Document". The action will be implemented in KWDuplicateObjectsToDocument
, which is as a subclass of AMBundleAction
. In the Info.plist for Duplicate Objects to Document.action, the NSPrincipalClass
will be KWDuplicateObjectsToDocument
.
KWDuplicateObjectsToDocument.h
will look something like:
#import <Cocoa/Cocoa.h>
#import <Automator/AMBundleAction.h>
@interface KWDuplicateObjectsToDocument : AMBundleAction {
}
- (id)runWithInput:(id)input fromAction:(AMAction *)anAction
error:(NSDictionary **)errorInfo;
@end
And your KWDuplicateObjectsToDocument.m
will look something like this:
#import "KWDuplicateObjectsToDocument.h"
#import "KWDocument.h"
#import "KWRegistrationManager.h"
@implementation KWDuplicateObjectsToDocument
- (id)runWithInput:(id)input fromAction:(AMAction *)anAction
error:(NSDictionary **)errorInfo {
if (![[KWRegistrationManager defaultManager] isRegistered]) {
return nil;
}
// eventually you'll call
// duplicateObjects:toDocument:
return input;
}
@end
You'll need to make sure that the necessary classes you use (such as KWRegistrationManager
, KWDocument
, etc.) are compiled and included as part of the build process for this bundle.
Basically, no: you cannot link with an executable.
An application binary is in a specific format. And that format is different from the static or shared library format.
It means you won't be able to load any code parts from an application binary, as you would with a library.
Take a look at distributed objects. Your application could vend one or more objects that your Automator action could use. I've never tried it with Automator, but it's a very elegant system that hasn't gotten a lot of attention in recent years. I think it's definitely worth a look.
One cool aspect of distributed objects is that the application could be running on the same computer if you wish, but it could just as easily be running on a different computer, perhaps even one that's very far away.
You could make certain behavior from you app accessible via Applescript, but accessing the the actual classes is not possible in the way I think you mean. I get the impression that you mean accessing the classes loaded into the memory of your running app. This is not possible on OS X (or any UNIX-like system). Applications run at the user level. Processess at the user level are not able to read memory from other processes. The components of the OS that need to do this sort of thing run at kernel level.
If you are just trying to reuse the code, you could build the parts you want to share into a static library, and others could link against it and share your code.
EDIT:
From NSGod's answer it seems that you can use the same approach that makes it accessible via Applescript and make it accessible via Obj-C. That looks pretty cool.
精彩评论