State Customization
PDFViewController
can be in five different states:
- Default (showing a PDF document)
- Loading
- Empty
- Locked (password-protected PDF document)
- Error
Take a look at ControllerState
for more information.
You can change the state’s strings and images or you can set PDFViewController.overlayViewController
to take care of state handling yourself.
To create an overlay view controller, you have to implement the ControllerStateHandling
protocol in a UIViewController
subclass.
Implementing all of the states, with the exception of locked, is pretty straightforward, because they don’t feature any interaction. To unlock documents, you need to add a text field and handle the keyboard accordingly. Use Document.unlock(withPassword:)
to unlock the document. After that, you need to reload the PDFViewController
with reloadData()
.
The following code snippets should help you create your own overlay view controller correctly:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | class OverlayViewController: UIViewController, ControllerStateHandling { // MARK: Properties weak var pdfController: PDFViewController! private let label: UILabel = { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.numberOfLines = 0 label.textColor = .gray label.textAlignment = .center return label }() private let textField: UITextField = { let textField = UITextField() textField.translatesAutoresizingMaskIntoConstraints = false textField.isSecureTextEntry = true textField.autocorrectionType = .no textField.autocapitalizationType = .none textField.borderStyle = .roundedRect return textField }() private let button: UIButton = { let button = UIButton(type: .system) button.translatesAutoresizingMaskIntoConstraints = false button.setTitle("Unlock", for: .normal) button.setTitleColor(.blue, for: .normal) button.sizeToFit() return button }() // MARK: UIViewController override func viewDidLoad() { super.viewDidLoad() button.addTarget(self, action: #selector(unlock), for: .touchUpInside) let stackView = UIStackView(arrangedSubviews: [label, textField, button]) stackView.translatesAutoresizingMaskIntoConstraints = false stackView.axis = .vertical stackView.distribution = .fillEqually stackView.spacing = 20 view.addSubview(stackView) NSLayoutConstraint.activate([ stackView.widthAnchor.constraint(equalToConstant: 300), stackView.heightAnchor.constraint(equalToConstant: 150), stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor), stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor) ]) } // MARK: Button Actions @objc private func unlock(sender: UIButton) { guard let document = document, let password = textField.text else { return } document.unlock(withPassword: password) pdfController.reloadData() } // MARK: ControllerStateHandling var document: Document? public func setControllerState(_ state: ControllerState, error: Error?, animated: Bool) { var text = "" var backgroundColor: UIColor? = .white switch state { case .default: backgroundColor = nil case .empty: text = "No document set" case .loading: text = "Loading..." case .locked: text = "Password:" case .error: text = "Unable to display document:\n\(error!.localizedDescription)" } label.text = text view.backgroundColor = backgroundColor view.isUserInteractionEnabled = state != .default if state == .locked { textField.isHidden = false button.isHidden = false textField.becomeFirstResponder() } else { textField.isHidden = true button.isHidden = true textField.resignFirstResponder() } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | @interface OverlayViewController : UIViewController <PSPDFControllerStateHandling> @property (nonatomic, weak) PSPDFViewController *pdfController; @end @interface OverlayViewController () @property (nonatomic) UILabel *label; @property (nonatomic) UITextField *textField; @property (nonatomic) UIButton *button; @end @implementation OverlayViewController #pragma mark - UIViewController -(void)viewDidLoad { [super viewDidLoad]; self.label = [UILabel new]; self.label.translatesAutoresizingMaskIntoConstraints = NO; self.label.numberOfLines = 0; self.label.textColor = [UIColor grayColor]; self.label.textAlignment = NSTextAlignmentCenter; self.textField = [UITextField new]; self.textField.translatesAutoresizingMaskIntoConstraints = NO; self.textField.secureTextEntry = YES; self.textField.autocorrectionType = UITextAutocorrectionTypeNo; self.textField.autocapitalizationType = UITextAutocapitalizationTypeNone; self.textField.borderStyle = UITextBorderStyleRoundedRect; self.button = [UIButton buttonWithType:UIButtonTypeSystem]; self.button.translatesAutoresizingMaskIntoConstraints = NO; [self.button setTitle:@"Unlock" forState:UIControlStateNormal]; [self.button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [self.button sizeToFit]; [self.button addTarget:self action:@selector(unlock:) forControlEvents:UIControlEventTouchUpInside]; UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[self.label, self.textField, self.button]]; stackView.translatesAutoresizingMaskIntoConstraints = NO; stackView.axis = UILayoutConstraintAxisVertical; stackView.distribution = UIStackViewDistributionFillEqually; stackView.spacing = 20; [self.view addSubview:stackView]; [NSLayoutConstraint activateConstraints:@[ [stackView.widthAnchor constraintEqualToConstant:300], [stackView.heightAnchor constraintEqualToConstant:150], [stackView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], [stackView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor] ]]; } #pragma mark - Button Actions - (void)unlock:(id)sender { NSString *password = self.textField.text; [self.document unlockWithPassword:password]; [self.pdfController reloadData]; } #pragma mark - PSPDFControllerStateHandling @synthesize document; -(void)setControllerState:(PSPDFControllerState)state error:(NSError *)error animated:(BOOL)animated { NSString *text = @""; UIColor *backgroundColor = [UIColor whiteColor]; switch (state) { case PSPDFControllerStateDefault: backgroundColor = nil; break; case PSPDFControllerStateEmpty: text = @"No document set"; break; case PSPDFControllerStateLoading: text = @"Loading..."; break; case PSPDFControllerStateLocked: text = @"Password:"; break; case PSPDFControllerStateError: text = [NSString stringWithFormat:@"Unable to display document:\n%@", error.localizedDescription]; break; default: break; } self.label.text = text; self.view.backgroundColor = backgroundColor; self.view.userInteractionEnabled = state != PSPDFControllerStateDefault; if (state == PSPDFControllerStateLocked) { self.textField.hidden = NO; self.button.hidden = NO; [self.textField becomeFirstResponder]; } else { self.textField.hidden = YES; self.button.hidden = YES; [self.textField resignFirstResponder]; } } @end |
1 2 3 4 | let pdfController = PDFViewController(document: document) let overlayViewController = OverlayViewController() overlayViewController.pdfController = pdfController pdfController.overlayViewController = overlayViewController |
1 2 3 4 | PSPDFViewController *pdfController = [[PSPDFViewController alloc] initWithDocument:document]; OverlayViewController *overlayViewController = [OverlayViewController new]; overlayViewController.pdfController = pdfController; pdfController.overlayViewController = overlayViewController; |