How to create a Cancel button on the screen that selects the file on Swift5?

I am using UIDocumentBrowser to retrieve files. But I am not able to place a back or cancel button in the navigation bar.



I want to make a cancellation button for this but I can't make a cancellation button. How can I solve this problem?



current code

~~~swift

import Foundation
import UIKit


@available(iOS 11.0, *)
class DocumentBrowserViewController : UIDocumentBrowserViewController, UIDocumentBrowserViewControllerDelegate {
   
    override func viewDidLoad() {
        super.viewDidLoad()
       
         delegate = self
       
         browserUserInterfaceStyle = .dark
         view.tintColor = .white
    }
       
    func documentBrowser(_ controller: UIDocumentBrowserViewController, didRequestDocumentCreationWithHandler importHandler: @escaping (URL?, UIDocumentBrowserViewController.ImportMode) -> Void) {
        let newDocumentURL: URL? = nil
       
        // Set the URL for the new document here. Optionally, you can present a template chooser before calling the importHandler.
        // Make sure the importHandler is always called, even if the user cancels the creation request.
        if newDocumentURL != nil {
            importHandler(newDocumentURL, .move)
        } else {
            importHandler(nil, .none)
        }
    }
   
    func documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentURLs documentURLs: [URL]) {
        guard let sourceURL = documentURLs.first else { return }
       
        do{
           try presentDocument(at: sourceURL)
        } catch {
            Log.Debug("\(error)")
        }
    }
   
    func documentBrowser(_ controller: UIDocumentBrowserViewController, didImportDocumentAt sourceURL: URL, toDestinationURL destinationURL: URL) {
        // Present the Document View Controller for the new newly created document
        do{
            try presentDocument(at: sourceURL)
        } catch {
            Log.Debug("\(error)")
        }
    }
   
    func documentBrowser(_ controller: UIDocumentBrowserViewController, failedToImportDocumentAt documentURL: URL, error: Error?) {
        // Make sure to handle the failed import appropriately, e.g., by presenting an error message to the user.
    }
   
    func presentDocument(at documentURL: URL) throws {
        guard documentURL.startAccessingSecurityScopedResource() else {
            throw IXError.fileAcessFailed
        }
       
        let storyBoard = UIStoryboard(name: "Main", bundle: nil)
        let documentViewController = storyBoard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
       
        documentViewController.document = Document(fileURL: documentURL)
    }
}

~~~



picture of cancellation button that I want

https://ibb.co/KVT2qpj

Replies

Looking at documentation, I see there are already buttons over the search bar.


How do you fit your Cancel within them ?


https://developer.apple.com/documentation/uikit/uidocumentbrowserviewcontroller


Cancel is supposed to Cancel what action ?

What do you mean there's a button over the search bar? If you're talking about a picture I've captured, it's the shape of a button I want, not my current picture.


I learned about the UIDocumentBrowserViewController class and succeeded in adding buttons. but The button has been created but is in a strange position. I want to put the Cancel button in the Select button position.


Code with button added

  override func viewDidLoad() {
  super.viewDidLoad()

  browserUserInterfaceStyle = .dark
  view.tintColor = .white
  let cancelbutton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: nil )
  additionalTrailingNavigationBarButtonItems = [cancelbutton]

  }

The screen where I added the current button.


https://ibb.co/ySTrXcp

What do you mean there's a button over the search bar?


I spoke of the image in the referenced link: https://developer.apple.com/documentation/uikit/uidocumentbrowserviewcontroller


There are several buttons above the search bar.

I do not see them in your first screen shot.


But they show on the new one.

I think your problem is that the Cancel is added to the list, but at the end of the array (append to the existing one, Select).

Hence, they are drawn : Select at right, then Cancel in next position, on its left.


You could tryto:

- retrieve the array of buttons

var existingButtons = navigationItem.rightBarButtonItems

- add the new button at pos 0

existingButtons.insert(cancelbutton, at: 0)

then set the right buttons:

navigationItem.rightBarButtonItems = existingButtons

Note: I did not test.


May also have a look here:

h ttps://www.hackingwithswift.com/example-code/uikit/how-to-add-a-bar-button-to-a-navigation-bar

The first screen shot shows a picture of the button position that I want.

The second screen shot shows my app applying the code I added. And I have succeeded in erasing by adding another code because I don't need a Plus button at the moment, and I want to erase the Select button or put my Cancel button in the location of the Select button.


My current code

~~~swift

overridefunc viewDidLoad() {
        super.viewDidLoad()
        delegate = self
        allowsDocumentCreation = false
        allowsPickingMultipleItems = false
        browserUserInterfaceStyle = .dark
        view.tintColor = .white
        let cancelbutton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action:#selector(cancelButton(sender:)))
        additionalTrailingNavigationBarButtonItems = [cancelbutton]
    }

~~~

My current ScreenShot

https://ibb.co/Rg6Wm5w



And I tried to execute the code you suggested, but an error occurred.

var existingButtons = navigationItem.rightBarButtonItems
        existingButtons.insert(cancelbutton, at: 0) 
        navigationItem.rightBarButtonItems = existingButtons

get Error : Value of type '[UIBarButtonItem]?' has no member 'insert'

>or put my Cancel button in the location of the Select button.


That scheme puts your app at risk of rejection during review.


Note the HIGs say this about that (emphasis mine):


"In general, buttons people are most likely to tap should be on the right. Cancel buttons should always be on the left. Label cancellation buttons appropriately. A button that cancels an alert's action should always be labeled Cancel."



https://developer.apple.com/design/human-interface-guidelines/ios/views/alerts/

Normal, it is an optional.


Replace with:

if var existingButtons = navigationItem.rightBarButtonItems {
        existingButtons.insert(cancelbutton, at: 0)  
        navigationItem.rightBarButtonItems = existingButtons 
}
let cancelbutton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action:#selector(cancelButton(sender:)))
  
        if var existingButtons = navigationItem.rightBarButtonItems {
                existingButtons.insert(cancelbutton, at: 0)
                navigationItem.rightBarButtonItems = existingButtons
        }

I tried this, but the select button did not disappear, and the cancel button was not visible.

So, try to insert at pos 1.

pos 1?? What dose mean pos 1?? I don't understand