20

I am making a func that edits a text file in the Users/johnDoe Dir.

let filename = "random.txt"
let filePath = "/Users/johnDoe"
let replacementText = "random bits of text"
do {

 try replacementText.write(toFile: filePath, atomically: true, encoding: .utf8)

}catch let error as NSError {
print(error: + error.localizedDescription)
}

But I want to be able to have the path universal. Something like

let fileManager = FileManager.default
    let downloadsURL =  FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first! as NSURL
    let downloadsPath = downloadsURL.path

but for the JohnDoe folder. I haven't been able to find any documentation on how to do this. The closest thing I could find mentioned using NSHomeDirectory(). And I am not sure how to use it in this context.

when I try adding it like...

let fileManager = FileManager.default
    let downloadsURL =  FileManager.default.urls(for: NSHomeDirectory, in: .userDomainMask).first! as NSURL
    let downloadsPath = downloadsURL.path

I get an error:

"Cannot Convert value of type 'String' to expected argument type 'FileManager.SearchPathDirectory'"

I've tried it .NSHomeDirectory, .NSHomeDirectory(), NShomeDirectory, NShomeDirectory()

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
JonnyTombstone
  • 219
  • 1
  • 2
  • 6

4 Answers4

36

You can use FileManager property homeDirectoryForCurrentUser

let homeDirURL = FileManager.default.homeDirectoryForCurrentUser

If you need it to work with earlier OS versions than 10.12 you can use

let homeDirURL = URL(fileURLWithPath: NSHomeDirectory())

print(homeDirURL.path)
Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • You sir... I could kiss you write now =). very simple and works like a charm. I guess I was trying to over think it. – JonnyTombstone Dec 29 '16 at 18:20
  • 11
    This will return app's home folder instead of user's if sandbox – Oleksii Nezhyborets Jul 24 '19 at 15:34
  • This Answer is just for macOS, do we have home dir or something like that for iOS as well? – ios coder Jan 16 '22 at 14:26
  • @ioscoder There is no home folder for iOS. What you have is the documents directory – Leo Dabus Jan 16 '22 at 14:47
  • @ioscoder for more info about which folder to use you should take some time and read [File System Basics](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html). If you would like to get a specific folder in your app check this post [Getting list of files in documents folder](https://stackoverflow.com/a/27722526/2303865) – Leo Dabus Jan 16 '22 at 14:48
5

There should be an easier way but -- at worst -- this should work:

let filePath = NSString(string: "~").expandingTildeInPath
Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
2

Following solution works even in Sandboxed apps :

public extension URL {
    static var userHome : URL   {
        URL(fileURLWithPath: userHomePath, isDirectory: true)
    }
    
    static var userHomePath : String   {
        let pw = getpwuid(getuid())

        if let home = pw?.pointee.pw_dir {
            return FileManager.default.string(withFileSystemRepresentation: home, length: Int(strlen(home)))
        }
        
        fatalError()
    }
}

Testing solution on sandboxed App:

enter image description here

Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101
  • 1
    I'm not sure why this had a negative vote. This should be the accepted answer, since all the other answers would give you `~/Library/Containers/MyAppId/Data/` in a macos app with App Sandbox enabled instead of the real home, `~`. – endavid Jun 12 '23 at 16:09
  • 1
    @endavid Bad things happens sometimes :) This downvote was made by Justin Vallely after I downvoted his answer :) He deleted his comments/messages about my answer "not covers scenario" but downvote still here :) I believe after some time will pass it will be upvoted by people like you :) – Andrew_STOP_RU_WAR_IN_UA Jun 12 '23 at 18:46
1

Swift 5 (and maybe lower)

let directoryString: String = NSHomeDirectory()
let directoryURL: URL = FileManager.default.homeDirectoryForCurrentUser
Justin Vallely
  • 5,932
  • 3
  • 30
  • 44
  • 1
    will return app's home folder instead of user's in case of sandbox. So this is wrong answer. – Andrew_STOP_RU_WAR_IN_UA Mar 31 '23 at 04:26
  • no it is not the same, my code works under AppSandbox as you can see on the screenshot attached into my answer. If you do not believe that screenshot is real you're able to check my code in your own project that it will return correct value even in case of app is sandboxed. So my solution already covers sandbox scenario. – Andrew_STOP_RU_WAR_IN_UA Mar 31 '23 at 17:14
  • Your solution is bad because of it have unexpected behaviour in case of app is sandboxed (in most cases, as truly, because by default app after installation is sandboxed in any case). And for developers who didn't know this this will be absolutely unexpected behaviour and will create problems 100% in case you didn't tell this in your answer directly. And you didn't say this in your answer. So yes, this solution/answer is bad. And yes, my solution covers scenario. – Andrew_STOP_RU_WAR_IN_UA Mar 31 '23 at 17:19