0

I want to write a bundle I've dragged and dropped into my project folder into a temporary file.

Previously I used fileManager.copyItem but it deleted the original.

Original code

func copyPackagedBundleToDocuments(withDestinationName dest: String) {
    if let bundlePath = Bundle.main.path(forResource: embeddedBundle, ofType: nil) {
        let fileManager = FileManager.default
        let destPath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!

        // applicationSupportDirectory is not created by default in the sandbox, and therefore we need to make sure that it exists!
        let urls = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask)
        if let applicationSupportURL = urls.last {
            do {
                try fileManager.createDirectory(at: applicationSupportURL, withIntermediateDirectories: true, attributes: nil)
            } catch {
                print(error)
            }
        }

        let fullDestPath = NSURL(fileURLWithPath: destPath + "/" + dest)
        do {
            try fileManager.copyItem(atPath: bundlePath, toPath: fullDestPath.path!)
        } catch {
            print(error)
        }
    }
}

This tells me the paths etc. are fine, since it does copy the file.

Now I want an atomic copy, so want to use Data(contentsOfFile)

So I rewrote everything:

func copyPackagedBundleToDocuments(withDestinationName dest: String) {
    if let bundlePath = Bundle.main.path(forResource: embeddedBundle, ofType: nil) {
        let fileManager = FileManager.default
        let destPath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first!

        // applicationSupportDirectory is not created by default in the sandbox, and therefore we need to make sure that it exists!
        let urls = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask)
        if let applicationSupportURL = urls.last {
            do {
                try fileManager.createDirectory(at: applicationSupportURL, withIntermediateDirectories: true, attributes: nil)
            } catch {
                print(error)
            }
        }

let urlPath = URL(fileURLWithPath: destPath + "/" + dest)

            let dta = try? Data(contentsOf: URL(fileURLWithPath: bundlePath) )

            do {
                try dta.write(to: urlPath , options: .atomic)
            } catch {
                print ("error \(error)")
            }
    }
}

However the data (dta) here is nil!

I think this is because my bundle location (as follows) ends in a backslash /:

file:///Users/user/Library/Developer/CoreSimulator/Devices/37A85B0B-F2B7-4A0C-BAA7-E05A831FFAE0/data/Containers/Bundle/Application/AD665103-E256-4F6C-8248-B62D8FF9FDC8/LocalBundle.app/Bundle.bundle/

and I guess that copyItem can treat the bundle as a single file, but writing the bundle to data is somehow not possible (the path is correct, since the code using copyItem works).

For clarity the following

    if let bundleURL = Bundle.main.url(forResource: embeddedBundle, withExtension: nil) {
        print ( try? Data(contentsOf: bundleURL ) )
    }

prints nil to the console, validating the url for the bundle.

How can I write my bundle to a file, atomically?

WishIHadThreeGuns
  • 1,225
  • 3
  • 17
  • 37
  • `moveItem` deletes the item at source location, `copyItem` does not. Did you read my answer to one of your [previous](https://stackoverflow.com/questions/58211706/ios-application-support-directory-exists-on-devices-by-default) questions how to handle the Application Support folder?. This avoids the check and explicit creation of the directory. And it's highly recommend to use always the URL related API of `Bundle` and `FileManager`. And don't use `NSURL` in Swift at all. – vadian Oct 04 '19 at 09:33
  • That makes sense, but the rewritten version doesn't use NSURL, and even without the explicit creation of the directory still reveals nil as the data. So I'm unclear how to proceed from here... – WishIHadThreeGuns Oct 05 '19 at 07:20
  • The rewritten version doesn't append the filename (what is `urlPath` anyway?) which is crucial. I meant NSData not NSURL – vadian Oct 05 '19 at 07:27
  • urlPath is kind of irrelevent, it's the destination path but since data (and it is the same for Data or NData) is nil...in any case I've updated the question to use Data. – WishIHadThreeGuns Oct 05 '19 at 11:53
  • I'm using the explicit check at the moment for the Application Support folder, this is a different question entirely. – WishIHadThreeGuns Oct 05 '19 at 12:15
  • What is `embeddedBundle`? Where does it come from? – vadian Oct 05 '19 at 14:32
  • embeddedBundle is an embeddedBundle, a bundle within the main project (embedded in the project). Here is is a String name "Bundle.bundle" which refers to the resource. – WishIHadThreeGuns Oct 06 '19 at 23:44

0 Answers0