UIDocumentPickerViewController - Delegate method not being called - ios

I'm using UIDocumentPickerViewController to select documents from the Files and upload it to a server. I'm able to successfully access Files, but upon clicking on the file the delegate method doesn't get called.
I've used the following code to call the document picker:
class Uploads: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func uploadDocument(_ sender: Any) {
let documentPicker = UIDocumentPickerViewController(documentTypes: [String(kUTTypePDF), String(kUTTypePlainText)], in: .import)
documentPicker.delegate = self
if #available(iOS 11.0, *) {
documentPicker.allowsMultipleSelection = false
} else {
}
present(documentPicker, animated: true, completion: nil)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
extension Uploads: UIDocumentPickerDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
print(urls.first)
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
print("Cancelled")
}
}
I noticed that I'm getting the following warning upon calling the delegate method:
Instance method 'documentPicker(:didPickDocumentsAt:)' nearly matches
optional requirement 'documentPicker(:didPickDocumentsAt:)' of
protocol 'UIDocumentPickerDelegate'
Make 'documentPicker(_:didPickDocumentsAt:)' private to silence this
warning
I believe that the delegate method isn't being called due to this warning, although I couldn't figure out why I'm getting this warning.

Sharing code sample hopefully it'll help:
class ViewController : UIViewController,UIDocumentPickerDelegate{
var documentBrowser: UIDocumentPickerViewController = {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let browser = UIDocumentPickerViewController(documentTypes: [documentsPath], in: .open)
browser.allowsMultipleSelection = true
return browser
}()
override func viewDidLoad() {
super.viewDidLoad()
self.addChild(documentBrowser)
documentBrowser.view.frame = self.view.bounds
view.addSubview(documentBrowser.view)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]){
print(urls)
}
}

Problem appears if class which adopts 'UIDocumentPickerDelegate' protocol is declared as 'open'.
For example this class will have a problem:
open class FilePickerHelper: UIDocumentPickerDelegate
while this class will not have a problem:
class FilePickerHelper: UIDocumentPickerDelegate

Related

Cannot load module 'visionKit' as 'VisionKit'

Im trying to build a simple app to scan documents, but faced this error when trying to import VisionKit module, how can i solve this error ?
My code:
import UIKit
import VisionKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func openCameraButtonTaped(_ sender: Any) {
configureDocumentView()
}
private func configureDocumentView() {
let scaningDocumentViewController = VNDocumentCameraViewController()
scaningDocumentViewController.delegate = self
self.present(scaningDocumentViewController, animated: true, completion: nil)
}
}
extension ViewController: VNDocumentCameraViewControllerDelegate {
func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
for pageNum in 0..<scan.pageCount {
let image = scan.imageOfPage(at: pageNum)
print(image)
}
controller.dismiss(animated: true, completion: nil)
}
}
You are giving a hard time for the compiler, your project name conflicts with Apple's VisionKit. Create a new your project with a different name.

documentPicker delegate not called by UIDocumentPickerViewController

I have the following ViewController that implements functionality for importing files into the app using the UIDocumentPickerViewController:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
func importFromFiles(origin: UIViewController?) {
let documentPicker = UIDocumentPickerViewController(documentTypes: [kUTTypeContent as String], in: .import)
documentPicker.delegate = self
documentPicker.allowsMultipleSelection = true
origin?.present(documentPicker, animated: true, completion: nil)
}
}
As you can see, the importFromFiles method receives a ViewController, which is simply the active VC. This method is called from the AppDelegate.
For now, the documentPicker method looks just as follows:
extension MyViewController: UIDocumentPickerDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
print("Files picked")
}
}
The picker is displayed and dismissed correctly, but the delegate is never called and therefore the print never executed.
Edit 1
The call to the importFromFiles method is happening inside the AppDelegate. More specifically, it happens while defining a closure for a SwiftTweaks tweak:
MyTweaks.importFromFiles.addClosure {
let topViewController = visibleViewController(root: self.window?.rootViewController)
let myVC: MyViewController = MyViewController()
myVC.importFromFiles(origin: topViewController)
}
It appears you need to retain the main object as you have
let myVC: MyViewController = MyViewController()
myVC.importFromFiles(origin: topViewController)
inside where you present that picker here MyViewController() isn't retained so make it an instance var like
var main = MyViewController()
main.importFromFiles(origin:self)

iOS Swift, what is the url of the "on my iPhone" folder

