ios 什么是文档目录(NSDocumentDirectory)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6907381/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:55:24  来源:igfitidea点击:

What is the documents directory (NSDocumentDirectory)?

iosnsdocumentdirectory

提问by user798719

Can someone explain to me what the documents directory is on an iOS app and when to use it?

有人可以向我解释一下 iOS 应用程序上的文档目录是什么以及何时使用它吗?

Here is what I believe at present:

以下是我目前的信念:

To me, it seems to be a central folder where the user can store any files needed for the app.

对我来说,它似乎是一个中央文件夹,用户可以在其中存储应用程序所需的任何文件。

This would be a different location than where Core Data stores its data?

这将与 Core Data 存储其数据的位置不同?

It seems like each app gets its own documents directory.

似乎每个应用程序都有自己的文档目录。

I am free to create a subdirectory of the documents directory, like documents directory/images, or documents directory/videos?

我可以随意创建文档目录的子目录,例如文档目录/图像或文档目录/视频?

回答by WrightsCS

Your app only (on a non-jailbroken device) runs in a "sandboxed" environment. This means that it can only access files and directories within its own contents. For example Documentsand Library.

您的应用程序仅(在非越狱设备上)在“沙盒”环境中运行。这意味着它只能访问自己内容中的文件和目录。例如DocumentsLibrary

See the iOS Application Programming Guide.

请参阅iOS 应用程序编程指南

To access the Documentsdirectory of your applications sandbox, you can use the following:

要访问应用程序沙箱的Documents目录,您可以使用以下命令:

iOS 8 and newer, this is the recommended method

iOS 8 及更新版本,这是推荐的方法

