Belgeler dizini (NSDocumentDirectory) nedir?


123

Biri bana bir iOS uygulamasında belgeler dizininin ne olduğunu ve ne zaman kullanılacağını açıklayabilir mi?

İşte şu anda inandığım şey:

Bana göre, kullanıcının uygulama için gerekli tüm dosyaları saklayabileceği merkezi bir klasör gibi görünüyor.

Bu, Core Data'nın verilerini depoladığı yerden farklı bir konum olabilir mi?

Görünüşe göre her uygulama kendi belgeler dizinine sahip.

Belgeler dizini / resimler veya belgeler dizini / videolar gibi belgeler dizininin bir alt dizinini oluşturabilir miyim?


Iirc, NSDocumentDirectory, uygulamanın temel verileriyle aynı yolda yer alır ve her uygulamanın kendi belge dizini vardır. Ve evet, uygulamanız için ihtiyacınız olan tüm kaynakları buraya özgürce koyabilirsiniz. Bu arada, sorunuz henüz tamamlanmadı mı?
Zekareisoujin

Sorunuzla ilgili olduğunu düşündüğüm bir şeyi burada stackoverflow.com/questions/5105250/… ' e gönderdim. Sizin için çalışıp çalışmadığını kontrol edin.
Wytchkraft

Google'dan gelen herkes için bunun iOS 8'de değiştiğini unutmayın. Aşağıdaki cevabıma bakın.
livingtech

sqlite dosyanızın kaydedildiği yer ile aynıdır.
Anurag Bhakuni

Yanıtlar:


197

Yalnızca uygulamanız (jailbreak yapılmamış bir cihazda) "korumalı" ortamda çalışır. Bu, yalnızca kendi içeriği içindeki dosyalara ve dizinlere erişebileceği anlamına gelir. Örneğin Belgeler ve Kitaplık .

Bkz iOS Uygulama Kılavuzu Programlama .

Uygulamalar sanal alanınızın Belgeler dizinine erişmek için aşağıdakileri kullanabilirsiniz:

iOS 8 ve daha yenisi, önerilen yöntem budur

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

iOS 7 veya önceki bir sürümünü desteklemeniz gerekiyorsa

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

Bu Belgeler dizini, uygulamanızın oluşturduğu veya ihtiyaç duyabileceği dosyaları ve alt dizinleri saklamanıza olanak tanır.

Uygulamalarınızın sanal alan kullanımının Kitaplık dizinindeki dosyalara erişmek için ( pathsyukarıdakinin yerine):

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

13
[@ "~ / Documents" stringByExpandingTildeInPath] yönteminin de aynı şeyi yaptığını keşfettim. Bunun cesaretinin kırılması için herhangi bir sebep var mı?
Cthutu

35
Yaklaşımı @ "~ / Documents" ile kullanmazdım. Sabit kodlama yolları asla iyi bir fikir değildir. Şimdi işe yarayabilir, ancak Apple Belgeler dizinini yeniden adlandırmayı veya taşımayı seçerse uygulamanız bozulacaktır. NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);her zaman size doğru dizini verecektir!

16
yine de sağlanan API'yi kullanmalısınız. Bu yüzden orada! Şimdiye kadar şanslıydın.
nielsbot

20
Her kullanmam gerektiğinde bunu google'a çevirmem ne kadar komik. Tüm mobil platformların ev / yazılabilir dizin için varsayılan genel parametre sağlaması gerektiğini düşünüyorum
Ravindranath Akila

1
bir uygulamanın klasörlere yazma yeteneği hakkında bilgi içeren güncellenmiş bağlantı: developer.apple.com/library/mac/documentation/FileManagement/…
phil

43

Bu, iOS 8'de değişti. Şu teknik nota bakın: https://developer.apple.com/library/ios/technotes/tn2406/_index.html

Apple'ın onayladığı yol (yukarıdaki bağlantıdan) aşağıdaki gibidir:

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

7
İstediğin cevap bu! Yıl neredeyse 2016 oldu. Bu, tarihi geçmiş cevapları olan popüler bir sorudur.
Jeff

Belge dizininin yolunu almak için yukarıdaki yöntemi kullanabilir miyim? url.path gibi mi?
Abuzar Amin

21

Kabul edilen yanıtın önerdiği dokümanda kodu bulamadım ama güncellenmiş karşılığını burada buldum:

Dosya Sistemi Programlama Kılavuzu :: Dosyalara ve Dizinlere Erişim »

