1

i am looking for a way how to do it. I say option how to work with files which are alredy created but UIDocument can not initialized only from URL.

So, here is my code and it does not work:

        weak var weakSelf = self
        let toFolder = presenter.interactor.url.path
        let name = "Untitled"
        var toPath = toFolder + "/" + name
        var count = 1
        while FileManager.default.fileExists(atPath: toPath) {
            toPath = toFolder + "/" + name + " (\(count))"
            count += 1
        }
        let url = (toPath + ".UTI").url!
        print(url.absoluteString)
        let document = Document(fileURL: url)
        document.save(to: url, for: UIDocument.SaveOperation.forCreating, completionHandler: { (success) in
            if success {
                vc.document = document
                vc.title = url.lastPathComponent
                let nvc = UINavigationController(rootViewController: vc)
                weakSelf?.userInterface.present(nvc, animated: true, completion: nil)
            } else {
                Alert.showError(body: "Could not create document".localized)
            }
        })

url is:

/var/mobile/Containers/Data/Application/67C2A474-A054-4DFE-8587-B453A8B44554/Documents/Untitled.UTI

I have crash on string: "let document = Document(fileURL: url)"

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'must pass a valid file URL to -[UIDocument initWithFileURL:]'

class Document:

enum DocumentError: Error {
case saveError
case loadError
}

class Document: UIDocument {

var text: String?

var encodingUsed: String.Encoding?

override func contents(forType typeName: String) throws -> Any {

    guard let data = text?.data(using: .utf8) else {
        throw DocumentError.saveError
    }

    return data
}

override func load(fromContents contents: Any, ofType typeName: String?) throws {

    guard let data = contents as? Data else {
        throw DocumentError.loadError
    }

    guard let utf8 = String(data: data, encoding: .utf8) else {
        throw DocumentError.loadError
    }

    self.text = utf8

}

}

var url: URL? {
    if self != "" && !isEmpty {
        return URL(string: self)
    } else {
        return nil
    }
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Marcuss
  • 13
  • 4
  • How does the line `let url = (toPath + ".rwmarkup").url!` even compile? – rmaddy Feb 20 '19 at 22:25
  • should I use some different extension or what;s the issue here? I updated extension to "UTI" but have the same error – Marcuss Feb 20 '19 at 22:27
  • Is 'let url = (toPath + ".UTI").url!' a string extension? Can you put the code of this extension? – qtngo Feb 20 '19 at 22:27
  • yes, fileURLWithPath solved the issue, but now i have some other issue and completion handler does not called. the code where this issue have place is: guard let data = text?.data(using: .utf8) else { throw DocumentError.saveError } – Marcuss Feb 20 '19 at 22:34
  • Please do not change your question after receiving answers. It negates the benefit of the answers. If you have a new issue after fixing the original problem, please accept the answer that best solved your original issue and if needed, post a new question specific to your new issue. – rmaddy Feb 20 '19 at 22:39

2 Answers2

1

Your code for creating paths and URLs needs a lot of work. But in the end you need to use URL(fileURLWithPath:) to create a file URL and pass that to your Document.

let toFolder = presenter.interactor.url
let name = "Untitled"
var toPath = toFolder.appendingPathComponent(name)
var count = 1
while FileManager.default.fileExists(atPath: toPath.path) {
    toPath = toFolder.appendingPathComponent(name + " (\(count))")
    count += 1
}
let url = toPath.appendingPathExtension("UTI")
print(url.path)
let document = Document(fileURL: url)
rmaddy
  • 314,917
  • 42
  • 532
  • 579
0

Your extension should return:URL(fileURLWithPath: self) not URL(string: self) because this is local file.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
qtngo
  • 1,594
  • 1
  • 11
  • 13