從C++訪問OS X上的標準目錄(如~/Library/Application Support
或~/Library/Preferences
)的現代標準規範方法是什麼?使用C++在OS X上訪問標準目錄
我見過使用CoreServices提及,但它也提到,它過時,我無法找到,讓我做的不僅僅是粘貼代碼的文檔。
我我發現提及使用Objective C++,但大多數有關該選項的信息都圍繞從Objective C調用C++代碼展開,並且Apple的文檔似乎相當稀少,或者至少我沒有成功找到它。
從C++訪問OS X上的標準目錄(如~/Library/Application Support
或~/Library/Preferences
)的現代標準規範方法是什麼?使用C++在OS X上訪問標準目錄
我見過使用CoreServices提及,但它也提到,它過時,我無法找到,讓我做的不僅僅是粘貼代碼的文檔。
我我發現提及使用Objective C++,但大多數有關該選項的信息都圍繞從Objective C調用C++代碼展開,並且Apple的文檔似乎相當稀少,或者至少我沒有成功找到它。
看一看下面的技術問答&一個,解決環境中的波浪線擴展,你不會想在NS命名空間拉: https://developer.apple.com/library/mac/qa/qa1549/_index.html
我還沒有遇到過內置的CoreFoundation調用類似於NSString的expandTildeAtPath。至於你提到的CoreServices例子,其中包括FsRefs。這些是舊的Carbon調用和對象來處理系統文件。這些已被棄用,而不是CoreFoundation。
那麼,有一個鮮爲人知的NSSystemDirectories.h
(在/usr/include/NSSystemDirectories.h
)標題已存在於每個版本的OS X我檢查一直回到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。 毫米(注意擴展名)
#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的Xcode 3.2.6中編譯它時得到的結果。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
的URLsForDirectory:inDomain:
返回NSURL
秒的自動釋放的陣列。調用NSURL
的path
方法返回(創建)自動釋放NSString
S(實際上,在NSPathStore2
私有子類),等等
我不知道這是否是另一個問題,但是當你在你的類實例中調用'pathForDirectory'時,爲什麼autorelease池會隱式地用於任何分配? – blackirishman
謝謝你的迴應,而工作,它的inelegance乾脆把我趕走。我決定使用Objective C++,它幾乎允許我在儘可能不使用C++的情況下使用此C++ API。儘管我仍然不確定'[NSFileManager URLsForDirectory:inDomains]'還是使用'NSURL'是最好的(我現在使用的是'NSFileManager'),但至少它使用簡單的代碼而不是Core Foundation的解決方法。 – Chuck