UIDocumentPickerViewController error after closing - ios

I am using a DocumentPickerViewController to import a document in my app. The picker does it's work, there are no bugs and no crashes but every time after a document is picked or the view controller is canceled I get a log with the following error:
[DocumentManager] The view service did terminate with error:
Error Domain=_UIViewServiceErrorDomain Code=1 "(null)"
UserInfo={Terminated=disconnect method}
This is the function where the picker VC will be presented:
#IBAction func presentDocumentPicker(_ sender: Any) {
let documentPicker = UIDocumentPickerViewController(documentTypes: ["com.adobe.pdf"], in: .import)
documentPicker.delegate = self
present(documentPicker, animated: false, completion: nil)
}
This is the delegate extension:
extension ViewController: UIDocumentPickerDelegate {
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
print(url)
}
public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
print("Canceled")
}
}
I also tried using the UIDocumentBrowserViewController but I get the same log. Another thing I tried is enabling the iCloud entitlements but there is no change. With a nav controller and just pushing the DocumentPicker renders the same result. Every test I did was built on both a real device and a simulator.
Is there anything I'm doing wrong? Is there anyway I can get rid of that log showing up?

Related

Error while closing the UIDocumentPicker

I am trying to initiate DocumentPicker in my app. I have declared:
var documentPicker: UIDocumentPickerViewController =
UIDocumentPickerViewController(documentTypes:
["public.text"], in: UIDocumentPickerMode.open)
documentPicker.delegate = self
documentPicker.modalPresentationStyle =
UIModalPresentationStyle.fullScreen
self.present(documentPicker, animated: true, completion: nil)
}
and for picked document:
func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL) {
if controller.documentPickerMode == UIDocumentPickerMode.exportToService {
//do some stuff
}
dismiss(animated: true, completion: nil)
}
However i am doing something wrong here. Whenever i choose a file or close the window I keep getting this error:
viewServiceDidTerminateWithError: Error Domain=_UIViewServiceErrorDomain Code=1 "(null)" UserInfo={Terminated=disconnect method}.
I have tried looking for a solution but i couldn't find anything useful.
EDIT: I have included a couple of print("test") into the documentPicker function to see if it is working. However i get 0 response from the console. Maybe I have implemented documentPicker in a bad way?
I, too, get this error message but not all the time.
I noticed the documentPicker is deprecated. Try this:
func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL urls: [URL]) {
if controller.documentPickerMode == UIDocumentPickerMode.exportToService {
//do some stuff
}
}
There's no need to have the dismiss statement. The picker is closed automatically.
Try this and see if it works.

which is this controller in iOS

I was surfing some site in safari. it was attachment button. when I clicked on that button. it showed this controller. Can any1 tell me which is this default functionality safari provide. it is dere in various apps too like slack.
its shows icloud/google drive/dropbox all three in one action.
It is UIDocumentPickController. Check the apple developer documentation
let documentPicker: UIDocumentPickerViewController = UIDocumentPickerViewController(documentTypes: ["public.text"], in: UIDocumentPickerMode.import)
documentPicker.delegate = self
documentPicker.modalPresentationStyle = UIModalPresentationStyle.formSheet
self.present(documentPicker, animated: true, completion: nil)
And delegate
// MARK: - UIDocumentPickerDelegate Methods
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
if controller.documentPickerMode == UIDocumentPickerMode.import {
// This is what it should be
// self.newNoteBody.text = String(contentsOfFile: url.path!)
}
}
After adding the code you should check this post too or else you will get an exception. You should go to capabilities & turn iCloud capabilities on. Add icloud containers also there
UIDocumentMenuController is the same as UIDocumentPickerViewController. But its deprecated. check the developer documentation here

UIDocumentMenuViewController blank Options

I have a problem with iCloud file import
I'm getting empty options after I choose the place to import from (iCloud, google drive, dropbox ... etc)
I have data on iCloud drive and the entitlements are right
So what is wrong with this code or is there anything about the settings may cause this problem?
here is the code
#IBAction func selectionButtonAction(_ sender: Any) {
let types = [kUTTypePDF as String ,kUTTypePNG as String, kUTTypeImage as String,kUTTypeJPEG as String]
UINavigationBar.appearance().isTranslucent = true
let documentMenu = UIDocumentMenuViewController(documentTypes: types, in: .import)
documentMenu.delegate = self
self.viewController?.present(documentMenu, animated: true, completion: nil)
}
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentMenu.delegate = self
self.viewController?.present(documentMenu, animated: true, completion: nil)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
if controller.documentPickerMode == .import {
// do staff
}
}
Here is what I get When I run the app on iOS 10
When I Press choose File
then after pressing on iCloud
That's what I get if I run the app on iOS 9:
I'm sure I have data there like here in the iCloud Drive application
And the entitlement
I had the same problem, when trying to present a already used Instance of the UIDocumentMenuViewController.
I was instantiating it lazily like this:
lazy var documentMenuController: UIDocumentMenuViewController = {
let controller = UIDocumentMenuViewController(documentTypes: ["com.adobe.pdf"], in: .import)
controller.delegate = self
return controller
}()
Which produced this error every time except the first time.
So I changed the code to this:
var documentMenuController: UIDocumentMenuViewController {
let controller = UIDocumentMenuViewController(documentTypes: ["com.adobe.pdf"], in: .import)
controller.delegate = self
return controller
}
To obtain a fresh instance on every access of the property.