+ (NSURL *)applicationDocumentsDirectory
{
     return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

if you need to support iOS 7 or earlier

如果您需要支持 iOS 7 或更早版本

+ (NSString *) applicationDocumentsDirectory 
{    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *basePath = paths.firstObject;
    return basePath;
}

This Documentsdirectory allows you to store files and subdirectories your app creates or may need.

Documents目录允许您存储应用程序创建或可能需要的文件和子目录。

To access files in the Librarydirectory of your apps sandbox use (in place of pathsabove):

要访问您的应用程序沙箱的Library目录中的文件,请使用(代替paths上面的):

[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]

回答by livingtech

This has changed in iOS 8. See the following tech note: https://developer.apple.com/library/ios/technotes/tn2406/_index.html

这在 iOS 8 中发生了变化。请参阅以下技术说明:https: //developer.apple.com/library/ios/technotes/tn2406/_index.html

The Apple sanctioned way (from the link above) is as follows:

苹果认可的方式(来自上面的链接)如下:

// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

回答by Hari Karam Singh

I couldn't find the code in the doc suggested by the accepted answer but I found the updated equivalent here:

我在接受的答案建议的文档中找不到代码,但我在这里找到了更新的等效代码:

File System Programming Guide :: Accessing Files and Directories ?

文件系统编程指南:: 访问文件和目录?

- (NSURL*)applicationDataDirectory {
    NSFileManager* sharedFM = [NSFileManager defaultManager];
    NSArray* possibleURLs = [sharedFM URLsForDirectory:NSApplicationSupportDirectory
                                 inDomains:NSUserDomainMask];
    NSURL* appSupportDir = nil;
    NSURL* appDirectory = nil;

    if ([possibleURLs count] >= 1) {
        // Use the first directory (if multiple are returned)
        appSupportDir = [possibleURLs objectAtIndex:0];
    }

    // If a valid app support directory exists, add the
    // app's bundle ID to it to specify the final directory.
    if (appSupportDir) {
        NSString* appBundleID = [[NSBundle mainBundle] bundleIdentifier];
        appDirectory = [appSupportDir URLByAppendingPathComponent:appBundleID];
    }

    return appDirectory;
}

It discourages use of NSSearchPathForDirectoriesInDomain:

它不鼓励使用 NSSearchPathForDirectoriesInDomain:

The NSSearchPathForDirectoriesInDomains function behaves like the URLsForDirectory:inDomains: method but returns the directory's location as a string-based path. You should use the URLsForDirectory:inDomains: method instead.

NSSearchPathForDirectoriesInDomains 函数的行为类似于 URLsForDirectory:inDomains: 方法,但将目录的位置作为基于字符串的路径返回。您应该改用 URLsForDirectory:inDomains: 方法。

Here are some other useful directory constants to play with. No doubt not all of these are supported in iOS. Also you can use the NSHomeDirectory() function which:

这里有一些其他有用的目录常量可供使用。毫无疑问,并非所有这些都在 iOS 中受支持。您也可以使用 NSHomeDirectory() 函数:

In iOS, the home directory is the application's sandbox directory. In OS X, it is the application's sandbox directory or the current user's home directory (if the application is not in a sandbox)

在 iOS 中,主目录是应用程序的沙箱目录。在 OS X 中,它是应用程序的沙箱目录或当前用户的主目录(如果应用程序不在沙箱中)

From NSPathUtilities.h

从 NSPathUtilities.h

NSApplicationDirectory = 1,             // supported applications (Applications)
    NSDemoApplicationDirectory,             // unsupported applications, demonstration versions (Demos)
    NSDeveloperApplicationDirectory,        // developer applications (Developer/Applications). DEPRECATED - there is no one single Developer directory.
    NSAdminApplicationDirectory,            // system and network administration applications (Administration)
    NSLibraryDirectory,                     // various documentation, support, and configuration files, resources (Library)
    NSDeveloperDirectory,                   // developer resources (Developer) DEPRECATED - there is no one single Developer directory.
    NSUserDirectory,                        // user home directories (Users)
    NSDocumentationDirectory,               // documentation (Documentation)
    NSDocumentDirectory,                    // documents (Documents)
    NSCoreServiceDirectory,                 // location of CoreServices directory (System/Library/CoreServices)
    NSAutosavedInformationDirectory NS_ENUM_AVAILABLE(10_6, 4_0) = 11,   // location of autosaved documents (Documents/Autosaved)
    NSDesktopDirectory = 12,                // location of user's desktop
    NSCachesDirectory = 13,                 // location of discardable cache files (Library/Caches)
    NSApplicationSupportDirectory = 14,     // location of application support files (plug-ins, etc) (Library/Application Support)
    NSDownloadsDirectory NS_ENUM_AVAILABLE(10_5, 2_0) = 15,              // location of the user's "Downloads" directory
    NSInputMethodsDirectory NS_ENUM_AVAILABLE(10_6, 4_0) = 16,           // input methods (Library/Input Methods)
    NSMoviesDirectory NS_ENUM_AVAILABLE(10_6, 4_0) = 17,                 // location of user's Movies directory (~/Movies)
    NSMusicDirectory NS_ENUM_AVAILABLE(10_6, 4_0) = 18,                  // location of user's Music directory (~/Music)
    NSPicturesDirectory NS_ENUM_AVAILABLE(10_6, 4_0) = 19,               // location of user's Pictures directory (~/Pictures)
    NSPrinterDescriptionDirectory NS_ENUM_AVAILABLE(10_6, 4_0) = 20,     // location of system's PPDs directory (Library/Printers/PPDs)
    NSSharedPublicDirectory NS_ENUM_AVAILABLE(10_6, 4_0) = 21,           // location of user's Public sharing directory (~/Public)
    NSPreferencePanesDirectory NS_ENUM_AVAILABLE(10_6, 4_0) = 22,        // location of the PreferencePanes directory for use with System Preferences (Library/PreferencePanes)
    NSApplicationScriptsDirectory NS_ENUM_AVAILABLE(10_8, NA) = 23,      // location of the user scripts folder for the calling application (~/Library/Application Scripts/code-signing-id)
    NSItemReplacementDirectory NS_ENUM_AVAILABLE(10_6, 4_0) = 99,       // For use with NSFileManager's URLForDirectory:inDomain:appropriateForURL:create:error:
    NSAllApplicationsDirectory = 100,       // all directories where applications can occur
    NSAllLibrariesDirectory = 101,          // all directories where resources can occur
    NSTrashDirectory NS_ENUM_AVAILABLE(10_8, NA) = 102                   // location of Trash directory

And finally, some convenience methods in an NSURL category http://club15cc.com/code/ios/easy-ios-file-directory-paths-with-this-handy-nsurl-category

最后,NSURL 类别中的一些便捷方法 http://club15cc.com/code/ios/easy-ios-file-directory-paths-with-this-handy-nsurl-category

回答by Anton Plebanovich

Swift 3 and 4 as global var:

Swift 3 和 4 作为全局变量:

var documentsDirectory: URL {
    return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!
}

As FileManager extension:

作为文件管理器扩展:

extension FileManager {
    static var documentsDirectory: URL {
        return `default`.urls(for: .documentDirectory, in: .userDomainMask).last!
    }

    var documentsDirectory: URL {
        return urls(for: .documentDirectory, in: .userDomainMask).last!
    }
}

回答by Paul Robinson

It can be cleaner to add an extension to FileManager for this kind of awkward call, for tidiness if nothing else. Something like:

为这种尴尬的调用添加一个扩展到 FileManager 会更干净,如果没有别的,为了整洁。就像是:

extension FileManager {
    static var documentDir : URL {
        return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    }
}

回答by Eric

Aside from the Documentsfolder, iOS also lets you save files to the tempand Libraryfolders.

除了Documents文件夹,iOS 还允许您将文件保存到tempLibrary文件夹。

For more information on which one to use, see this link from the documentation:

有关使用哪个的更多信息,请参阅文档中的此链接:

回答by Sumit Oberoi

You can access documents directory using this code it is basically used for storing file in plist format:

您可以使用此代码访问文档目录,它基本上用于以 plist 格式存储文件:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
return documentsDirectory;

回答by Mike Gledhill

Here's a useful little function, which makes using/creating iOS folders a little easier.

这是一个有用的小功能,它使使用/创建 iOS 文件夹更容易一些。

You pass it the name of a subfolder, it'll return the full path back to you, and make sure the directory exists.

您将子文件夹的名称传递给它,它会将完整路径返回给您,并确保该目录存在。

(Personally, I stick this static function in my AppDelete class, but perhaps this isn't the smartest place to put it.)

(就我个人而言,我将这个静态函数放在我的 AppDelete 类中,但也许这不是放置它的最聪明的地方。)

Here's how you would call it, to get the "full path" of a MySavedImages subdirectory:

以下是您如何调用它,以获取 MySavedImages 子目录的“完整路径”:

NSString* fullPath = [AppDelegate getFullPath:@"MySavedImages"];

And here's the full function:

这是完整的功能:

+(NSString*)getFullPath:(NSString*)folderName
{
    //  Check whether a subdirectory exists in our sandboxed Documents directory.
    //  Returns the full path of the directory.
    //
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    if (paths.count < 1)
        return nil;

    NSString *rootFolder = [paths firstObject];
    NSString* fullFolderPath = [rootFolder stringByAppendingPathComponent:folderName];

    BOOL isDirectory;
    NSFileManager* manager = [NSFileManager defaultManager];

    if (![manager fileExistsAtPath:fullFolderPath isDirectory:&isDirectory] || !isDirectory) {
        NSError *error = nil;
        NSDictionary *attr = [NSDictionary dictionaryWithObject:NSFileProtectionComplete
                                                         forKey:NSFileProtectionKey];
        [manager createDirectoryAtPath:fullFolderPath
           withIntermediateDirectories:YES
                            attributes:attr
                                 error:&error];
        if (error) {
            NSLog(@"Error creating directory path: %@", [error localizedDescription]);
            return nil;
        }
    }
    return fullFolderPath;
}

Using this little function, it's easy to create a directory in your app's Documents directory (if it doesn't already exist), and to write a file into it.

使用这个小功能,可以很容易地在应用程序的 Documents 目录中创建一个目录(如果它不存在),并将文件写入其中。

Here's how I would create the directory, and write the contents of one of my image files into it:

下面是我将如何创建目录,并将我的图像文件之一的内容写入其中:

//  Let's create a "MySavedImages" subdirectory (if it doesn't already exist)
NSString* fullPath = [AppDelegate getFullPath:@"MySavedImages"];

//  As an example, let's load the data in one of my images files
NSString* imageFilename = @"icnCross.png";

UIImage* image = [UIImage imageNamed:imageFilename];
NSData *imageData = UIImagePNGRepresentation(image);

//  Obtain the full path+filename where we can write this .png to, in our new MySavedImages directory
NSString* imageFilePathname = [fullPath stringByAppendingPathComponent:imageFilename];

//  Write the data
[imageData writeToFile:imageFilePathname atomically:YES];

Hope this helps !

希望这可以帮助 !

回答by akashlal.com

Like others mentioned, your app runs in a sandboxed environment and you can use the documents directory to store images or other assets your app may use, eg. downloading offline-d files as user prefers - File System Basics - Apple Documentation - Which directory to use, for storing application specific files

与其他人提到的一样,您的应用程序在沙盒环境中运行,您可以使用文档目录来存储应用程序可能使用的图像或其他资产,例如。根据用户喜好下载离线 d 文件 -文件系统基础 - Apple 文档 - 使用哪个目录,用于存储特定于应用程序的文件

Updated to swift 5, you can use one of these functions, as per requirement -

更新到 swift 5,您可以根据需要使用以下功能之一 -

func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return paths[0]
}

func getCacheDirectory() -> URL {
        let paths = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)
        return paths[0]
    }

func getApplicationSupportDirectory() -> URL {
        let paths = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
        return paths[0]
    }

Usage:

用法:

let urlPath = "https://jumpcloud.com/wp-content/uploads/2017/06/SSH-Keys.png" //Or string path to some URL of valid image, for eg.

if let url = URL(string: urlPath){
    let destination = getDocumentsDirectory().appendingPathComponent(url.lastPathComponent)
    do {
        let data = try Data(contentsOf: url) //Synchronous call, just as an example
        try data.write(to: destination)
    } catch _ {
        //Do something to handle the error
    }
}