使用objective-c编写的自己的应用程序打开文件

时间:2013-05-23 05:56:55

标签: objective-c macos

我想知道如何使用我在OS-X中编写的OS X应用程序打开文件。我在Info.plist中注册了文件类型,我的代码中有application:openFile:。我按this post做了所有事情,标记为已解决。

问题是,只有在我的应用程序运行时将其拖放到我的应用程序中时,这才有效。但是,如果我只是双击我的文件,它就无法工作。它启动我的应用程序,但不是因为如果我拖放它会开始。因此,双击时application:openFile:中的代码不会运行,但只有当我拖放文件时才会运行。

编辑:

关于我的代码的更多细节,以及我想要实现的目标。 我为其他应用程序创建了一个包装器应用程序。让其他应用程序调用" HelperApp.app"。这个HelperApp位于我的包装器应用程序的/Contents/文件夹中。使用包装器应用程序,我指定了一个新的文件类型,让我们称之为" .ha"在Info.plist文件中。该文件包含一些参数命令。我试图实现的,当用户点击一个" .ha"文件,然后我的包装器应用程序从该文件中读取参数并为HelperApp设置它,然后启动HelperApp。这个HelperApp根据它得到的参数打开不同的东西。您可以在下面查看我的代码。

默认情况下,我有AppDelegate.hAppDelegate.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。所以这应该是错误...

4 个答案:

答案 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之后发生:在这种情况下!

在这个上抓了一个小时。