- (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'in kullanılmasını engeller:

NSSearchPathForDirectoriesInDomains işlevi, URLsForDirectory: inDomains: yöntemi gibi davranır, ancak dizinin konumunu dize tabanlı bir yol olarak döndürür. Bunun yerine URLsForDirectory: inDomains: yöntemini kullanmalısınız.

İşte oynayabileceğiniz diğer kullanışlı dizin sabitleri. Şüphesiz bunların hepsi iOS'ta desteklenmiyor. Ayrıca NSHomeDirectory () işlevini de kullanabilirsiniz:

İOS'ta ana dizin, uygulamanın korumalı alan dizinidir. OS X'te, uygulamanın sanal alan dizini veya geçerli kullanıcının ana dizinidir (uygulama bir sanal alanda değilse)

NSPathUtilities.h sitesinden

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

Ve son olarak, bir NSURL kategorisindeki bazı kolaylık yöntemleri http://club15cc.com/code/ios/easy-ios-file-directory-paths-with-this-handy-nsurl-category


8

Swift 3 ve 4 global değişken olarak:

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

FileManager uzantısı olarak:

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

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

Teşekkürler. Bunu hep unutuyorum. :) API tasarım yönergelerine hızlı bir şekilde uymak istiyorsanız, onu adlandırabilir documentDirectoryURLveya basitçe documentDirectorytürüne güvenebilirsiniz. FileManagerBir uzantıdaki statik bir özelliğe statik olarak kapsama alma fikrini seviyorum .
Ray Fix

1
Teşekkürler @RayFix, cevabımı önerinizle güncelledi!
Anton Plebanovich


6

Bu tür garip çağrılar için FileManager'a bir uzantı eklemek, başka bir şey değilse bile düzen için daha temiz olabilir. Gibi bir şey:

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

4

Temelde dosyayı plist biçiminde depolamak için kullanılan bu kodu kullanarak belgeler dizinine erişebilirsiniz:

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

Aynı cevap, WrightsCS tarafından 3 yıl önce verildi. Ayrıca, Apple'ın livingtech'in cevabında bu yöntemi önerdiği düşünüldüğünde, 2014 yılında bu cevabı vermek tuhaf.
Jeff

Eğer olumsuz oy kullandığımı düşünüyorsanız, lütfen nedenini açıklayın. Sorularımdan birinin intikamını almak çocukça. Bu site, en iyi cevapları en üste itmekle ilgili.
Jeff

@jeff işaret ettiğiniz için teşekkür ederim, biraz araştırma yaptınız ve haklıydınız. yeni çözüm: - (NSURL *) applicationDocumentsDirectory {return [[[NSFileManager defaultManager] URLsForDirectory: NSDocumentDirectory inDomains: NSUserDomainMask] lastObject]; }
Sumit Oberoi

1

İşte iOS klasörlerini kullanmayı / oluşturmayı biraz daha kolaylaştıran kullanışlı küçük bir işlev.

Ona bir alt klasörün adını iletirsiniz, tam yolu size geri döndürür ve dizinin var olduğundan emin olur.

(Şahsen, bu statik işlevi AppDelete sınıfıma yapıştırıyorum, ancak belki de burası onu koymak için en akıllıca yer değil.)

MySavedImages alt dizininin "tam yolunu" almak için onu şu şekilde adlandırırsınız:

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

Ve işte tam işlev:

+(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;
}

Bu küçük işlevi kullanarak, uygulamanızın Belgeler dizininde bir dizin oluşturmak (zaten yoksa) ve içine bir dosya yazmak kolaydır.

Dizini şu şekilde oluşturabilirim ve görüntü dosyalarımdan birinin içeriğini içine yazabilirim:

//  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];

Bu yardımcı olur umarım !


0

Bahsedilen diğerleri gibi, uygulamanız korumalı bir ortamda çalışır ve belgeler dizinini, uygulamanızın kullanabileceği görüntüleri veya diğer varlıkları depolamak için kullanabilirsiniz, örn. çevrimdışı-d dosyalarını kullanıcının tercih ettiği şekilde indirmek - Dosya Sisteminin Temelleri - Apple Belgeleri - Uygulamaya özel dosyaları depolamak için hangi dizinin kullanılacağı

Swift 5'e güncellendi, ihtiyaca göre bu işlevlerden birini kullanabilirsiniz -

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]
    }

Kullanımı:

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
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.