从C ++访问OS X上的标准目录的现代标准规范方法是什么,例如~/Library/Application Support
或~/Library/Preferences
?
我已经看到了使用CoreServices的提及,但它也提到了它已被弃用,我无法找到允许我做更多的文档,而不仅仅是粘贴代码。
我发现提到使用Objective C ++,但关于该选项的大多数信息都围绕着从Objective C调用C ++代码,而且Apple的文档似乎相当稀疏,或者至少我没有成功找到它
答案 0 :(得分:2)
嗯,在每个OS X版本上都存在鲜为人知的NSSystemDirectories.h
(/usr/include/NSSystemDirectories.h
)标题,我一直检查回OS X 10.3。它是libc的一部分:http://opensource.apple.com//source/Libc/Libc-825.40.1/include/NSSystemDirectories.h
它提供了一个C API,虽然创建一个Objective-C ++包装器并不困难:创建一个纯C ++接口,在实现中使用Objective-C。
FolderManager.h:
#include <stdio.h>
namespace fm {
enum {
NSApplicationDirectory = 1,
NSDemoApplicationDirectory,
NSDeveloperApplicationDirectory,
NSAdminApplicationDirectory,
NSLibraryDirectory,
NSDeveloperDirectory,
NSUserDirectory,
NSDocumentationDirectory,
NSDocumentDirectory,
NSCoreServiceDirectory,
NSAutosavedInformationDirectory = 11,
NSDesktopDirectory = 12,
NSCachesDirectory = 13,
NSApplicationSupportDirectory = 14,
NSDownloadsDirectory = 15,
NSInputMethodsDirectory = 16,
NSMoviesDirectory = 17,
NSMusicDirectory = 18,
NSPicturesDirectory = 19,
NSPrinterDescriptionDirectory = 20,
NSSharedPublicDirectory = 21,
NSPreferencePanesDirectory = 22,
NSApplicationScriptsDirectory = 23,
NSItemReplacementDirectory = 99,
NSAllApplicationsDirectory = 100,
NSAllLibrariesDirectory = 101,
NSTrashDirectory = 102
};
typedef unsigned long SearchPathDirectory;
enum {
NSUserDomainMask = 1, // user's home directory --- place to install user's personal items (~)
NSLocalDomainMask = 2, // local to the current machine --- place to install items available to everyone on this machine (/Library)
NSNetworkDomainMask = 4, // publically available location in the local area network --- place to install items available on the network (/Network)
NSSystemDomainMask = 8, // provided by Apple, unmodifiable (/System)
NSAllDomainsMask = 0x0ffff // all domains: all of the above and future items
};
typedef unsigned long SearchPathDomainMask;
class FolderManager {
public:
FolderManager();
~FolderManager();
const char *pathForDirectory(SearchPathDirectory directory, SearchPathDomainMask domainMask);
const char *pathForDirectoryAppropriateForItemAtPath(SearchPathDirectory directory, SearchPathDomainMask domainMask, const char *itemPath, bool create = false);
private:
void *m_autoreleasePool;
};
};
FolderManager。 mm (请注意文件扩展名)
#include "FolderManager.h"
#import <Foundation/Foundation.h>
using namespace fm;
FolderManager::FolderManager() {
m_autoreleasePool = [[NSAutoreleasePool alloc] init];
}
FolderManager::~FolderManager() {
[(NSAutoreleasePool *)m_autoreleasePool release];
}
const char * FolderManager::pathForDirectory(SearchPathDirectory directory, SearchPathDomainMask domainMask) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *URLs = [fileManager URLsForDirectory:(NSSearchPathDirectory)directory inDomains:domainMask];
if (URLs.count == 0) return NULL;
NSURL *URL = [URLs objectAtIndex:0];
NSString *path = URL.path;
// `fileSystemRepresentation` on an `NSString` gives a path suitable for POSIX APIs
return path.fileSystemRepresentation;
}
const char * FolderManager::pathForDirectoryAppropriateForItemAtPath(SearchPathDirectory directory,
SearchPathDomainMask domainMask, const char *itemPath, bool create) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *nsPath = [fileManager stringWithFileSystemRepresentation:itemPath length:strlen(itemPath)];
NSURL *itemURL = (nsPath ? [NSURL fileURLWithPath:nsPath] : nil);
NSURL *URL = [fileManager URLForDirectory:(NSSearchPathDirectory)directory
inDomain:domainMask
appropriateForURL:itemURL
create:create error:NULL];
return URL.path.fileSystemRepresentation;
}
请注意,这应该在没有启用自动引用计数的情况下编译(或者至少,这就是我使用它的方式;它可能也适用于ARC,但我没有测试过)。分别在构造函数和析构函数中创建和释放NSAutoreleasePool
非常重要,否则,您可能会在控制台中获得内存泄漏和警告(除非在其他地方为您创建了NSAutoreleasePool
) **。
要使用它,就像这样:
int main(int argc, const char * argv[]) {
char *folderPath = NULL;
FolderManager folderManager;
folderPath = (char *)folderManager.pathForDirectory(NSApplicationSupportDirectory, NSUserDomainMask);
printf("folderPath == %s\n", folderPath);
folderPath = (char *)folderManager.pathForDirectory(NSApplicationSupportDirectory, NSLocalDomainMask);
printf("folderPath == %s\n", folderPath);
folderPath = (char *)folderManager.pathForDirectory(NSTrashDirectory, NSAllDomainsMask);
printf("folderPath == %s\n", folderPath);
if (argc > 1) {
folderPath = (char *)folderManager.pathForDirectoryAppropriateForItemAtPath(NSTrashDirectory, NSAllDomainsMask, argv[1]);
printf("folderPath == %s\n", folderPath);
folderPath = (char *)folderManager.pathForDirectoryAppropriateForItemAtPath(NSItemReplacementDirectory, NSUserDomainMask, argv[1], true);
printf("folderPath == %s\n", folderPath);
}
return 0;
}
当我在我的机器上运行它时,传递/Volumes/Untitled3/folder/testFile.chm
的参数,它将输出以下内容:
folderPath == /Users/mdouma46/Library/Application Support
folderPath == /Library/Application Support
folderPath == /Users/mdouma46/.Trash
folderPath == /Volumes/Untitled 3/.Trashes/501
folderPath == /Volumes/Untitled 3/.TemporaryItems/folders.501/TemporaryItems/(A Document Being Saved By findFolder)
**关于关于NSAutoreleasePool
重要性的内存管理评论:我在OS X Yosemite,Xcode 7.2.1中通过评论NSAutoreleasePool
的创建来测试它,并且我的生活,我无法将任何错误记录到控制台,所以我不确定发生了什么。
我期待的是当我在OS X 10.6中的Xcode 3.2.6中编译它时得到的结果:
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x10010c6d0 of class NSCFArray autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x10010c820 of class NSCFString autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x100111540 of class NSCFString autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x100111710 of class NSPathStore2 autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x100111770 of class NSPathStore2 autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x100111a20 of class NSCFArray autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x100111a60 of class NSCFArray autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x100111d10 of class NSCFString autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x100111ac0 of class NSURL autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x100111c20 of class NSCFArray autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x100111de0 of class NSCFString autoreleased with no pool in place - just leaking
findFolder[300] *** __NSAutoreleaseNoPool(): Object 0x100111cb0 of class NSConcreteData autoreleased with no pool in place - just leaking
folderPath == /Users/mdouma46/Library/Application Support
这是因为许多Objective-C调用都返回自动释放的对象:NSFileManager
的{{1}}返回一个自动释放的URLsForDirectory:inDomain:
数组。调用NSURL
的{{1}}方法返回(创建)自动释放的NSURL
s(实际上是path
私有子类)等...
答案 1 :(得分:1)
查看以下技术问答&amp;在您不想要引入NS名称空间的环境中解决代字号扩展的问题: https://developer.apple.com/library/mac/qa/qa1549/_index.html
我没有遇到类似于NSString的expandTildeAtPath的内置CoreFoundation调用。至于你提到的CoreServices示例,其中包括FsRefs。这些是旧的Carbon调用和使用系统文件的对象。那些已被弃用,而不是CoreFoundation。