Preview PDF files on iOS 11.2 - ios

I ran into this bug that prevents my app from displaying PDF using UIDocumentInteractionController or QLPreviewController: https://forums.developer.apple.com/thread/91835
According to the suggestions, the solution is to copy files to documents or tmp folders and load files from there.
However, this does not work for me. Loading the files from .documentDirectory or NSTemporaryDirectory() produces the same error, but now not only on device, but also in simulator.
Edit:
The following code solved the problem for me:
func copyFiles(fileName: String) -> URL {
let filemgr = FileManager.default
filemgr.delegate = self
let tempDocsFolder = URL.init(fileURLWithPath: NSTemporaryDirectory()).path
// my fileName is in format "file.pdf"
let fileSplit = fileName.components(separatedBy: ".")
let filePath = Bundle.main.path(forResource: fileSplit[0], ofType: fileSplit[1])
let destPath = "\(tempDocsFolder)/\(fileName)"
do {
try? filemgr.copyItem(atPath: filePath!, toPath: destPath)
}
return URL.init(fileURLWithPath: destPath)
}
Then returned URL is then feeded to the UIDocumentInteractionController. The reason it didn't work for me before was because I tried to copy my files to /tmp/documents/, but the files must be copied to the root of the tmp folder: /tmp/ (I have no idea why).

Check for case-sensitivity of resources(File names).
Add any screen shots of the code.

Related

How can I create an app icon folder in the files app and copy items to it?

I want to transfer some files (sound, texts, etc.) from an iOS app to the files app. In addition, I want to put all these items into a folder which has the same name as my app - as it is the case with GarageBand or KeyNote, for example.
In Xcode, I did enable the iCloud Documents capability - I did also define a Container "iCloud.xxx.yyy" - see code below.
guard let fileURL = Bundle.main.url(forResource: "test", withExtension: "aiff") else { return }
guard let containerURL = FileManager.default.url(forUbiquityContainerIdentifier: "iCloud.xxx.yyy") else { return }
if !FileManager.default.fileExists(atPath: containerURL.path) {
try FileManager.default.createDirectory(at: containerURL, withIntermediateDirectories: true, attributes: nil)
}
let backupFileURL = containerURL.appendingPathComponent("test.aiff")
if FileManager.default.fileExists(atPath: backupFileURL.path) {
try FileManager.default.removeItem(at: backupFileURL)
try FileManager.default.copyItem(at: fileURL, to: backupFileURL)
} else {
try FileManager.default.copyItem(at: fileURL, to: backupFileURL)
}
When I run my code, it seems to work - anyhow, I can't see nor folder representing my app name, nor "test.aiff" file in the files app. What is wrong with my approach?
You don't need to copy/move any file. What you need is to allow your app documents to be accessible from the other apps. Just go to your Info plist and allow "Supports Document Browser". All documents in your Documents directory will be automatically available there.

Saving a file without document directory ios

hope you are doing good in development. I have a question regarding Zipping currently i am using Zip framework which I am using for zip the all captured image in device but the problem here is I do not want to save the Zip file in document directory instead I wanna save this memory itself. I am struggling since last week please let me know how can we achieve the zipping without saving it in local directory filepath
Also when I captured the image successfully I saved it to local directory using
let documentsDirectory = FileManager.default.urls(for:
.documentDirectory, in: .userDomainMask).first!
let fileName = "image.jpg"
let fileURL = documentsDirectory.appendingPathComponent(fileName)
if let data = UIImageJPEGRepresentation(image, 1.0),
!FileManager.default.fileExists(atPath: fileURL.path) {
do {
// writes the image data to disk
try data.write(to: fileURL)
print("file saved")
} catch {
print("error saving file:", error)
}
}
After when I am trying to send the image before our server I want to make it all one file so I have implemented the Zip (framework)
Here filpathArray meant all captured image in local path
do {
var urls = [URL]()
for i in 0..<(self.filePathArray.count)
{
urls.append(self.filePathArray[i] as! URL)
}
if self.filePathArray.count > 0 {
let zipFiles = try Zip.quickZipFiles(urls, fileName: "AllFiles")
}
}
Here zipping is done successfully but it saved in local path so when using app container I can able to see the images, I do not want to see the images in device like apple sandbox or Xcode container itself
I want to make zipping on the flow like without saving it document directory, Thanks in advance.

