我想知道如何使用我在OS-X中编写的OS X应用程序打开文件。我在Info.plist中注册了文件类型,我的代码中有application:openFile:
。我按this post做了所有事情,标记为已解决。
问题是,只有在我的应用程序运行时将其拖放到我的应用程序中时,这才有效。但是,如果我只是双击我的文件,它就无法工作。它启动我的应用程序,但不是因为如果我拖放它会开始。因此,双击时application:openFile:
中的代码不会运行,但只有当我拖放文件时才会运行。
编辑:
关于我的代码的更多细节,以及我想要实现的目标。
我为其他应用程序创建了一个包装器应用程序。让其他应用程序调用" HelperApp.app"。这个HelperApp位于我的包装器应用程序的/Contents/
文件夹中。使用包装器应用程序,我指定了一个新的文件类型,让我们称之为" .ha"在Info.plist文件中。该文件包含一些参数命令。我试图实现的,当用户点击一个" .ha"文件,然后我的包装器应用程序从该文件中读取参数并为HelperApp设置它,然后启动HelperApp。这个HelperApp根据它得到的参数打开不同的东西。您可以在下面查看我的代码。
默认情况下,我有AppDelegate.h
和AppDelegate.mm
最新Xcode如何创建它。我将此行添加到我的AppDelegate.h
,就在" @ end"之前:
- (BOOL)processFile:(NSString *)file;
我在AppDelegate.mm
:
#import "AppDelegate.h"
#import "ArgumentParser.h"
@implementation AppDelegate
- (void)dealloc
{
[super dealloc];
}
- (BOOL)application:(NSApplication *)WrapperApp openFile:(NSString *)filename
{
return [self processFile:filename];
}
- (BOOL)processFile:(NSString *)file
{
NSLog(@"The following file has been dropped or selected: %@",file);
std::string path = [file cStringUsingEncoding:[NSString defaultCStringEncoding]];
ArgumentParser parser = ArgumentParser();
parser.getArgumentfromFile(path);
parser.setArgumentinFile(); // <== This is the "corrupted" function
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *helperAppPath = [[mainBundle bundlePath]
stringByAppendingString:@"/Contents/HelperApp.app"];
[[NSWorkspace sharedWorkspace] launchApplication:helperAppPath];
return YES;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
损坏的功能 - setArgumentinFile()
:
void ArgumentParser::setArgumentinFile() {
std::string content = ""; // The file content
std::fstream file;
file.open("HelperApp.app/Contents/Wrapper/HelperApp.app/Contents/Info.plist");
// Open the file and modify the arguments
if(file.is_open()) {
std::stringstream stream;
stream << file.rdbuf();
std::string line = "";
bool isIt = false;
while(getline(stream, line)) {
// This line is the argument list, which needs to be modifyed
if(isIt) {
int index = (int)line.find_last_of("<");
std::string start = line.substr(0, index);
std::string end = line.substr(index, std::string::npos);
std::string argument_list = start + " " + _argument + end;
content += argument_list + '\n';
isIt = false;
}
// Save the rest of the file so we can overwrite it
else {
content += line + '\n';
}
// Next line is the argument list
if(line.find("WineProgramArguments") != std::string::npos) {
isIt = true;
}
}
file.flush();
file.close();
}
else {
file.flush();
file.close();
throw std::runtime_error("File isn't opened");
}
file.open("HelperApp.app/Contents/Wrapper/HelperApp.app/Contents/Info.plist", std::ios::out);
// Open the file and overwrite it with the modifyed argument
if(file.is_open()) {
file << content;
file.flush();
file.close();
}
else {
file.flush();
file.close();
throw std::runtime_error("File isn't opened");
}
}
如果我在processFile
的{{1}}函数中注释掉上述函数,那么一切正常并且#34;顺利#34;。我的意思是包装器应用程序启动,它使用默认参数启动HelperApp。所以这应该是错误...
答案 0 :(得分:4)
如果您已实现-application:openFile:
,则在双击已注册类型的文件时应调用它。你说该应用程序启动,因此操作系统正在尝试使用您的应用程序打开该文件。以下是文档中的有用说明:
如果用户通过双击文件启动应用程序,则 委托在收到之前收到应用程序:openFile:message 在applicationDidFinishLaunching:。 (applicationWillFinishLaunching:是 在申请前发送:openFile:。)
因此,如果您在打开任何文件之前必须在-applicationDidFinishLaunching:
中执行任何操作,那么这可能是您的问题。考虑将您的应用初始化代码移至-applicationWillFinishLaunching:
。
答案 1 :(得分:1)
我已经弄清楚了。双击文件图标时,应用程序将自动启动,其他操作正确完成。但响应您的操作的应用程序不一定是您最后一次构建的应用程序。可能是您的应用程序的旧副本正在响应。看看图书馆&gt;开发人员&gt; Xcode&gt; DrivedData。您应该看到应用程序的许多文件夹。您可以通过右键单击并在构建后选择“在Finder中显示”来找到应用程序文件夹。将它们全部删除,并构建一个新的应用程序。然后双击,看看现在发生了什么。
答案 2 :(得分:1)
问题是,我在我的功能中给出了错误的路径。如果我从Xcode启动应用程序,这条路径有效,但如果我自己启动应用程序则不行。
这是解决我问题的post!
答案 3 :(得分:1)
右键单击而不是双击打开文件的行为方式不同!
Apple Docs:
如果用户通过双击文件启动应用程序,则委托在接收applicationDidFinishLaunching之前收到应用程序:openFile:message。 (applicationWillFinishLaunching:在应用程序之前发送:openFile :.)
Apple Docs遗漏了一条至关重要的信息...... 我假设右键单击 - &gt; &#39;打开&#39; Finder中的操作与双击相同。 它不是!
应用程序:openFile:在applicationDidFinishLaunching之后发生:在这种情况下!
在这个上抓了一个小时。