I need to import to my app some document that have been saved into the "On My iPhone" folder. What would be the url of this folder? (those document (pdf) are saved outside the app by the user and I would like if possible to move/copy them to the app document folder but again I can't find that url.
Try this code (the way to pick needed document from iPhone Folder:
extension YourViewController: UIDocumentInteractionControllerDelegate {
/// If presenting a top a navigation stack, provide the navigation controller in order to animate in a manner consistent with the rest of the platform
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self.navigationController ?? self
}
}
extension YourViewController : UIDocumentPickerDelegate {
func initDocs() {
let pickerController = UIDocumentPickerViewController(documentTypes: ["public.item"], in: .import)
pickerController.delegate = self
if #available(iOS 11.0, *) {
pickerController.allowsMultipleSelection = false
}
present(pickerController, animated: false, completion: nil)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
if let url = urls.first {
self.handleDoc(url: url) // method in your view controller
}
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
print("url = \(url)")
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
dismiss(animated: true, completion: nil)
}
}
In YourViewController call function:
#IBAction func importPem(_ sender: UIButton) {
initDocs()
UIDocumentInteractionController().presentPreview(animated: true)
}

swift: iClouds Documents seems to be disabled when loaded from custom application

i am trying to upload the PDF files from iCloud in my custom application. But as i move to iCloud from my application the documents cannot be selected it seems like as if they are disabled. Most of all the explanations are in Obj-C so i could no understand exactly.
What is wrong here? This is my code in swift2:
import UIKit
import MobileCoreServices
class ViewController: UIViewController, UIDocumentPickerDelegate, UITextViewDelegate {
#IBOutlet weak var emailButton: UIButton!
#IBOutlet weak var UITextField: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func handleImportPickerPressed(sender: AnyObject) {
let documentPicker = UIDocumentPickerViewController(documentTypes: [kUTTypeText as NSString as String], inMode: .Import)
documentPicker.delegate = self
presentViewController(documentPicker, animated: true, completion: nil)
}
func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL) {
print(url)
}
They are disable means that document types you have in your iCloud does not match while your are selecting.Use documents types as:
#IBAction func handleImportPickerPressed(sender: AnyObject) {
let documentPicker = UIDocumentPickerViewController(documentTypes:["public.data", "public.text"],inMode: UIDocumentPickerMode.Import)
documentPicker.delegate = self
documentPicker.modalPresentationStyle = UIModalPresentationStyle.FormSheet
presentViewController(documentPicker, animated: true, completion: nil)
}
There are many other document types. They are disable means that they cannot be read by the documentTypes you are passing.

iOS Swift how to tell the UIView Controller that we received information via a NSURLProtocol object

I created a class that implements NSURLProtocol which will tells me about the UIWebView requests. I am looking to tell the UI that we hit a URL of interest and run code back on the ViewController to access the WebView.
I believe Protocols are the solution but cant seem to wrap my head around how to get this to work. Any suggestions and code example would be much appreciated. Here is what I've tried so far.
UI View Controller.swift
class WebViewController: UIViewController,WebAuthDelegate {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string: "http://example.com")
let request = NSURLRequest(URL: url!)
webView.loadRequest(request)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func onBackClick(sender: AnyObject) {
if(webView.canGoBack){
webView.goBack()
}
}
#IBAction func onFwdClick(sender: AnyObject) {
if(webView.canGoForward){
webView.goForward()
}
}
#IBAction func onRefresh(sender: AnyObject) {
webView.reload()
}
func getUserToken() {
print("RUN THIS AFTER I HIT URL IN URL PROTOCAL CLASS")
}
}
Here is my NSURLProtocol implemented class along with the attempted protocol(which please tell me if its the wrong approach)
class CUrlProtocol: NSURLProtocol {
//let delegate: WebAuthDelegate? = nil
override class func canInitWithRequest(request: NSURLRequest) -> Bool {
print("URL = \(request.URL!.absoluteString)")
if request.URL!.absoluteString == "http://api-dev.site.com/token" {
//Tell the UI That we now have the info and we can access the UIWebView Object
}
return false
}
}
protocol WebAuthDelegate{
func getUserToken()
}
The best way to achieve this would probably be to post an NSNotification from your protocol when you match the URL.
In CUrlProtocol, when you find a match (notification name can be your choosing):
let notification:NSNotification = NSNotification(name: "MyURLMatchedNotification", object: nil)
NSNotificationCenter.defaultCenter().postNotification(notification)
In your WebViewController:
// During init (or viewDidAppear, if you only want to do it while its on screen)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "getUserToken", name: "MyURLMatchedNotification", object: nil)
...
// During dealloc (or viewWillDisappear)
NSNotificationCenter.defaultCenter().removeObserver(self, name: "MyURLMatchedNotification", object: nil)
You can also pass something with your notification, if you need information from that request. Just set the object parameter when you create your notification and change your getUserToken to accept a single parameter that has a type of NSNotification and access its object property.

Resources