No matter what I do, status bar keeps coming when i open image picker and won't go away after it is dismissed. I tried various swift solutions I was able to read on this site that are supposed to be fix the problem, but it won't help at all.
Here is what I do. I subclass the picker controller:
class MyImagePickerController: UIImagePickerController {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.setNeedsStatusBarAppearanceUpdate()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.setNavBar()
}
override func prefersStatusBarHidden() -> Bool {
self.setNavBar()
return true
}
override func childViewControllerForStatusBarHidden() -> UIViewController? {
return nil;
}
func setNavBar() -> Void {
self.setNavBar(65)
}
func setNavBar(height: CGFloat) -> Void {
var frame = self.navigationBar.frame;
frame.size.height = height;
self.navigationBar.frame = frame;
}
}
then I to call it from an IBoutled action:
func chooseImageFromGallery() {
var image = MyImagePickerController()
image.delegate = self
image.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
image.allowsEditing = false
self.presentViewController(image, animated: true, completion: nil)
}
Also, of course, I set the bar hidden in the Plist file. Problem is specifically when calling the picker controller.
Please answer in Swift.
Use below code to do this
import Foundation
extension UIImagePickerController {
override public func prefersStatusBarHidden() -> Bool {
return true
}
}
this is an extention(category) of UIImagePickerController and works for me.
Related
I am fairly new to iOS and am a bit stuck on this issue. The problem is that when I rotate the device from landscape to portrait in SFSafariViewcontroller the DONE button gets pushed up. See image here:
I thought about maybe recalculating the height and width in viewWillTransistion but I am honestly not sure what to do. The App is portrait only and only this ViewController should be rotated.
My Safari View Controller:
extension SFSafariViewController {
convenience init(url URL: URL, entersReaderIfAvailable: Bool) {
let configuration = SFSafariViewController.Configuration()
configuration.entersReaderIfAvailable = entersReaderIfAvailable
self.init(url: URL, configuration: configuration)
}
}
public class MySafariViewController: SFSafariViewController {
public var isIdleTimerDisabled: Bool = false
public override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if size.height > size.width {
Logging.debug("We are in portrait mode currently. Transitioning to landscape")
} else {
Logging.debug("We are in landscape mode currently. Transitioning to portrait")
}
}
public override func viewDidLoad() {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
appDelegate.allowRotateAlways = true
self.view.insetsLayoutMarginsFromSafeArea = true
}
public override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if isIdleTimerDisabled {
UIApplication.shared.isIdleTimerDisabled = true
}
}
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
public override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isIdleTimerDisabled { // for the case if it's been true at the startup
UIApplication.shared.isIdleTimerDisabled = false
}
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
appDelegate.allowRotateAlways = false
}
public override var shouldAutorotate: Bool {
return true
}
}
I am allowing rotation by setting the allowRotateAlways variabel to true. The variabel is used in AppDelegate in the func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {} function to change the orientation. So orientation change works i.e going from portrait to landscape and vice versa, but I am unsure why I get these side effects.
I am trying to present QLPreviewController as one of the Tab in a Tabview contorller. It able to show PDF properly but pencilkit/Markup not shown
Reason: i want to show PencilKit to draw on the PDF and save it (other type of files from local or network also hence QL), also capture highlights from PDF(others)
Xcode 12.3
Swift 5
iOS/iPAD: 14
problem:
Q1) Unable to view Markup or edit button at the stop of PDF files. Tried hiding tab bar and subviews are always nil. Any help is appreciated.
Q2) Is it possible to override Highlight sector/function in menuItem (on PDF i see nice options so want to use it however want to save the text selection)?
class QLPreviewController2: QLPreviewController {
var toolbars: [UIView] = []
var observations : [NSKeyValueObservation] = []
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
}
extension QLPreviewController2: QLPreviewControllerDelegate {
func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode {
return .updateContents
}
func previewController(_ controller: QLPreviewController, shouldOpen url: URL, for item: QLPreviewItem) -> Bool {
return true
}
func previewController(_ controller: QLPreviewController, didUpdateContentsOf previewItem: QLPreviewItem) {
}
func previewController(_: QLPreviewController, didSaveEditedCopyOf: QLPreviewItem, at: URL) {
}
}
And my TabVC is
class TabVC: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let viewcontollers = viewControllers else {
return
}
let item1 = QLPreviewController2()
item1.dataSource = self
// self.navigationItem.rightBarButtonItems?.append(item1.editButtonItem) //did not work
item1.isEditing = true //did not work
item1.setEditing(true, animated: true)//did not work
let icon1 = UITabBarItem(title: "Title", image: UIImage(named: "doc"), selectedImage: UIImage(named: "doc"))
item1.tabBarItem = icon1
self.viewControllers!.append(item1)
// navigationItem.leftBarButtonItems?.append(item1.editButtonItem) //did not work
}
//Delegate methods
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
print("Should select viewController: \(viewController.title ?? "") ?")
return true;
}
}
extension TabVC: QLPreviewControllerDataSource {
func numberOfPreviewItems(in: QLPreviewController) -> Int {
return 1
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
print("2")
let fileUrl = Bundle.main.url(forResource: "some", withExtension: ".pdf", subdirectory: nil, localization: nil)
let filePreview = PreviewItem2()
filePreview.previewItemURL = fileUrl
return filePreview
}
}
For solving first problem you should embed your QLPreviewController into the UINavigationController and this will consequently show UINavigationBar over QLPreviewController along with bar button items. Then you must append this UINavigationController instance to viewControllers instance property of the UITabBarController.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//...
let item1 = QLPreviewController2()
let nc = UINavigationController(rootViewController: item1)
//...
self.viewControllers!.append(nc)
}
Second problem is hard to define because of your english, but I'm guessing you want some custom functionality which can't be achieved by QuickLook framework.
I have an overlay view to segregate content, I'm checking for authentication in viewWillAppear() and I have a Notification subscribed to my Auth method. If I authenticate before any of my other views appear the overlay does not show up, however it does on the first view and will not go away even after calling removeFromSuperView().
import UIKit
import FirebaseAuth
class ProtectedViewController: UIViewController, ForceSignInBannerDelegate,
SignUpViewControllerDelegate, LoginViewControllerDelegate{
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
NotificationCenter.default.addObserver(self, selector: #selector(checkAuthentication), name: .myNotification, object: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.checkAuthentication()
}
func checkAuthentication() {
let bannerViewController = ForceSignInBanner.instanceFromNib() as! ForceSignInBanner
bannerViewController.delegate = self
if (!AuthenticationService.sharedInstance.isAuthenticated()) {
self.setView(view: bannerViewController, hidden: false)
print("Need to login")
} else if(AuthenticationService.sharedInstance.isAuthenticated()) {
self.setView(view: bannerViewController, hidden: true)
}
}
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: { _ in
view.isHidden = hidden
if hidden {
view.removeFromSuperview()
} else {
self.view.addSubview(view)
}
}, completion: nil)
}
It's because you're trying to remove a new ForceSignInBanner each time. Ideally you should create it once and keep a reference to the ForceSignInBanner created (as an optional property of ProtectedViewController).
Then remove the ForceSignInBanner that you've stored in the property.
class ProtectedViewController: UIViewController, ForceSignInBannerDelegate {
// This lazily loads the view when the property is first used and sets the delegate.
// Ideally you wouldn't force-case the `as` but I've left it for simplicity here.
private lazy var forceSignInBannerView: ForceSignInBanner = {
let forceSignInBannerView = ForceSignInBanner.instanceFromNib() as! ForceSignInBanner
forceSignInBannerView.delegate = self
return forceSignInBannerView
}()
// ... your other code ... //
fun toggleForceSignInBannerViewVisibility(isVisible: Bool) {
if isVisible {
view.addSubview(forceSignInBannerView)
} else {
forceSignInBannerView.removeFromSuperview()
}
}
}
I am using ARCGIS library for GIS features, I wants to achieve basemap gallery like the one show in below picture.
how can I achieve above gallery, I tried to search sample code but did not get anything like shown in above picture.....
if possible if any one has done can give me the link to refer sample code...will be very helpful.
Here is a code for popup galary in IPad
import UIKit
class ViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UIPopoverPresentationControllerDelegate {
var imagePicker = UIImagePickerController()
var popController:UIPopoverPresentationController!
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 btn_action(sender: UIButton) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum) {
self.imagePicker.delegate = self
self.imagePicker.sourceType = UIImagePickerControllerSourceType.SavedPhotosAlbum
self.imagePicker.allowsEditing = true
imagePicker.modalPresentationStyle = UIModalPresentationStyle.Popover
self.presentViewController(self.imagePicker, animated: true, completion: nil)
popController = imagePicker.popoverPresentationController!
popController.permittedArrowDirections = UIPopoverArrowDirection.Up
popController.delegate = self
popController.sourceView = self.view
let contentSize : CGSize = CGSizeMake(500,400)
self.imagePicker.preferredContentSize = contentSize
popController.backgroundColor=UIColor.redColor()
popController.sourceRect = CGRectMake(sender.frame.origin.x + sender.bounds.width/2-5, sender.frame.origin.y+sender.bounds.size.height/2, 10, 10)
}
}
internal override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask
{
return UIInterfaceOrientationMask.Landscape
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
}
func imagePickerControllerDidCancel(picker: UIImagePickerController)
{
imagePicker.dismissViewControllerAnimated(true, completion: nil)
}
}
extension UIImagePickerController
{
public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask
{
return UIInterfaceOrientationMask.Landscape
}
}
The Problem
I have a problem with my split view. It works fine on iPhone and iPad simulators, but on the iPhone 6+ I lose the navigation bar after rotating the device. Here's what happens on the 6+ simulator:
I start the app and it presents a + button in the navigation bar. I tap this button.
It loads a view controller over the existing view. A navigation bar, as expected, is visible with a working back button.
I turn the device horizontally. As intended the new controller appears in the Master section, with an empty detail section on the right. Unfortunately the navigation bar dissapears.
When I turn the device vertically the navigation bar does not reappear.
In fact when I turn the device horizontally it seems the navigation controller is removed from the stack (I've observed this from outputting the contents of splitViewContoller.viewControllers).
My Code
The test application is simply the Master Detail template with a few modifications.
I've added a new "Add Item" controller and then created a show segue from the Master view's "+" button. The "Add Item" controller is blank, just a blue background.
The DetailViewController has a timerStarted boolean value that is true when the detail view is being used and false when it isn't. The master view is hidden when the detail is in use and displayed when it isn't.
Here's the relevant code (there's nothing interesting in AppDelegate as it's no longer a split view delegate, and MasterViewController has no interaction as the button works via the storyboard)
DetailViewController
import UIKit
class DetailViewController: UIViewController, UISplitViewControllerDelegate {
#IBOutlet weak var detailDescriptionLabel: UILabel!
var collapseDetailViewController = true
var detailItem: AnyObject? {
didSet {
self.configureView()
}
}
var timerStarted: Bool = false {
didSet {
self.changeTimerStatus()
}
}
func configureView() {
if let detail: AnyObject = self.detailItem {
if let label = self.detailDescriptionLabel {
label.text = detail.description
self.timerStarted = true
}
}
}
func changeTimerStatus() {
if self.timerStarted {
if splitViewController!.collapsed == false {
UIView.animateWithDuration(0.3, animations: {
self.splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden
})
}
collapseDetailViewController = false
} else {
if splitViewController!.collapsed {
self.splitViewController?.viewControllers[0].popToRootViewControllerAnimated(true)
} else {
UIView.animateWithDuration(0.3, animations: {
self.splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
})
}
collapseDetailViewController = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
splitViewController?.delegate = self
self.disabledScreen.hidden = false
self.view.bringSubviewToFront(disabledScreen)
self.configureView()
}
override func viewWillAppear(animated: Bool) {
if splitViewController!.collapsed == false && self.timerStarted == false {
splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
}
}
#IBAction func closeButton(sender: AnyObject) {
self.timerStarted = false
}
func primaryViewControllerForExpandingSplitViewController(splitViewController: UISplitViewController) -> UIViewController? {
if timerStarted == true {
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden
} else {
splitViewController.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
}
return nil
}
func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController: UIViewController!, ontoPrimaryViewController primaryViewController: UIViewController!) -> Bool {
return collapseDetailViewController
}
}
AddItemViewController
import UIKit
class AddItemViewController: UIViewController, UISplitViewControllerDelegate {
var collapseDetailViewController = false
override func viewDidLoad() {
super.viewDidLoad()
self.splitViewController?.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewDidAppear(animated: Bool) {
self.splitViewController?.delegate = self
self.collapseDetailViewController = false
}
override func viewWillDisappear(animated: Bool) {
self.splitViewController?.delegate = nil
self.collapseDetailViewController = true
}
func primaryViewControllerForExpandingSplitViewController(splitViewController: UISplitViewController) -> UIViewController? {
return self
}
func primaryViewControllerForCollapsingSplitViewController(splitViewController: UISplitViewController) -> UIViewController? {
return nil
}
func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController: UIViewController!, ontoPrimaryViewController primaryViewController: UIViewController!) -> Bool {
return collapseDetailViewController
}
}
I'd be grateful for any suggestions.
I have found the answer. I read a article which I had originally missed because it focuses on changing the detail view rather than the master. As it turns out, the split view works better if I just manage the detail and then the master will take care of itself. Since I never want to change the detail I can simply add the following to my split view delegate:
func splitViewController(splitViewController: UISplitViewController, separateSecondaryViewControllerFromPrimaryViewController primaryViewController: UIViewController!) -> UIViewController? {
return (UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("detailView") as! UIViewController)
}
Once this is done, I no longer lose the navigation bar.