How can I write a file in a folder located at Apple's Files App in SwiftUI?
As I have already posted in comments you can NOT programmatically save a file out of your APP Bundle. You can use a UIDocumentInteractionController
and ask the user to choose the location where the file is supposed to be written.
So if you are working with SwiftUI this gets a bit more complicated than the regular Storyboard approach as you can see in this post because you need to implement UIViewControllerRepresentable
for UIDocumentInteractionController
:
struct DocumentInteractionController: UIViewControllerRepresentable {
fileprivate var isExportingDocument: Binding<Bool>
fileprivate let viewController = UIViewController()
fileprivate let documentInteractionController: UIDocumentInteractionController
init(_ isExportingDocument: Binding<Bool>, url: URL) {
self.isExportingDocument = isExportingDocument
documentInteractionController = .init(url: url)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<DocumentInteractionController>) -> UIViewController { viewController }
func updateUIViewController(_ controller: UIViewController, context: UIViewControllerRepresentableContext<DocumentInteractionController>) {
if isExportingDocument.wrappedValue && documentInteractionController.delegate == nil {
documentInteractionController.uti = documentInteractionController.url?.typeIdentifier ?? "public.data, public.content"
documentInteractionController.name = documentInteractionController.url?.localizedName
documentInteractionController.presentOptionsMenu(from: controller.view.frame, in: controller.view, animated: true)
documentInteractionController.delegate = context.coordinator
documentInteractionController.presentPreview(animated: true)
}
}
func makeCoordinator() -> Coordintor { .init(self) }
}
And its Coordinator:
class Coordintor: NSObject, UIDocumentInteractionControllerDelegate {
let documentInteractionController: DocumentInteractionController
init(_ controller: DocumentInteractionController) {
documentInteractionController = controller
}
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController { documentInteractionController.viewController }
func documentInteractionControllerDidDismissOptionsMenu(_ controller: UIDocumentInteractionController) {
controller.delegate = nil
documentInteractionController.isExportingDocument.wrappedValue = false
}
}
Now you can create your DocumentInteraction View and its previews:
struct DocumentInteraction: View {
@State private var isExportingDocument = false
var body: some View {
VStack {
Button("Export Document") { self.isExportingDocument = true }
.background(DocumentInteractionController($isExportingDocument,
url: Bundle.main.url(forResource: "sample", withExtension: "pdf")!))
}
}
}
struct DocumentInteraction_Previews: PreviewProvider {
static var previews: some View { DocumentInteraction() }
}
You will need those helpers as well:
extension URL {
var typeIdentifier: String? { (try? resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier }
var localizedName: String? { (try? resourceValues(forKeys: [.localizedNameKey]))?.localizedName }
}
Sample project
How to write a file to a folder located at Apple's Files App in Swift
You can use UIDocumentInteractionController
and let the user select where he wants to save your file when you share your url. The user just needs to select save to files and choose which directory to save the file you are exporting.
You can use UIDocumentInteractionController
to share any file type located inside your App bundle, at your Documents directory or another folder accessible from your App.
class ViewController: UIViewController {
let documentInteractionController = UIDocumentInteractionController()
func share(url: URL) {
documentInteractionController.url = url
documentInteractionController.uti = url.typeIdentifier ?? "public.data, public.content"
documentInteractionController.name = url.localizedName ?? url.lastPathComponent
documentInteractionController.presentOptionsMenu(from: view.frame, in: view, animated: true)
}
@IBAction func shareAction(_ sender: UIButton) {
guard let url = URL(string: "https://www.ibm.com/support/knowledgecenter/SVU13_7.2.1/com.ibm.ismsaas.doc/reference/AssetsImportCompleteSample.csv?view=kc") else { return }
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else { return }
let tmpURL = FileManager.default.temporaryDirectory
.appendingPathComponent(response?.suggestedFilename ?? "fileName.csv")
do {
try data.write(to: tmpURL)
DispatchQueue.main.async {
self.share(url: tmpURL)
}
} catch {
print(error)
}
}.resume()
}
}
extension URL {
var typeIdentifier: String? {
return (try? resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier
}
var localizedName: String? {
return (try? resourceValues(forKeys: [.localizedNameKey]))?.localizedName
}
}
edit/update:
If you would like to expose the files located on your App Bundle's document directory you can check this post How can I display my App documents in the Files app for iPhone
How can I display my App documents in the Files app for iPhone
If you would like to expose your App document files inside Apple's Files App you need to include the "Supports Document Browser"
key in your info plist file and set it to YES:
How to save document to Files App in swift
If you have access to your PDFdata
then you could present the user with a UIActivityViewController
where they can then save it to Files
, or share it with any of the other available options:
let activityViewController = UIActivityViewController(activityItems: ["Name To Present to User", pdfData], applicationActivities: nil)
present(activityViewController, animated: true, completion: nil)
How to write files in an iOS app to make them visible to afc protocol?
It seems that what I am trying to find is the Documents
directory in my iOS app's sandbox directory (from documentation).
The directory can be made visible in afc protocol by following this answer,
and this answer gives a good example of writing to a file in that directory.
Share Specific directory in app's Documents with Files app
Before using file system of iOS, Please check the usage of different directories of the iOS file system.
You can refer this link: https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html
As per above link, apple has clearly mentioned that:
For Documents Directory : It clearly says that this directory should only contain files that you may wish to expose to the user.
If you want something that should not be exposed to User, then dont use Documents
directory, instead use Library
directory for this.
For Library
directory: Use the Library subdirectories for any files you don’t want exposed to the user. Your app should not use these directories for user data files.
Here, see the following screenshot from above link, which says about which directory to use when?
In short, keep your root directories content in Document directory and move all other directory with their content to Library directory OR Library/Application Support Directory. So, your intended purpose will get fulfilled.
Create a folder inside documents folder in iOS apps
I do that the following way:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"/MyFolder"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder
Related Topics
How to Fix iOS 12 Safari Cors Preflight Error
How to Show Verification Code Suggestion on Keyboard from Message
Uicollectionview Self Sizing Cells With Auto Layout
How to Increment the Filename If File Already Exists
Disabling Auto-Play in Full Screen on Ios
Updating Configuration Profile Installed in iOS Device in Mdm
Ios Simple Tcp Connection Example
How to Create Custom Calendar in React Native
How to Remove Constraints Programmatically That Is Added from Storyboard
Create Tap-Able "Links" in the Nsattributedstring of a Uilabel
Ios Swift - Objective C Code Migration to Swift
Protocol Can Only Be Used as a Generic Constraint Because It Has Self or Associatedtype Requirements
Ios 7 Status Bar Back to iOS 6 Default Style in Iphone App
Conditional Binding: If Let Error - Initializer For Conditional Binding Must Have Optional Type
How to Hide Keyboard When Using Swiftui
Rotate Scncamera Node Looking At an Object Around an Imaginary Sphere