Path to pdf in directory with pdfKit

I am starting to use PDFKit, with a pdf file located in the root, it works with the following code:
if let path = Bundle.main.path(forResource: "mypdf1", ofType: "pdf") {
let url = URL(fileURLWithPath: path)
if let pdfDocument = PDFDocument(url: url) {
pdfView.autoScales = true
pdfView.displayMode = .singlePageContinuous
pdfView.displayDirection = .vertical
pdfView.document = pdfDocument
print(path)
}
}
But if I change the pdf file inside a directory for example "mydirectory", it does not work, my code is the following:
if let path = Bundle.main.path(forResource: "mypdf1", ofType: "pdf", inDirectory: "mydirectory") {
let url = URL(fileURLWithPath: path)
if let pdfDocument = PDFDocument(url: url) {
pdfView.autoScales = true
pdfView.displayMode = .singlePageContinuous
pdfView.displayDirection = .vertical
pdfView.document = pdfDocument
}
}
Any suggestions to fix the path problem.
UPDATE
According to the suggestion, try the following code, but I can not visualize the PDF either.
if let documentURL = Bundle.main.url(forResource: "mypdf1", withExtension: "pdf", subdirectory: "mydirectory") {
if let document = PDFDocument(url: documentURL) {
pdfView.autoScales = true
pdfView.backgroundColor = UIColor.lightGray
pdfView.document = document
}
}
Your code to read the pdf from a subdirectory is correct and as I read they get a nil in the path, that's for sure because your container folder has not been created correctly. You can see yellow and blue folder, your container folder should be blue.
To make blue folder you should do following steps:
Prepare folder structure with files in it.
Drag that folder into xcode i.e. project navigation pan.
Select " Create folder references for any added folders " option.
Finally click to add.
You will get that folder with blue color and your code can read the pdf.
There are two types of folders in Xcode: groups and folder references.
You can use groups to organize files in your project without affecting
their structure on the actual file system. This is great for code,
because you’re only going to be working with your code in Xcode. On
the other hand, groups aren’t very good for resource files.
On any reasonably complicated project, you’ll usually be dealing with
dozens – if not hundreds – of asset files, and those assets will need
to be modified and manipulated from outside of Xcode, either by you or
a designer. Putting all of your resource files in one flat folder is a
recipe for disaster. This is where folder references come in. They
allow you to organize your files into folders on your file system and
keep that same folder structure in Xcode.
Blue is used to represent a "Folder Reference".

Where to save and load large files in IOS [duplicate]

This question already has answers here:
Save An Image To Application Documents Folder From UIView On IOS
(6 answers)
Closed 5 years ago.
I want to in my app, be able to allow users to save large images(jpg) as well as data for each image(txt) and load the images/data. I'm having trouble figuring out where to save these images and text files. Userdefault wouldnt work because of the size of the image files and I don't want to save in the documents directory because then the user can access and potentially corrupt the data.
Where is a good place to save large data files for my app so I can load them later?
You can save and retrieve your files in application directory folder. Also you can use iCloud to save your files.
Use below code if you want to save and retrieve files from Directory folder .
Xcode 8.3.2 Swift 3.x. Using NSKeyedArchiver and NSKeyedUnarchiver
Reading file from documents
let documentsDirectoryPathString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let documentsDirectoryPath = NSURL(string: documentsDirectoryPathString)!
let jsonFilePath = documentsDirectoryPath.appendingPathComponent("Filename.json")
let fileManager = FileManager.default
var isDirectory: ObjCBool = false
if fileManager.fileExists(atPath: (jsonFilePath?.absoluteString)!, isDirectory: &isDirectory) {
let finalDataDict = NSKeyedUnarchiver.unarchiveObject(withFile: (jsonFilePath?.absoluteString)!) as! [String: Any]
}
else{
print("File does not exists")
}
Write file to documents
NSKeyedArchiver.archiveRootObject(finalDataDict, toFile:(jsonFilePath?.absoluteString)!)
If for some reason you don't want to use the documents directory, or you want those data in a separate folder, or you don't want to permanently save them, you can also create your own temporary directory
saving data as file in a new directory (swift 3):
func saveToMyDirectory(data: Data, filename: String) {
var tempDirectoryURL = NSURL.fileURL(withPath: NSTemporaryDirectory(), isDirectory: true)
tempDirectoryURL = tempDirectoryURL.appendingPathComponent(filename)
do {
try data?.write(to: tempDirectoryURL)
} catch {}
}
Alternative approach: use Apple's UIDocumentInteractionController or UIActivityViewController and let the user choose how to save his/her documents:
https://developer.apple.com/documentation/uikit/uidocumentinteractioncontroller
https://developer.apple.com/documentation/uikit/uiactivityviewcontroller

