iOS temporary folder location
Asked Answered
L

4

39

My app has just been rejected by Apple because it was storing temporary or cache files in the documents directory. Right. Their rejection message states:

Temporary files used by your app should only be stored in the /tmp directory

I suppose it is that besides the Documents and Library in the Application's folder.

I am now trying to debug this issue in the iPhone Simulator, and when I use NSTemporaryDirectory(), the value I get in the Xcode debugger is /var/folders/yj/gnz1c7156c7d6d4fj429yms40000gn/T/tempzip.zip, and not /Users/me/Library/Application Support/iPhone Simulator/5.1/Applications/8F71AB72-598C-427A-A116-36833D3209F7/tmp/tempzip.zip.

So: is NSTemporaryDirectory() having a different behaviour using the iPhone Simulator, and, is it possible to track the application's temporary directory at debug time ?

Lushy answered 10/8, 2012 at 8:16 Comment(1)
nshipster.com/temporary-files has well dissected the difference between FileManager.default.temporaryDirectory and itemReplacementDirectory. Use the former for use-and-throw files, use latter for edit-and-move files.Kitkitchen
L
29

UPDATED 2016 ANSWER :

  • Data which is explicitly accepted by the user as personal, and potentially backuped in his/her iCloud space, should be written in user's "Documents" directory

  • Data that belongs and extends your application (an extension user can download for instance,...), but which is NOT in the bundle, should be written in a subfolder of "Application Support/" directory, having the title of your appID. It can also be the "Cache" directory.

  • Data with short-life time can be stored in the tmp directory of your application. In this case, use of NSTemporaryDirectory() is possible to get the "tmp" directory. Check this link for additional help.

Check this official iOS developement Apple page in section "Determining Where to Store Your App-Specific Files" for explanations.

Below are 3 functions in Swift designed to return NSURLs to these directories and make your like simpler.

Swift:

func GetDocumentsDirectory()->NSURL{
    //returns User's "Documents" directory
    //something like this on a real device : file:///private/var/mobile/Containers/Data/Application/APPID/Documents/
    //something like this on the simulator : file:///Users/MACUSERID/Library/Developer/CoreSimulator/Devices/SIMDEVICEID/data/Containers/Data/Application/APPUUID/Documents/
    let filemgr = NSFileManager.defaultManager()
    let docsDirURL = try! filemgr.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
    return docsDirURL
}

func GetApplicationSupportDirectory()->NSURL{
    //returns Application's support directory
    //something like this on a real device : file:///private/var/mobile/Containers/Data/Application/APPID/Library/Application%20Support/YOURAPPBUNDLEID/
    //something like this on the simulator : file:///Users/MACUSERID/Library/Developer/CoreSimulator/Devices/SIMDEVICEID/data/Containers/Data/Application/APPUUID/Library/Application%20Support/YOURAPPBUNDLEID/
    let AllDirectories : [NSURL]
    var ApplicationSupportDirectory : NSURL=NSURL.init()
    var ApplicationDirectory : NSURL=NSURL.init()
    AllDirectories=NSFileManager.defaultManager().URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask)
    if AllDirectories.count>=1{
        ApplicationSupportDirectory=AllDirectories[0]
    }
    if !ApplicationSupportDirectory.isEqual(nil) {
        ApplicationDirectory=ApplicationSupportDirectory.URLByAppendingPathComponent(NSBundle.mainBundle().bundleIdentifier!)
    }
    return ApplicationDirectory
}

func GetTemporaryDirectory()->NSURL{
    //returns Application's temporary directory
    //something like this on a real device : file:///private/var/mobile/Containers/Data/Application/APPID/tmp/
    //something like this on the simulator : file:///Users/MACUSERID/Library/Developer/CoreSimulator/Devices/SIMDEVICEID/data/Containers/Data/Application/APPUUID/tmp/
    return NSURL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
}
Lushy answered 10/5, 2016 at 23:55 Comment(0)
D
49

iOS 9 or later • Swift 3 or later

let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory())

iOS 10.0+Beta, macOS 10.12+, tvOS 10.0+Beta & watchOS 3.0+ • Xcode 8 • Swift 3 or later

let tmpDirURL = FileManager.default.temporaryDirectory
Downing answered 4/9, 2016 at 15:28 Comment(1)
Functionality-wise, this is the same. temporaryDirectory is a shim that calls NSTemporaryDirectory(). github.com/apple/swift-corelibs-foundation/blob/…Pinchpenny
L
29