MFMailComposeViewControllerDelegate not working Swift 3

I have been using the mail composer in a few of my apps for awhile now and as of recent the mailComposeDelegate no longer gets call.I wasn't sure if this was something to do with the new release of Swift. So, I thought I would ask and see if anyone else is having similar issues.I can present the mail composer but it never gets dismissed due to the delegate not working.
Below is an exact copy of the code I have been using:
func launchFeedback() {
guard MFMailComposeViewController.canSendMail() else {
return
}
let emailTitle = "Feedback"
let messageBody = ""
let toRecipents = ["johnappleseed#icloud.com"]
mailComposer.mailComposeDelegate = self
mailComposer.setSubject(emailTitle)
mailComposer.setMessageBody(messageBody, isHTML: false)
mailComposer.setToRecipients(toRecipents)
self.show(mailComposer, sender: self)
}
func mailComposeController(controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
print(error)
controller.dismiss(animated: true, completion: nil)
}
This is clearly an Xcode bug. The only way to get around this (after searching though StackOverflow life for an hour) was this:
#objc(mailComposeController:didFinishWithResult:error:)
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult,error: NSError?) {
controller.dismiss(animated: true)
}
See the #objc macro before the method implementation. Also note that the last parameter has to be NSError type instead of Error as suggested by Apple documentation (and autocompleted by Xcode)
Swift 3 no longer has unnamed first parameters by default (see this proposal), so you'll need to add an underscore to your function:
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
print(error)
controller.dismiss(animated: true, completion: nil)
}
Swift 4, Xcode 9.1.
My issue was that MFMailComposeViewController was working fine but if you click cancel, dismiss, and then trying to open it one more time both cancel and send button will not fire didFinishWith delegate function.
It was happening because I've declared MFMailComposeViewController as lazy variable and solution was to create new instance of MFMailComposeViewController every time you want to open it.
Problem:
lazy var mailComposeViewController: MFMailComposeViewController = {
let mailComposeViewController = MFMailComposeViewController()
mailComposeViewController.mailComposeDelegate = self
mailComposeViewController.setToRecipients(["example#test.test"])
mailComposeViewController.setSubject("subject")
mailComposeViewController.setMessageBody("test body", isHTML: false)
return mailComposeViewController
}()
Solution:
func createMailComposeViewController() -> MFMailComposeViewController {
let mailComposeViewController = MFMailComposeViewController()
mailComposeViewController.mailComposeDelegate = self
mailComposeViewController.setToRecipients(["example#test.test"])
mailComposeViewController.setSubject("subject")
mailComposeViewController.setMessageBody("test body", isHTML: false)
return mailComposeViewController
}
After wasting 2 good hours, i came to the conclusion that as of Xcode 8.3. MFMailComposeViewController does not work on a mixed swift/objc code base. It pops odd compile errors, which first i thought were due to my stupidity, but no.
This is so frustrating apple. Most of us old timers do have tons of code on obj-c, so a pure swift scenario is close to impossible. So as i move classes to swift i have to deal with extra pain as well.
Adding
#import <MessageUI/MessageUI.h>
to the AppName-Bridging-Header.h did the job !

How to access Cloud drives to import files to my app in swift?

I want to get documents from Cloud services like iCloud , google drive and dropbox on a button click (like in WhatsApp screenshot below), does anyone know how to do it in swift ? Thanks in advance
From your project's capabilities. First enable both the iCloud services and the Key-Sharing, import MobileCoreServices in your class and finally extended the following three classes inside your UIViewController :
UIDocumentMenuDelegate,UIDocumentPickerDelegate,UINavigationControllerDelegate
Implement the following functions :
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
let myURL = url as URL
print("import result : /(myURL)")
}
public func documentMenu(_ documentMenu:UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
print("view was cancelled")
dismiss(animated: true, completion: nil)
}
How to call all of this? Add the following bit of code to your click function..
func clickFunction(){
let importMenu = UIDocumentMenuViewController(documentTypes: [String(kUTTypePDF)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil)
}
Click your button. The following menu will pop up ..
In the case of DropBox. Upon clicking on any item. You will be redirected back to your app and the URL will be logged in your terminal.
Manipulate the documentTypes to your need. In my app, Users permitted to Pdf only. So, suit yourself.
kUTTypePDF
Also if you feel like customizing your own menu bar. Add the following code and customize your own function inside the handler
importMenu.addOption(withTitle: "Create New Document", image: nil, order: .first, handler: { print("New Doc Requested") })
Enjoy it.
First enable iCloud documents Capabilitie, see Apple documentation here
The you have to use UIDocumentMenuViewController
let importMenu = UIDocumentMenuViewController(documentTypes: doctypes, inMode: .Import)
importMenu.delegate = self
importMenu.popoverPresentationController?.barButtonItem = self.addButon;
self.presentViewController(importMenu, animated: true, completion: nil)

Resources