How do I count a number of images in a folder reference in swift

I'm working on an custom emoji keyboard in Swift and I'm having trouble finding and counting the images in a folder reference called "emojis".
EDIT: To clarify my issue is that let contents always end up as nil.
The structure from the location of the .xcodeproj file looks like this:
EmojiBoard/emojis/emoji-0.png and so on.
I've been trying to use the NSFileManager with no luck.
let fileManager = NSFileManager.defaultManager()
let contents = fileManager.contentsOfDirectoryAtPath("emojis", error: &error)
println(contents)
This prints nil. I've also tried "EmojiBoard/emojis" and "/EmojiBoard/emojis".
I need this to determine how many images there are and loop them all out without having to resort to an insane switch statement or something like that.
Thank you!
P.S. Please note that I'm coding in Swift, not Objective C. I'm not proficient enough to convert C programming to swift I'm afraid. D.S.
if you created folder reference when adding the folder to your project use it like this (emojis folder icon is a blue folder):
let resourceURL = Bundle.main.resourceURL!.appendingPathComponent("emojis")
var resourcesContent: [URL] {
(try? FileManager.default.contentsOfDirectory(at: resourceURL, includingPropertiesForKeys: nil)) ?? []
}
let emojiCount = resourcesContent.count
print(emojiCount)
if you created groups when adding the folder to your project use it like this (emojis folder icon is a yellow folder):
let resourceURL = Bundle.main.resourceURL!
let resourcesContent = (try? FileManager.default.contentsOfDirectory(at: resourceURL, includingPropertiesForKeys: nil)) ?? []
let emojiCount = resourcesContent.filter { $0.lastPathComponent.hasPrefix("emoji-") }.count
print(emojiCount)
From the top of my head, without access to an IDE to test this code, I reckon something like this:
let fileManager = NSFileManager.defaultManager()
let contents = fileManager.contentsOfDirectoryAtPath(path, error: &error)
for var index = 0; index < contents.count; ++index {
println("File is \(contents[index])")
}
If you replace 'path' above with your documents directory, this code should loop through the whole folder and print out all files.
If you just want the count of items just do this:
println("count is \(contents.count)")
The problem (or at least a major part of the problem) is your path. You can't pass in a path that's just a filename. You need an absolute path to one of the sandboxed directories available to your app like the documents directory.
Your code might look like this:
let documentsDir = NSSearchPathForDirectoriesInDomains(
NSSearchPathDirectory.DocumentDirectory,
NSSearchPathDomainMask.UserDomainMask,
true)[0] as! NSString
let emojisPath = documentsDir.stringByAppendingPathCompnent("emojis")
let contents = fileManager.contentsOfDirectoryAtPath(emojisPath,
error: &error)
println(contents)
(That would work if your emojis folder is in your app's documents folder. If instead your emojis are in your app bundle (built into the app) you would need to use different code entirely (using NSBundle functions to get a path to the directory inside the bundle).
EDIT:
If you want to find files in your app's bundle use the NSBundle method resourcePath, and then append the folder name to the bundle's resourcePath using stringByAppendingPathCompnent, like the code above.

Resources