UPDATED 2016 ANSWER :

  • Data which is explicitly accepted by the user as personal, and potentially backuped in his/her iCloud space, should be written in user's "Documents" directory

  • Data that belongs and extends your application (an extension user can download for instance,...), but which is NOT in the bundle, should be written in a subfolder of "Application Support/" directory, having the title of your appID. It can also be the "Cache" directory.

  • Data with short-life time can be stored in the tmp directory of your application. In this case, use of NSTemporaryDirectory() is possible to get the "tmp" directory. Check this link for additional help.

Check this official iOS developement Apple page in section "Determining Where to Store Your App-Specific Files" for explanations.

Below are 3 functions in Swift designed to return NSURLs to these directories and make your like simpler.

Swift:

func GetDocumentsDirectory()->NSURL{
    //returns User's "Documents" directory
    //something like this on a real device : file:///private/var/mobile/Containers/Data/Application/APPID/Documents/
    //something like this on the simulator : file:///Users/MACUSERID/Library/Developer/CoreSimulator/Devices/SIMDEVICEID/data/Containers/Data/Application/APPUUID/Documents/
    let filemgr = NSFileManager.defaultManager()
    let docsDirURL = try! filemgr.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
    return docsDirURL
}

func GetApplicationSupportDirectory()->NSURL{
    //returns Application's support directory
    //something like this on a real device : file:///private/var/mobile/Containers/Data/Application/APPID/Library/Application%20Support/YOURAPPBUNDLEID/
    //something like this on the simulator : file:///Users/MACUSERID/Library/Developer/CoreSimulator/Devices/SIMDEVICEID/data/Containers/Data/Application/APPUUID/Library/Application%20Support/YOURAPPBUNDLEID/
    let AllDirectories : [NSURL]
    var ApplicationSupportDirectory : NSURL=NSURL.init()
    var ApplicationDirectory : NSURL=NSURL.init()
    AllDirectories=NSFileManager.defaultManager().URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask)
    if AllDirectories.count>=1{
        ApplicationSupportDirectory=AllDirectories[0]
    }
    if !ApplicationSupportDirectory.isEqual(nil) {
        ApplicationDirectory=ApplicationSupportDirectory.URLByAppendingPathComponent(NSBundle.mainBundle().bundleIdentifier!)
    }
    return ApplicationDirectory
}

func GetTemporaryDirectory()->NSURL{
    //returns Application's temporary directory
    //something like this on a real device : file:///private/var/mobile/Containers/Data/Application/APPID/tmp/
    //something like this on the simulator : file:///Users/MACUSERID/Library/Developer/CoreSimulator/Devices/SIMDEVICEID/data/Containers/Data/Application/APPUUID/tmp/
    return NSURL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
}
Lushy answered 10/5, 2016 at 23:55 Comment(0)
L
12

I have tested this on a real device, and it returned : "/private/var/mobile/Applications/C82383-EBD6-4F72-BC16-A865478D27/tmp/tempzip.zip"

So overall, using NSTemporaryDirectory() is the correct way of finding the path to the temporary directory, and that if you want to debug and view what is done within, you need to find it manually in the Finder if you are using the iPhone Simulator.

Check newer answer below (this one is deprecated)

Lushy answered 10/8, 2012 at 8:16 Comment(1)
If you store a file at this url how long does it stay there for?Sorgo
P
10

According to the docs, you should avoid NSTemporaryDirectory() in favour of this approach

- (NSURL)URLForTemporaryFolder
{
    // Get a parent folder, trying user folder (fails iOS) and falling back to AppSupport and Docs
    NSURL *parentFolderURL = [NSURL URLForDirectory:NSUserDirectory domainMask:NSUserDomainMask];
    if (!parentFolderURL) parentFolderURL = [NSURL URLForDirectory:NSApplicationSupportDirectory domainMask:NSUserDomainMask];
    if (!parentFolderURL) parentFolderURL = [NSURL URLForDirectory:NSDocumentDirectory domainMask:NSUserDomainMask];

    // Get the temp folder URL using approach outlined in the docs
    NSURL *tmpURL = [[NSFileManager defaultManager]
     URLForDirectory:NSItemReplacementDirectory
     inDomain:NSUserDomainMask
     appropriateForURL:parentFolderURL
     create:YES
     error:NULL];

    return tmpURL;
}

Be aware that this creates a new unique temp folder each time you call it and it's up to you to clean it up.

Paine answered 21/9, 2013 at 20:24 Comment(3)
Isn't it just of OSX ?Lushy
I'm using it in iOS and works fine. Maybe they've changed things since the post though.Paine
Careful, this API has many gotchas, behaves differently on device and simulator! gist.github.com/steipete/d7a1506cdb1300cba0a3ae1b11450ab5Pinchpenny

© 2022 - 2024 — McMap. All rights reserved.