views:

490

answers:

4

through terminal you can make it with a command - "SetFile -a B filename"

programmatically i think i should set one of the attributes through [[NSFileManager defaultManager] createDirectoryAtPath:dirPath withIntermediateDirectories:NO attributes:attributes error:nil];

but i can't find witch one.

thanks)

+2  A: 

What are you trying to do?

Almost all Mac OS X bundles are actually folders with a very specific layout of files/folders within. Rarely is a bundle just a file -- they do exist, but not often.

In most cases, the Bundle bit on the file is entirely irrelevant.

i want to set a folder as a bundle. so through the file system it will looks like a file. later a want to open that package with my application. the question is how to set the folder bundle attribute through cocoa.

You really don't need to set the bundle bit. As long as your folder has an extension (which it should) and your application is properly configured to open files/folders of that extension, it should sow up in the finder as if it were a file.

Example:

  1. Go to ~/Desktop in Finder

  2. In terminal, do:

  3. cd ~/Desktop

  4. mkdir aafoo

  5. mv aafoo aafoo.rtfd

After (4), you'll see 'aafoo' show up in Finder as a folder.

AFter (5), 'aafoo' will change to be a TextEdit document. No attribute bits necessary.


OK -- fair enough. You really really want to set that bit.

Given that you have the command line to do it, I would suggest simply using NSTask. It will likely be easier than using an API to do so.

bbum
i want to set a folder as a bundle. so through the file system it will looks like a file. later a want to open that package with my application.the question is how to set the folder bundle attribute through cocoa.
Remizorrr
yes. but i need not rtfd extention. but for example fbp.And i need to make it programmatically.to make any folder a bundle you can use a command through terminal: SetFile -a B foldername .man page for SetFile says - -a attributes Sets the file attributes bits where ...(etc.) B | b Has bundle .the question is how to make the same programmatically through cocoa.
Remizorrr
+4  A: 

It is still useful to be able to set the bundle bit programmatically, for instance iPhoto does this to make the iPhoto Library folder appear as a single file.

You can set the bundle bit programmatically using the Carbon File Manager API. You'll need to make sure your app links against the Carbon framework and import the <Carbon/Carbon.h> header. These calls are 64-bit safe.

- (void)setBundleBitOfFile:(NSString*)path toBool:(BOOL)newValue
{
    const char* pathFSR = [path fileSystemRepresentation];
    FSRef ref;
    OSStatus err        = FSPathMakeRef((const UInt8*)pathFSR, &ref, /*isDirectory*/ NULL);

    if (err == noErr)
    {
        struct FSCatalogInfo catInfo;
        union FinderInfoTransmuter finderInfoPointers = { .bytes = catInfo.finderInfo };

        err = FSGetCatalogInfo(&ref,
                               kFSCatInfoFinderInfo,
                               &catInfo,
                               /*outName*/ NULL,
                               /*FSSpec*/ NULL,
                               /*parentRef*/ NULL);

        if (err == noErr)
        {
            if (newValue)
                finderInfoPointers.finderInfo->finderFlags |=  kHasBundle;
            else
                finderInfoPointers.finderInfo->finderFlags &= ~kHasBundle;

            FSSetCatalogInfo(&ref,
                             kFSCatInfoFinderInfo,
                             &catInfo);
        }
    }
}

- (BOOL)bundleBitOfFile:(NSString*)path
{
    BOOL value          = NO;

    const char* pathFSR = [path fileSystemRepresentation];
    FSRef ref;
    OSStatus err        = FSPathMakeRef((const UInt8*)pathFSR, &ref, /*isDirectory*/ NULL);

    if (err == noErr)
    {
        struct FSCatalogInfo catInfo;
        union FinderInfoTransmuter finderInfoPointers = { .bytes = catInfo.finderInfo };

        err = FSGetCatalogInfo(&ref,
                               kFSCatInfoFinderInfo,
                               &catInfo,
                               /*outName*/ NULL,
                               /*FSSpec*/ NULL,
                               /*parentRef*/ NULL);

        if (err == noErr)
        {
            value = (BOOL)(((finderInfoPointers.finderInfo->finderFlags) & kHasBundle) == kHasBundle);
        }
    }

    return value;
}
Rob Keniger
+2  A: 

You do not set a bundle attribute. You define your document types in your application's Info.plist file, and this is where you specify whether your document's are packages or plain files.

You can do this from within Xcode by selecting "Get Info" on your application target; switch to the "Properties" tab, then under "Document Types" add a document, give it a Name, set its file extension, choose an Icon file, then check the "Package" checkmark.

Darren
Of course, for this to work you need to ensure your documents are saved with a bundle structure, as outlined here: http://developer.apple.com/mac/library/documentation/CoreFoundation/Conceptual/CFBundles/DocumentPackages/DocumentPackages.html#//apple_ref/doc/uid/10000123i-CH106-SW1
Rob Keniger
There's no trick to it. To quote the article: "all you have to do is create a directory with the appropriate filename extension."
Darren
Yes, you're right.
Rob Keniger
A: 

Thanks everybody for help. I used the solution with info.plist file. this is the part of the plist file.

<key>CFBundleDocumentTypes</key>
<array>
    <dict>
        <key>CFBundleTypeName</key>
        <string>Project</string>
        <key>LSHandlerRank</key>
        <string>Default</string>
        <key>LSTypeIsPackage</key>
        <true/>
        <key>CFBundleTypeExtensions</key>
        <array>
            <string>fbp</string>
        </array>
        <key>CFBundleTypeIconFile</key>
        <string>document</string>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
    </dict>
</array>
Remizorrr