Что такое каталог документов (NSDocumentDirectory)?
Может кто-нибудь объяснить мне, что каталог документов находится в приложении для iOS и когда его использовать?
Вот что я верю в настоящее время:
Мне кажется, это центральная папка, где пользователь может хранить любые файлы, необходимые для приложения.
Это будет другое место, чем где Core Data хранит свои данные?
Кажется, что каждое приложение получает свой собственный каталог документов.
Я могу создать подкаталог каталога документов, например, каталог документов / изображения или каталог документов / видео?
8 ответов
Только ваше приложение (на не взломанном устройстве) работает в "изолированной" среде. Это означает, что он может получить доступ только к файлам и каталогам в пределах своего собственного содержимого. Например Документы и Библиотека.
См. Руководство по программированию приложений iOS.
Чтобы получить доступ к каталогу документов вашей изолированной программной среды приложений, вы можете использовать следующее:
iOS 8 и новее, это рекомендуемый метод
+ (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
если вам нужно поддерживать iOS 7 или более раннюю версию
+ (NSString *) applicationDocumentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = paths.firstObject;
return basePath;
}
Этот каталог документов позволяет хранить файлы и подкаталоги, которые создает или может понадобиться вашему приложению.
Для доступа к файлам в каталоге Library вашей песочницы приложений используйте (вместо paths
выше):
[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]
Это изменилось в iOS 8. См. Следующую техническую заметку: https://developer.apple.com/library/ios/technotes/tn2406/_index.html
Apple, санкционированный способ (из ссылки выше) заключается в следующем:
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
Я не смог найти код в документе, предложенный принятым ответом, но нашел обновленный эквивалент здесь:
Руководство по программированию файловой системы:: Доступ к файлам и каталогам "
- (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;
}
Это препятствует использованию NSSearchPathForDirectoriesInDomain:
Функция NSSearchPathForDirectoriesInDomains ведет себя как метод URLsForDirectory:inDomains:, но возвращает местоположение каталога в виде пути на основе строки. Вместо этого вы должны использовать метод URLsForDirectory:inDomains:.
Вот еще несколько полезных констант каталогов, с которыми можно поиграть. Без сомнения, не все из них поддерживаются в iOS. Также вы можете использовать функцию NSHomeDirectory(), которая:
В iOS домашний каталог - это каталог песочницы приложения. В OS X это каталог песочницы приложения или домашний каталог текущего пользователя (если приложение не находится в песочнице)
Из 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
И, наконец, некоторые удобные методы в категории NSURL http://club15cc.com/code/ios/easy-ios-file-directory-paths-with-this-handy-nsurl-category
Swift 3 и 4 как глобальная переменная:
var documentsDirectory: URL {
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!
}
Как расширение FileManager:
extension FileManager {
static var documentsDirectory: URL {
return `default`.urls(for: .documentDirectory, in: .userDomainMask).last!
}
var documentsDirectory: URL {
return urls(for: .documentDirectory, in: .userDomainMask).last!
}
}
Помимо Documents
iOS также позволяет сохранять файлы в temp
а также Library
папки.
Для получения дополнительной информации о том, какой использовать, см. Эту ссылку в документации:
Может быть чище добавить расширение для FileManager для такого рода неудобных вызовов, для аккуратности, если ничего больше. Что-то вроде:
extension FileManager {
static var documentDir : URL {
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
}
}
Вы можете получить доступ к каталогу документов, используя этот код, он в основном используется для хранения файла в формате plist:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
return documentsDirectory;
Вот небольшая полезная функция, которая немного упрощает использование / создание папок iOS.
Вы передаете ей имя подпапки, она вернет вам полный путь и убедится, что каталог существует.
(Лично я вставляю эту статическую функцию в мой класс AppDelete, но, возможно, это не самое умное место для ее размещения.)
Вот как вы бы назвали это, чтобы получить "полный путь" подкаталога MySavedImages:
NSString* fullPath = [AppDelegate getFullPath:@"MySavedImages"];
И вот полная функция:
+(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;
}
Используя эту маленькую функцию, легко создать каталог в каталоге документов вашего приложения (если он еще не существует) и записать в него файл.
Вот как я могу создать каталог и записать в него содержимое одного из моих файлов изображений:
// 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];
Надеюсь это поможет!
Как уже упоминалось, ваше приложение работает в изолированной среде, и вы можете использовать каталог документов для хранения изображений или других ресурсов, которые может использовать ваше приложение, например. загрузка файлов offline-d по желанию пользователя - Основы файловой системы - Документация Apple - Какой каталог использовать для хранения файлов, специфичных для приложения
После обновления до 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]
}
Применение:
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
}
}